ranuts 0.2.0-alpha.1 → 0.4.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 (119) hide show
  1. package/CLAUDE.md +126 -24
  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/sw/index.d.ts +109 -0
  19. package/dist/src/sw/index.js +1 -0
  20. package/dist/src/utils/async.d.ts +81 -0
  21. package/dist/src/utils/audioRecorder.d.ts +1 -1
  22. package/dist/src/utils/behavior.d.ts +12 -3
  23. package/dist/src/utils/bom.d.ts +68 -178
  24. package/dist/src/utils/bridge.d.ts +153 -0
  25. package/dist/src/utils/canvas.d.ts +54 -0
  26. package/dist/src/utils/chain.d.ts +80 -0
  27. package/dist/src/utils/color.d.ts +76 -4
  28. package/dist/src/utils/compose.d.ts +1 -1
  29. package/dist/src/utils/console.d.ts +19 -1
  30. package/dist/src/utils/debounce.d.ts +27 -5
  31. package/dist/src/utils/device.d.ts +31 -3
  32. package/dist/src/utils/dom.d.ts +5 -84
  33. package/dist/src/utils/error.d.ts +18 -1
  34. package/dist/src/utils/event.d.ts +61 -0
  35. package/dist/src/utils/file.d.ts +35 -0
  36. package/dist/src/utils/i18n/index.js +1 -0
  37. package/dist/src/utils/i18n.d.ts +69 -0
  38. package/dist/src/utils/idb.d.ts +218 -0
  39. package/dist/src/utils/img.d.ts +60 -4
  40. package/dist/src/utils/index.d.ts +50 -16
  41. package/dist/src/utils/index.js +1 -1
  42. package/dist/src/utils/lang.d.ts +69 -0
  43. package/dist/src/utils/localePath.d.ts +62 -0
  44. package/dist/src/utils/memoize.d.ts +53 -5
  45. package/dist/src/utils/monitor.d.ts +55 -26
  46. package/dist/src/utils/number.d.ts +46 -9
  47. package/dist/src/utils/obj.d.ts +56 -31
  48. package/dist/src/utils/paginate.d.ts +73 -0
  49. package/dist/src/utils/prefetch.d.ts +81 -0
  50. package/dist/src/utils/queue.d.ts +53 -23
  51. package/dist/src/utils/report.d.ts +51 -3
  52. package/dist/src/utils/request.d.ts +26 -7
  53. package/dist/src/utils/script.d.ts +26 -4
  54. package/dist/src/utils/segment.d.ts +62 -0
  55. package/dist/src/utils/signal.d.ts +35 -3
  56. package/dist/src/utils/storage.d.ts +57 -0
  57. package/dist/src/utils/str.d.ts +112 -88
  58. package/dist/src/utils/style.d.ts +31 -0
  59. package/dist/src/utils/subscribe.d.ts +5 -5
  60. package/dist/src/utils/throttle.d.ts +26 -13
  61. package/dist/src/utils/time.d.ts +38 -6
  62. package/dist/src/utils/tween.d.ts +40 -0
  63. package/dist/src/utils/visual/application.d.ts +4 -4
  64. package/dist/src/utils/visual/enums.d.ts +4 -4
  65. package/dist/src/utils/visual/graphics/graphics.d.ts +25 -25
  66. package/dist/src/utils/visual/graphics/graphicsData.d.ts +1 -1
  67. package/dist/src/utils/visual/graphics/graphicsGeometry.d.ts +6 -6
  68. package/dist/src/utils/visual/index.js +1 -1
  69. package/dist/src/utils/visual/math/matrix.d.ts +8 -8
  70. package/dist/src/utils/visual/math/transform.d.ts +1 -1
  71. package/dist/src/utils/visual/render/batchRenderer.d.ts +20 -18
  72. package/dist/src/utils/visual/render/utils/batch/index.d.ts +13 -13
  73. package/dist/src/utils/visual/render/utils/float.d.ts +13 -13
  74. package/dist/src/utils/visual/render/utils/verticy.d.ts +3 -3
  75. package/dist/src/utils/visual/render/utils/webgl/initShader.d.ts +3 -2
  76. package/dist/src/utils/visual/render/utils/webgpu/shaders.d.ts +2 -2
  77. package/dist/src/utils/visual/render/webGPURenderer.d.ts +8 -8
  78. package/dist/src/utils/visual/vertex/container.d.ts +17 -16
  79. package/dist/src/utils/worker.d.ts +125 -0
  80. package/dist/src/utils/zip.d.ts +162 -0
  81. package/dist/src/vnode/index.d.ts +1 -1
  82. package/dist/src/vnode/index.js +1 -1
  83. package/dist/src/vnode/is.d.ts +4 -0
  84. package/dist/test/canvas.test.d.ts +1 -0
  85. package/dist/test/color.test.d.ts +1 -0
  86. package/dist/test/sw.test.d.ts +1 -0
  87. package/dist/test/tween.test.d.ts +1 -0
  88. package/dist/test/utils/async.test.d.ts +1 -0
  89. package/dist/test/utils/file-read.test.d.ts +1 -0
  90. package/dist/test/utils/format.test.d.ts +1 -0
  91. package/dist/test/utils/idb-collection.test.d.ts +1 -0
  92. package/dist/test/utils/idb.test.d.ts +1 -0
  93. package/dist/test/utils/instrumentation.test.d.ts +1 -0
  94. package/dist/test/utils/lang.test.d.ts +1 -0
  95. package/dist/test/utils/locale-path.test.d.ts +1 -0
  96. package/dist/test/utils/media-query.test.d.ts +1 -0
  97. package/dist/test/utils/number-parse.test.d.ts +1 -0
  98. package/dist/test/utils/paginate.test.d.ts +1 -0
  99. package/dist/test/utils/prefetch.test.d.ts +1 -0
  100. package/dist/test/utils/query-storage.test.d.ts +1 -0
  101. package/dist/test/utils/queue.test.d.ts +1 -0
  102. package/dist/test/utils/report-config.test.d.ts +1 -0
  103. package/dist/test/utils/report-image.test.d.ts +1 -0
  104. package/dist/test/utils/segment.test.d.ts +1 -0
  105. package/dist/test/utils/signal-once.test.d.ts +1 -0
  106. package/dist/test/utils/single-flight.test.d.ts +1 -0
  107. package/dist/test/utils/timing.test.d.ts +1 -0
  108. package/dist/test/utils/worker-client.test.d.ts +1 -0
  109. package/dist/test/utils/worker-serve.test.d.ts +1 -0
  110. package/dist/test/utils/zip.test.d.ts +1 -0
  111. package/dist/umd/index.umd.cjs +1 -1
  112. package/dist/umd/node/node.umd.cjs +1 -1
  113. package/dist/umd/utils/utils.umd.cjs +1 -1
  114. package/dist/utils-8TVtLBjA.js +1 -0
  115. package/docs/API.md +341 -147
  116. package/package.json +13 -6
  117. package/dist/src/vnode/chainDom.d.ts +0 -47
  118. package/dist/subscribe-CINWsor3.js +0 -1
  119. package/dist/utils-_OxsVZmz.js +0 -1
package/docs/API.md CHANGED
@@ -8,204 +8,365 @@ 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
+ **352 exports** across 6 entry points. Generated at 2026-07-25T13:06:04.393Z.
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_ · 271 exports
16
+ - [`ranuts/sw`](#ranutssw) — Service Worker caching strategies and the precache protocol · _service worker only_ · 9 exports
17
+ - [`ranuts/node`](#ranutsnode) — Node server utilities (fs / http / ws / middleware) · _node only_ · 26 exports
18
+ - [`ranuts/visual`](#ranutsvisual) — 2D rendering engine (Canvas / WebGL / WebGPU) · _browser only_ · 12 exports
19
+ - [`ranuts/i18n`](#ranutsi18n) — Framework-agnostic i18n engine (also re-exported from ranuts/utils) · _browser + node_ · 8 exports
20
+ - [`ranuts/vnode`](#ranutsvnode) — Snabbdom-style virtual DOM · _browser_ · 26 exports
19
21
 
20
22
  ## `ranuts/utils`
21
23
 
22
- 浏览器 / 通用工具函数 · runtime: **browser + node** · source: `src/utils/index.ts`
24
+ Browser and general-purpose utilities · runtime: **browser + node** · source: `src/utils/index.ts`
23
25
 
24
26
  ```ts
25
- import {} from /* … */ 'ranuts/utils';
27
+ import { /* … */ } from 'ranuts/utils';
26
28
  ```
27
29
 
28
30
  ### Functions
29
31
 
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`
32
+ - `acceptPortBridge({ targetOrigin, name, }?: AcceptPortBridgeOptions) => Promise<PortBridge>` — Acceptor: wait for the port the initiator hands over and return the bridge once the
33
+ - `addClassToElement(element: Element, addClass: string) => void` — Add a class to an element
34
+ - `addNumSym(value: string | number, flag?: string | number) => string`
35
+ - `adoptSheetText(shadowRoot: ShadowRoot, cssText: string, marker?: string) => void` — Inject dynamic styles supplied at runtime (a component's `sheet` property, say).
36
+ - `adoptStyles(shadowRoot: ShadowRoot, cssText: string, marker?: string) => void` Inject a component's static styles into a shadow root.
37
+ - `appendUrl(url: string, params?: Record<string, string>) => string` — Turn an object into a query string and append it to a URL
38
+ - `arrayBufferToString(buffer: ArrayBuffer | Uint8Array) => string` — Decode bytes into a string using the sniffed encoding. Required when reading
39
+ - `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.
40
+ - `buildOffsets(lengths: readonly number[]) => number[]` — The global start offset of every chunk in the concatenated coordinate
41
+ - `canvasVendor() => string | null`
42
+ - `changeHumpToLowerCase(str: string) => string`
43
+ - `checkEncoding(uint8Array: Uint8Array) => string`
44
+ - `clearBr(str?: string) => string` Strip whitespace, line breaks and HTML tags out of a string
45
+ - `clearStr(str: string, options?: ClearStrOption) => string` — Trim surrounding whitespace, percent-decode, and drop surrounding quotes
46
+ - `cloneDeep<T>(value: T, cloneMap?: WeakMap<object, any>) => T` Deep clone, covering the complex built-in types and circular references.
47
+ - `componentToHex(c: string | number) => string`
48
+ - `compose<T>(middleware: Array<Middleware<T>>) => ComposedMiddleware<T>` — Run a chain of async functions as if it were sequential
49
+ - `connection() => number | undefined` — Current network status: type, throughput, and whether the connection changed
50
+ - `convertImageToBase64(file: File) => Promise<convertImageToBase64Return>` Convert an image to base64
51
+ - `crc32(data: Uint8Array) => number` — CRC32 checksum (IEEE 802.3 polynomial), the one ZIP stores per entry.
52
+ - `create(tagName: string, options?: ElementCreationOptions) => Chain`
53
+ - `createData(params?: Record<string, unknown>) => Record<string, unknown>` — Build the standard envelope that accompanies a report — page URL, referrer,
54
+ - `createDocumentFragment(list: Element[]) => DocumentFragment | undefined` — Create a DocumentFragment
55
+ - `createHandoff<T>({ dbName, storeName, key }: HandoffOptions) => Handoff<T>`A one-shot value handoff between two pages of the same origin, backed by
56
+ - `createI18n(config?: I18nConfig) => I18nCore` — Create and register the global i18n singleton.
57
+ - `createLocalePath(config: LocalePathConfig) => LocalePath` Create the set of locale path conversion functions.
58
+ - `createObjectURL(src: Blob | ArrayBuffer | Response) => Promise<string>`
59
+ - `createPortBridge(port: MessagePort) => PortBridge` — Build a bridge on any MessagePort (a Web Worker, a SharedWorker, or a port from a completed handshake).
60
+ - `createSignal<T = unknown>(value: T, options?: SignalOptions<T>) => [() => T, (newValue: T) => void]` — Create a minimal signal with optional event broadcasting, returned as
61
+ - `createStore<T>(prefix?: string) => JsonStore<T>` — A prefixed, JSON-serialising view over localStorage.
62
+ - `createZip(files: ReadonlyArray<{ name: string; data: Uint8Array | string; }>) => Uint8Array` — Build a ZIP from scratch, every entry STORED. No compression, so this is
63
+ - `currentDevice() => CurrentDevice`
64
+ - `cutRound(img: ImgSource, radius: number) => ImgSource` — Round an image's corners, returning an offscreen canvas.
65
+ - `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
66
+ - `deferred<T = void>() => Deferred<T>` — A promise plus its `resolve` / `reject`, for the case where the thing that
67
+ - `delay(ms: number) => Promise<void>` — Resolve after `ms` milliseconds. Uses the bare `setTimeout`, so it works in
68
+ - `detectLanguage(text: string, sampleSize?: number) => TextLanguage` — Decide a text's primary language from the ratio of CJK to Latin characters.
69
+ - `durationHandler<T, U>(handler: (...args: T[]) => U, ...params: T[]) => ((a: number) => Promise<U>)` — Run a function repeatedly at a fixed interval
70
+ - `encodeUrl(url: string) => string` — Encode a URL to a percent-encoded form, excluding already-encoded sequences.
71
+ - `escapeHtml(string?: string | number | null) => string`
72
+ - `fanShapedByArc(ctx: CanvasRenderingContext2D, maxRadius: number, start: number, end: number, gutter: number) => void` — Trace a pie slice with arc(), including the gutter between slices.
73
+ - `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
74
+ - `formatDate(value?: number | string | Date, pattern?: string) => string` — Format a date with a token pattern. Accepts a timestamp, a date string, a
75
+ - `formatJson(value: string | object, onError?: (error: Error) => void, indent?: number) => string` — Pretty-print JSON. Accepts an object or a JSON string (single quotes are
76
+ - `getAllQueryString(url?: string) => Record<string, string>` Parse a URL's query string into an object. Defaults to the current
77
+ - `getAngle(deg: number) => number` — Degrees to radians
78
+ - `getArcPointerByDeg(deg: number, r: number) => [number, number]` — The point on a circle at a given angle
79
+ - `getCookie(objName: string) => string` Read a named cookie
80
+ - `getCookieByName(name: string) => string`
81
+ - `getExtensions(mimeType: string) => string[]` Get file extensions from MIME type
82
+ - `getFrame(n?: number) => Promise<number>` Frames per millisecond; multiply by 1000 for frames per second
83
+ - `getImage(src: string) => Promise<ImgSource>` — Load an image by path, resolving once it has decoded.
84
+ - `getLinearGradient(ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, background: string) => CanvasGradient` Translate a CSS `linear-gradient(...)` string into a Canvas CanvasGradient.
85
+ - `getMatchingSentences(text: string, searchValue: string) => string[]` — Collect the complete sentences of a text that contain the search term, keeping only the
86
+ - `getMatrix(radius: number, sigma?: number) => number[]` — Build a 2D Gaussian weight matrix, normalised so the weights sum to 1.
87
+ - `getMime(ext: string) => string | undefined`
88
+ - `getPerformance() => BasicType | undefined`
89
+ - `getPixelRatio(context: CanvasRenderingContext2D & Partial<Context>) => number` — Get the device pixel ratio
90
+ - `getQuery(url?: string) => Record<string, string>` — Alias of [`getAllQueryString`](#getallquerystring). The two used to be
91
+ - `getRandomString(len?: number) => string`
92
+ - `getReportUrl() => string` — The currently configured reporting endpoint, or `''` when none was set
93
+ - `getStatus(code?: number | string) => number | string | undefined` — Get the status code.
94
+ - `getTangentByPointer(x: number, y: number) => Array<number>` — The tangent line at a point on a circle
95
+ - `getWindow() => ClientRatio` — Get the viewport size across browsers
96
+ - `handleConsole(hooks?: (...args: unknown[]) => void) => (() => void)` — Tap into `console` so every call also reaches your hook, while still printing
97
+ - `handleError(hooks?: (error: ErrorPayload) => void) => (() => void)` — Listen for uncaught errors and unhandled promise rejections, in the capture
98
+ - `handleFetchHook(options?: Partial<Options>) => (() => void)` Instrument `window.fetch` so every request, response and failure reaches your
99
+ - `handleXhrHook(options?: Partial<Options>) => (() => void)` Instrument `XMLHttpRequest` (`open` / `send`) so requests, responses and
100
+ - `hexToAlpha(aa: string) => number` — A two-digit hex alpha channel (`ff` / `80` / `00`) to a 0–100 percentage.
101
+ - `hexToHsb(hex: string) => number[] | null` — `#rrggbb` / `#rgb` to `[h, s, b]`; null when the hex is invalid.
102
+ - `hexToHsv(hex: string) => number[] | null`
103
+ - `hexToRgb(hex: string) => Array<number> | null` — `#rrggbb` / `#rgb` (with or without the `#`) to `[r, g, b]`; null when it cannot be parsed.
104
+ - `hsbToHsl(h: number, s: number, b: number) => number[]`
105
+ - `hsbToRgb(h: number, s: number, v: number) => number[]`
106
+ - `hslToHsb(h: number, s: number, l: number) => number[]` — `[h, s, l]` to `[h, s, b]`
107
+ - `hslToHsv(h: number, s: number, l: number) => number[]`
108
+ - `hslToRgb(h: number | string | number[], s: number | string, l: number | string) => Array<number>`
109
+ - `hsvToHsl(h: number, s: number, b: number) => number[]`
110
+ - `hsvToRgb(h: number, s: number, v: number) => number[]`
111
+ - `hue2rgb(p: number, q: number, t: number) => number`
112
+ - `imageRequest(url?: string) => Promise<number>` — Request an image (used to time the network)
113
+ - `indexForOffset(offsets: readonly number[], offset: number) => number` — Binary-search which chunk a global offset falls into — the last index
114
+ - `inflateRaw(data: Uint8Array) => Promise<Uint8Array>` Decompress raw DEFLATE bytes (no zlib or gzip wrapper) — the form ZIP
115
+ - `isBangDevice() => boolean`
116
+ - `isEqual(value: any, other: any, seen?: Map<any, any>) => boolean` — Deep-compare two values.
117
+ - `isImageSize(file: File, width?: number, height?: number) => Promise<boolean>` — Check an image's dimensions against a given width / height. When both are
118
+ - `isInIframe() => boolean` — Whether this page is running inside an iframe. Returns false under SSR.
119
+ - `isMobile() => boolean` — Whether this is a mobile device
120
+ - `isSafari() => boolean | undefined | string`
121
+ - `isString(obj: unknown) => boolean`
122
+ - `isUrlCached(url: string) => Promise<boolean>` Whether a URL is already in CacheStorage. When probing a group of files,
123
+ - `isWeiXin() => boolean` Whether this is the WeChat in-app browser
124
+ - `loadScript({ type, content }: LoadScriptOptions) => Promise<{ success: boolean; }>` Inject one script dynamically, de-duplicated by content.
125
+ - `localStorageGetItem(name: string) => string` Read a string from localStorage, or `''` when missing or unavailable.
126
+ - `localStorageRemoveItem(name: string) => void` — Remove a key from localStorage. Silently does nothing when storage is unavailable.
127
+ - `localStorageSetItem(name: string, value: string) => void` Write a string to localStorage. Silently does nothing when storage is
128
+ - `matchMediaQuery(query: string) => boolean` Read whether a media query currently matches, synchronously. Returns false under SSR.
129
+ - `mathjs(a: number, type: string, b: number) => ComputeNumberResult`
130
+ - `md5(str: string) => string` — MD5 hash function implementation
131
+ - `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
132
+ - `merge(a: Obj, b?: Obj) => Obj` — Merge objects
133
+ - `mergeExports(obj: Record<string, string>, exports: Record<string, string>) => Record<string, string>` — Copy an exports object onto `obj`, then freeze it
134
+ - `navigatorLanguage() => TextLanguage` — Map the browser UI language into the same buckets (the default when there is
135
+ - `networkAllowsDownload(options?: NetworkAllowanceOptions) => boolean` — Whether the current network and user settings allow proactively downloading
136
+ - `networkSpeed(options: Options) => Promise<ReturnType>` — Measure the network's ping by timing requests
137
+ - `noop() => void`
138
+ - `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
139
+ - `opacity(img: ImgSource, opacity: number) => ImgSource` — Apply an overall opacity to an image, returning an offscreen canvas.
140
+ - `openPortBridge({ targetWindow, targetOrigin, name, }: OpenPortBridgeOptions) => PortBridge` — Initiator: create a MessageChannel, hand one port to the target window and keep the other.
141
+ - `paginateText(text: string, box: TextBox, metrics: TextGridMetrics, options?: PaginateOptions) => PaginateResult` — Cut text into pages that fit `box`, given the type metrics.
142
+ - `parseChineseNumber(value: string) => number | null` — Chinese numerals to Arabic, covering 「十五」「二十三」「一百零三」「一千零一」「三万」.
143
+ - `parseEnglishNumber(value: string) => number | null` — English ordinals to numbers, tried in order: Arabic digits, number words
144
+ - `parseRomanNumber(value: string) => number | null` — Roman numerals to Arabic (either case, handling subtractive forms such as IV / IX). Returns null for invalid input.
145
+ - `performanceTime() => number` — Current timestamp
146
+ - `perToNum(str?: string) => number` — Convert a percentage string into a number
147
+ - `prefetchUrl(url: string) => Promise<void>` — Pull a single URL into the cache; skipped when already cached. Failures are
148
+ - `prefetchUrls(urls: string[], options?: PrefetchOptions) => Promise<void>` — Prefetch a group of URLs, **serially** — prefetching is background work, and
149
+ - `prefetchWhenIdle(urls: string[], options?: WhenIdleOptions & NetworkAllowanceOptions & PrefetchOptions) => (() => void)` — Prefetch a group of URLs while idle, subject to `networkAllowsDownload`.
150
+ - `queryFlag(key: string, url?: string) => boolean` — Read a query parameter as a boolean flag. True for `?k`, `?k=`, `?k=1` and
151
+ - `querystring(data?: {}) => string` — Serialise an object into a URL query string
152
+ - `randomColor() => Color`
153
+ - `randomString(len?: number) => string`
154
+ - `range(num: number, min?: number, max?: number) => number` — Clamp a value between a minimum and a maximum
155
+ - `readFileAsArrayBuffer(blob: Blob) => Promise<ArrayBuffer>` — Read a File / Blob as an ArrayBuffer
156
+ - `readFileAsDataURL(blob: Blob) => Promise<string>` — Read a File / Blob as a data: URL (image previews and the like)
157
+ - `readFileAsText(blob: Blob, encoding?: string) => Promise<string>` — Read a File / Blob as text
158
+ - `readFileAsUint8Array(blob: Blob) => Promise<Uint8Array<ArrayBuffer>>` — Read a File / Blob as a Uint8Array (pair with checkEncoding / arrayBufferToString for encoding sniffing)
159
+ - `readZipEntries(bytes: Uint8Array) => ZipEntry[]` — Read an archive's central directory. Returns `[]` for anything that is not
160
+ - `readZipEntry(bytes: Uint8Array, entry: string | ZipEntry) => Promise<Uint8Array | null>` — Extract one entry's decompressed bytes. Resolves `null` when the entry is
161
+ - `removeClassToElement(element: Element, removeClass: string) => void` — Remove a class from an element
162
+ - `removeGhosting(event: DragEvent) => void` — Remove the drag event's ghost image
163
+ - `replaceOld(source: any, name: string, replacement: (...args: unknown[]) => unknown, isForced?: boolean) => () => void` — Replace a property on an object, wrapping whatever was there before.
164
+ - `report({ url, type, payload }: BeaconPayload) => boolean` — Send a telemetry beacon. Prefers `navigator.sendBeacon` (does not block
165
+ - `requestUrlToBuffer(src: string, options: Partial<RequestUrlToArraybufferOption>) => Promise<requestUrlToArraybufferReturn>` — Fetch a URL as an ArrayBuffer
166
+ - `resolveLocale(options: ResolveLocaleOptions) => string` — Resolve which of your supported locales to use, from the usual chain:
167
+ - `retain(callback?: () => void) => void` — Override the browser's back-button behaviour
168
+ - `rewriteZip(bytes: Uint8Array, options?: RewriteZipOptions) => Promise<Uint8Array>` — Rebuild an archive with some entries replaced and/or new entries appended.
169
+ - `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
170
+ - `rgbaToHex(r: number, g: number, b: number, a: number) => string` — Composite a translucent colour over white and return it as a 6-digit hex.
171
+ - `rgbaToRgb(r: number, g: number, b: number, a: number) => number[]` — Composite a translucent colour **over white**, giving the equivalent opaque rgb.
172
+ - `rgbToHex(r: string | number | Array<string | number>, g?: string | number, b?: string | number) => string`
173
+ - `rgbToHsb(r: number, g: number, b: number) => number[]`
174
+ - `rgbToHsl(r: number | number[], g?: number, b?: number) => Array<number>`
175
+ - `rgbToHsv(r: number, g: number, b: number) => number[]` — Alias of `rgbToHsb` — HSV and HSB are two names for the same colour space.
176
+ - `roundRectByArc(ctx: CanvasRenderingContext2D, ...[x, y, w, h, r]: number[]) => void` — Trace a rounded rectangle with arc(). A corner radius larger than half the
177
+ - `scriptOnLoad(urls: string[], append?: HTMLElement, callback?: () => void) => Promise<void>` — Insert script/link tags dynamically
178
+ - `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
179
+ - `serveWorker<Req extends WorkerRequestBase, Res extends object = object, Progress = unknown>(handler: (request: Req, context: WorkerHandlerContext<Progress>) =>…` — Serve requests inside a Web Worker, mirroring {@link WorkerClient} on the
180
+ - `setAttributeByGlobal(name: string, value: unknown) => void` — Define a property on the global object
181
+ - `setFontSize2html(designWidth?: number) => void` — Set the root font size from the design mock's width
182
+ - `setMime(ext: string, mimeType: string) => Map<string, string>`
183
+ - `setReportUrl(next: ReportConfig | string) => void` — Configure the default reporting endpoint (and optionally the cookie holding
184
+ - `singleFlight<T>(fn: () => Promise<T>) => SingleFlight<T>` — The async flavour of "run once": concurrent callers share one in-flight
185
+ - `str2Xml(xmlStr: string, format?: DOMParserSupportedType) => HTMLElement | undefined` — Parse a string into XML using the given MIME type
186
+ - `strParse(str?: string, sep?: string | RegExp, eq?: string | RegExp) => Record<string, string>` — Parse a delimited string into an object, e.g.
187
+ - `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
188
+ - `timeFormat(time: number) => string` — Format a number of seconds as a colon-separated duration
189
+ - `timestampToTime(timestamp?: number | string) => Date & { format?: Function; }` — Turn a timestamp into a `Date` carrying a `format` method.
190
+ - `toFullWidth(value: string) => string` — Convert half-width characters to full-width (the inverse of `toHalfWidth`)
191
+ - `toHalfWidth(value: string) => string` — Convert full-width characters to half-width (digits, letters, punctuation and
192
+ - `toString(value: string | number) => string`
193
+ - `transformNumber(value: string, locale?: string, precision?: number, fixed?: number) => string`
194
+ - `transformText(content: string | ArrayBuffer) => TransformText | undefined`
195
+ - `useI18n() => I18nCore | null` — Return the active global i18n instance, or null if none was created.
196
+ - `watchMediaQuery(query: string, callback: (matches: boolean) => void) => (() => void)` — Watch a media query. The callback **fires once synchronously with the
197
+ - `webglVendor() => { vendor: string; renderer: string; } | null`
198
+ - `whenIdle(callback: () => void, options?: WhenIdleOptions) => (() => void)` — Run a callback while the browser is idle, falling back to setTimeout where
199
+ - `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
200
+ - `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
201
+ - `zipHasEntry(bytes: Uint8Array, name: string) => boolean` — Whether the archive contains an entry with exactly this name. Cheaper than
128
202
 
129
203
  ### Classes
130
204
 
131
- - `class AudioRecorder` — 录音
205
+ - `class AudioRecorder` — Record audio
132
206
  - `class BridgeManager`
133
- - `class Chain` — 链式调用的 dom 操作
207
+ - `class Chain` — Chainable DOM operations
134
208
  - `class Color`
135
209
  - `class ColorScheme`
210
+ - `class EventManager` — EventManager — a scoped listener registry built on AbortController.
136
211
  - `class Hsl`
137
212
  - `class Hsla`
138
- - `class Mathjs` — 数字运算(主要用于小数点精度问题)
139
- - `class Monitor`
140
- - `class PostMessageBridge` — Bridge 注册事件,供 client 消费
141
- - `class QuestQueue`
213
+ - `class I18nCore`
214
+ - `class Mathjs` — Arithmetic that works around floating-point precision.
215
+ - `class Monitor` — Front-end telemetry: page-load performance, clicks, errors, fetch/XHR traffic
216
+ - `class PostMessageBridge` — Bridge registration event, consumed by the client
217
+ - `class QuestQueue` — An async task queue with limited concurrency. At most `simultaneous` tasks
142
218
  - `class Rgb`
143
219
  - `class Rgba`
144
220
  - `class SyncHook`
221
+ - `class TimeoutError`
145
222
  - `class TOTP`
223
+ - `class WebDB` — A Promise wrapper over IndexedDB. The native API is event-callback and
224
+ - `class WorkerClient` — A worker client with request ids. The request type `Req` is defined by the
146
225
 
147
226
  ### Interfaces
148
227
 
149
228
  - `interface AcceptPortBridgeOptions`
229
+ - `interface BeaconPayload`
150
230
  - `interface BridgeManagerOptions`
151
231
  - `interface BroadcastPayload`
152
232
  - `interface CallToPayload`
233
+ - `interface Debounced`
234
+ - `interface Deferred` — Promise primitives that JavaScript does not ship: an externally settled promise and a
235
+ - `interface Handoff`
236
+ - `interface HandoffOptions`
237
+ - `interface I18nConfig`
238
+ - `interface IDBCollection` — A store name bound once, values unwrapped, failures folded into the empty case
239
+ - `interface IDBResult` — The uniform result shape of every IndexedDB operation. Every method
240
+ - `interface IDBStoreSchema` — Declarative schema for object stores. `openDataBase` creates the missing
241
+ - `interface JsonStore`
242
+ - `interface LoadScriptOptions`
243
+ - `interface LocalePath`
244
+ - `interface LocalePathConfig`
245
+ - `interface LocaleRoute` — URL maths for a multi-language site (pure functions, no global state, no DOM).
153
246
  - `interface MessageData`
154
247
  - `interface MessageHandler`
248
+ - `interface NetworkAllowanceOptions`
249
+ - `interface OffsetRange` — An annotation in global coordinates: the half-open interval `[start, end)` plus any payload
155
250
  - `interface OpenPortBridgeOptions`
251
+ - `interface PaginateOptions`
252
+ - `interface PaginateResult`
156
253
  - `interface PendingRequest`
157
- - `interface PortBridge` — 基于 MessagePort 的点对点桥接(方案 B,作为新 API 提供)。
254
+ - `interface PortBridge` — A point-to-point bridge over MessagePort.
255
+ - `interface PrefetchOptions`
256
+ - `interface ReportConfig`
257
+ - `interface ResolveLocaleOptions`
258
+ - `interface RewriteZipOptions`
259
+ - `interface Segment` — One piece of the split result: `value === null` marks a plain span covered by no range
260
+ - `interface ServeWorkerOptions`
261
+ - `interface SingleFlight`
262
+ - `interface SpeedType` — The ease-in / ease-out pair of one easing family
263
+ - `interface TextBox` — The box each page must fit into, in px.
264
+ - `interface TextGridMetrics`
265
+ - `interface TextPage`
266
+ - `interface Throttled`
158
267
  - `interface TransformText`
268
+ - `interface WebDBOptions`
269
+ - `interface WhenIdleOptions`
270
+ - `interface WorkerClientOptions`
271
+ - `interface WorkerHandlerContext` — Handed to the handler so it can stream progress for the request it is currently serving
272
+ - `interface WorkerRequestBase` — A request always carries the id the client stamped on it
273
+ - `interface WorkerResponseBase` — A response must at least echo the request id so the two can be paired
274
+ - `interface ZipEntry` — One entry as described by the archive's central directory.
159
275
 
160
276
  ### Types
161
277
 
162
278
  - `type CurrentDevice`
279
+ - `type EasingFn` — One easing function: (elapsed, from, delta, duration) => current value
280
+ - `type ImgSource` — A bitmap container usable both as a drawImage source and as a render target
281
+ - `type LocaleChangeHandler`
282
+ - `type LocaleMessages`
283
+ - `type MessageDict`
284
+ - `type TextLanguage` — Coarse language bucket: Chinese / English / other only
285
+ - `type TranslateParams`
163
286
 
164
287
  ### Constants
165
288
 
289
+ - `const ADOPTED_SHEET_MARKER: "data-adopted-sheet"`
290
+ - `const ADOPTED_STYLE_MARKER: "data-adopted-style"` — Default marker attribute on the `<style>` fallback, identifying styles this module injected
166
291
  - `const BRIDGE_MARKER: "__ranuts_bridge__"`
167
292
  - `const bridgeManager: BridgeManager`
293
+ - `const circ: SpeedType`
168
294
  - `const Client: { connect: ({ id, targetWindow, targetOrigin, channel, }: BridgeManagerOptions) => { bridge: PostMessageBridge; id: string; }; remove: (id: strin…`
295
+ - `const cubic: SpeedType`
169
296
  - `const DEFAULT_CHANNEL: "default"`
297
+ - `const expo: SpeedType`
170
298
  - `const FMT: Record<string, string[]>`
299
+ - `const HEX_COLOR_REGEX: RegExp` — `#rgb` / `#rrggbb` (the `#` is required)
171
300
  - `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…` — 消息编解码工具
301
+ - `const MessageCodec: { encode(data: any): string; decode<T = any>(encodedStr: string): T | null; encodeFile(file: File): Promise<string>; decodeFile(encoded: st…` — Message codec.
173
302
  - `const MimeType: Map<string, string>`
303
+ - `const MOBILE_MEDIA_QUERY: "(max-width: 768px)"` — Viewport breakpoint, matching where the mobile layout takes over
174
304
  - `const Platform: { init: <T = unknown, R = unknown>(events: Record<string, MessageHandler<T, R>>) => { destroy: () => void; }; }`
305
+ - `const quad: SpeedType`
306
+ - `const quart: SpeedType`
307
+ - `const quint: SpeedType`
308
+ - `const RGB_REGEX: RegExp` — `rgb(r,g,b)`, no spaces — strip whitespace before matching
309
+ - `const RGBA_REGEX: RegExp` — `rgba(r,g,b,a)`, no spaces — strip whitespace before matching
310
+ - `const sine: SpeedType`
175
311
  - `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`
312
+ - `const subscribers: SyncHook` — Global event bus: a signal carrying a `subscriber` broadcasts through it on change
313
+ - `const ZIP_DEFLATE: 8`
314
+ - `const ZIP_STORED: 0` — Compression methods this module understands.
315
+
316
+ ## `ranuts/sw`
317
+
318
+ Service Worker caching strategies and the precache protocol · runtime: **service worker only** · source: `src/sw/index.ts`
319
+
320
+ ```ts
321
+ import { /* … */ } from 'ranuts/sw';
322
+ ```
323
+
324
+ ### Functions
325
+
326
+ - `cacheFirst(request: Request, options: CacheStrategyOptions) => Promise<Response>` — Cache-first: serve the stored copy when there is one, otherwise fetch and
327
+ - `dropCachesExcept(keep: readonly string[], options?: { scope?: SWScope; }) => Promise<string[]>` — Delete every cache except the ones named. Call it on `activate` so a new
328
+ - `networkFirst(request: Request, options: CacheStrategyOptions) => Promise<Response>` — Network-first: go to the network, store what comes back, and fall back to the
329
+ - `precache(cacheName: string, urls: readonly string[], options?: { scope?: SWScope; }) => Promise<void>` — Fill a cache with a list of URLs, skipping what is already there. Failures are
330
+ - `servePrecache(options: ServePrecacheOptions) => (() => void)` — Answer the precache messages that `prefetchUrls({ serviceWorkerMessage })`
331
+
332
+ ### Interfaces
333
+
334
+ - `interface CacheStrategyOptions`
335
+ - `interface PrecacheMessageEvent` — The bit of `ExtendableMessageEvent` used here, declared locally rather than pulled from
336
+ - `interface ServePrecacheOptions`
337
+ - `interface SWScope` — Minimal view of the SW global the helpers touch, so they can be unit-tested with a stub.
177
338
 
178
339
  ## `ranuts/node`
179
340
 
180
- Node 服务端工具(fs / http / ws / 中间件) · runtime: **node only** · source: `src/node/index.ts`
341
+ Node server utilities (fs / http / ws / middleware) · runtime: **node only** · source: `src/node/index.ts`
181
342
 
182
343
  ```ts
183
- import {} from /* … */ 'ranuts/node';
344
+ import { /* … */ } from 'ranuts/node';
184
345
  ```
185
346
 
186
347
  ### Functions
187
348
 
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
349
+ - `appendFile(path: string, content: string) => Promise<Ranuts.Identification>` — Append content to an existing file
350
+ - `bodyMiddleware(options?: Partial<ServerBody>) => MiddlewareFunction`
351
+ - `connect(connectMiddleware: ConnectMiddleware) => MiddlewareFunction`
352
+ - `get({ url }: Request) => Promise<Response>`
353
+ - `getIPAdress() => string | undefined`
354
+ - `default(req: Req) => ParseUrl | undefined` — Parse an IncomingMessage's request URL; the return type is always ParseUrl
355
+ - `prompt({ message, stream, defaultResponse }: PromptOption) => Promise<boolean>`
356
+ - `queryFileInfo(path: string) => Promise<Ranuts.Identification>` — Stat a file — typically to tell a file from a directory via data.isDirectory()
357
+ - `readDir(options: Options) => Array<string>`
358
+ - `readFile(path: string, format?: BufferEncoding) => FilePromiseResult` — Read a file, returning a status code and the content on success
359
+ - `readStream(option: ReadOption) => ReadStream`
360
+ - `runCommand(command: string, args: string[]) => Promise<void>`
361
+ - `startTask() => symbol`
362
+ - `staticMiddleware(option?: Partial<Option>) => MiddlewareFunction`
363
+ - `taskEnd(symbol: symbol) => number | bigint`
364
+ - `traverse(dir: string, callback: Caller, pre?: string) => Promise<any>` — Walk every directory recursively, running a function for each file found
365
+ - `traverseSync(dir: string, callback: Caller, pre?: string) => void` — Synchronous: walk every directory recursively, running a function for each file found
366
+ - `watchFile(path: string, interval?: number) => Promise<Ranuts.Identification>` — Watch a file for changes and report its status
367
+ - `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
368
+ - `writeStream(option: WriteOption) => WriteStream`
369
+ - `WSS(this: any, server: http.Server) => void` — Create a WebSocket Server
209
370
 
210
371
  ### Classes
211
372
 
@@ -218,7 +379,7 @@ import {} from /* … */ 'ranuts/node';
218
379
 
219
380
  ### Constants
220
381
 
221
- - `const isColorSupported: any`
382
+ - `const isColorSupported: boolean`
222
383
 
223
384
  ### Other
224
385
 
@@ -226,10 +387,10 @@ import {} from /* … */ 'ranuts/node';
226
387
 
227
388
  ## `ranuts/visual`
228
389
 
229
- 2D 渲染引擎(Canvas / WebGL / WebGPU · runtime: **browser only** · source: `src/utils/visual/index.ts`
390
+ 2D rendering engine (Canvas / WebGL / WebGPU) · runtime: **browser only** · source: `src/utils/visual/index.ts`
230
391
 
231
392
  ```ts
232
- import {} from /* … */ 'ranuts/visual';
393
+ import { /* … */ } from 'ranuts/visual';
233
394
  ```
234
395
 
235
396
  ### Classes
@@ -256,25 +417,53 @@ import {} from /* … */ 'ranuts/visual';
256
417
  - `const BYTES_PER_VERTEX: 12`
257
418
  - `const MAX_VERTEX_COUNT: 65536`
258
419
 
420
+ ## `ranuts/i18n`
421
+
422
+ Framework-agnostic i18n engine (also re-exported from ranuts/utils) · runtime: **browser + node** · source: `src/utils/i18n.ts`
423
+
424
+ ```ts
425
+ import { /* … */ } from 'ranuts/i18n';
426
+ ```
427
+
428
+ ### Functions
429
+
430
+ - `createI18n(config?: I18nConfig) => I18nCore` — Create and register the global i18n singleton.
431
+ - `useI18n() => I18nCore | null` — Return the active global i18n instance, or null if none was created.
432
+
433
+ ### Classes
434
+
435
+ - `class I18nCore`
436
+
437
+ ### Interfaces
438
+
439
+ - `interface I18nConfig`
440
+
441
+ ### Types
442
+
443
+ - `type LocaleChangeHandler`
444
+ - `type LocaleMessages`
445
+ - `type MessageDict`
446
+ - `type TranslateParams`
447
+
259
448
  ## `ranuts/vnode`
260
449
 
261
- Snabbdom 风格虚拟 DOM · runtime: **browser** · source: `src/vnode/index.ts`
450
+ Snabbdom-style virtual DOM · runtime: **browser** · source: `src/vnode/index.ts`
262
451
 
263
452
  ```ts
264
- import {} from /* … */ 'ranuts/vnode';
453
+ import { /* … */ } from 'ranuts/vnode';
265
454
  ```
266
455
 
267
456
  ### Functions
268
457
 
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`
458
+ - `addNS(data: VNodeData, children: Array<VNode | string | number> | undefined, sel: string | undefined) => void`
459
+ - `create(tagName: string, options?: ElementCreationOptions) => Chain`
460
+ - `h{ (sel: string): VNode; (sel: string, data: VNodeData | null): VNode; (sel: string, children: VNodeChildren): VNode; (sel: string, data: VNodeData | null, chi… (+3 overloads)`
461
+ - `init() => (oldVnode: VNode | Element, vnode: VNode) => VNode`
273
462
  - `vnode(sel: string | undefined, data: any | undefined, children: Array<VNode | string | number> | undefined, text: string | number | undefined, elm: Element | T…`
274
463
 
275
464
  ### Classes
276
465
 
277
- - `class Chain` — 链式调用的 dom 操作
466
+ - `class Chain` — Chainable DOM operations
278
467
 
279
468
  ### Interfaces
280
469
 
@@ -303,3 +492,8 @@ import {} from /* … */ 'ranuts/vnode';
303
492
  - `const modules: Modules`
304
493
  - `const propsModule: { create: (oldVnode: VNode, vnode: VNode) => void; update: (oldVnode: VNode, vnode: VNode) => void; }`
305
494
  - `const styleModule: { pre: () => void; create: (oldVnode: VNode, vnode: VNode) => void; update: (oldVnode: VNode, vnode: VNode) => void; destroy: (vnode: VNode)…`
495
+
496
+ ### Namespaces
497
+
498
+ - `namespace is` — Type guards — array / string / primitive / VNode
499
+