ranuts 0.4.0-alpha.2 → 0.4.0-alpha.4

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 (43) hide show
  1. package/CLAUDE.md +40 -4
  2. package/README.md +11 -16
  3. package/README.zh-CN.md +11 -16
  4. package/dist/{color-Bh_QUad2.js → color-DPV7TsVU.js} +1 -1
  5. package/dist/i18n-Bq-f7htr.js +1 -0
  6. package/dist/index.js +1 -1
  7. package/dist/src/node/index.js +1 -1
  8. package/dist/src/utils/async.d.ts +30 -0
  9. package/dist/src/utils/behavior.d.ts +0 -14
  10. package/dist/src/utils/bom.d.ts +2 -22
  11. package/dist/src/utils/color.d.ts +75 -0
  12. package/dist/src/utils/device.d.ts +0 -1
  13. package/dist/src/utils/dom.d.ts +5 -2
  14. package/dist/src/utils/event.d.ts +34 -0
  15. package/dist/src/utils/i18n/index.js +1 -1
  16. package/dist/src/utils/index.d.ts +16 -13
  17. package/dist/src/utils/index.js +1 -1
  18. package/dist/src/utils/number.d.ts +60 -0
  19. package/dist/src/utils/obj.d.ts +0 -11
  20. package/dist/src/utils/placement.d.ts +40 -0
  21. package/dist/src/utils/str.d.ts +0 -8
  22. package/dist/src/utils/time.d.ts +33 -1
  23. package/dist/src/utils/visual/application.d.ts +10 -0
  24. package/dist/src/utils/visual/index.d.ts +5 -2
  25. package/dist/src/utils/visual/index.js +1 -1
  26. package/dist/src/utils/visual/render/filter.d.ts +43 -0
  27. package/dist/src/utils/visual/render/render.d.ts +6 -0
  28. package/dist/src/utils/visual/render/renderTarget.d.ts +13 -0
  29. package/dist/src/utils/visual/render/utils/earcut.d.ts +45 -0
  30. package/dist/src/utils/visual/render/webGlRenderer.d.ts +4 -0
  31. package/dist/test/utils/color-grade.test.d.ts +1 -0
  32. package/dist/test/utils/event.test.d.ts +1 -0
  33. package/dist/test/utils/interp.test.d.ts +1 -0
  34. package/dist/test/utils/placement.test.d.ts +1 -0
  35. package/dist/test/utils/visual/filter.test.d.ts +1 -0
  36. package/dist/umd/index.umd.cjs +1 -1
  37. package/dist/umd/node/node.umd.cjs +1 -1
  38. package/dist/umd/utils/utils.umd.cjs +1 -1
  39. package/dist/utils-CYrYCt5o.js +1 -0
  40. package/docs/API.md +41 -17
  41. package/package.json +24 -13
  42. package/dist/i18n-D1p8_7wC.js +0 -1
  43. package/dist/utils-vTF6lLZZ.js +0 -1
package/CLAUDE.md CHANGED
@@ -52,12 +52,13 @@ packages/ranuts/
52
52
  ├── index.ts # Root barrel (re-exports utils + visual + selected)
53
53
  ├── src/
54
54
  │ ├── utils/ # ranuts/utils — the largest surface (~14k LOC)
55
- │ │ ├── str.ts obj.ts number.ts color.ts bom.ts dom.ts time.ts …
55
+ │ │ ├── str.ts obj.ts number.ts color.ts bom.ts dom.ts …
56
+ │ │ ├── time.ts # formatDate / formatDuration / formatRelative + parseVttTimestamp / parseVttCueTiming
56
57
  │ │ ├── bridge.ts # postMessage request/response (split out of bom.ts)
57
58
  │ │ ├── idb.ts # WebDB (declarative stores) + createHandoff (one-shot value handoff)
58
59
  │ │ ├── worker.ts # WorkerClient — request/response over a Web Worker
59
60
  │ │ ├── zip.ts # ZIP read/rewrite — crc32, inflateRaw, rewriteZip, createZip
60
- │ │ ├── async.ts # deferred / withTimeout / withTimeoutFallback / delay
61
+ │ │ ├── async.ts # deferred / withTimeout / withTimeoutFallback / delay / createRaceGuard
61
62
  │ │ ├── storage.ts # localStorage* + createStore (prefixed JSON view)
62
63
  │ │ ├── segment.ts # offsets ↔ chunks, range→segment splitting (highlights)
63
64
  │ │ ├── localePath.ts # createLocalePath — i18n sub-directory URL maths
@@ -65,10 +66,11 @@ packages/ranuts/
65
66
  │ │ ├── lang.ts # detectLanguage + resolveLocale (query→cookie→storage→navigator)
66
67
  │ │ ├── file.ts # readFileAs* — FileReader promises
67
68
  │ │ ├── i18n.ts # ranuts/i18n — I18nCore, {param} interpolation, locale persistence
68
- │ │ ├── event.ts # EventManager — AbortController-scoped listeners + delegation
69
+ │ │ ├── event.ts # EventManager (AbortController-scoped listeners + delegation) + createDoubleTapDetector
69
70
  │ │ ├── chain.ts # Chain / create — chainable DOM builder (shared with vnode)
70
71
  │ │ ├── style.ts # adoptStyles / adoptSheetText — Shadow DOM CSS injection
71
72
  │ │ ├── canvas.ts # Canvas 2D geometry — roundRectByArc, fanShapedByArc, getLinearGradient
73
+ │ │ ├── placement.ts # computePlacement — flip/shift floating-panel placement (re-exported by ranui/utils/placement)
72
74
  │ │ ├── tween.ts # easing curves (quad/cubic/quart/quint/sine/expo/circ)
73
75
  │ │ ├── visual/ # ranuts/visual — 2D rendering engine (see below)
74
76
  │ │ └── totp/ # TOTP + hand-rolled SHA
@@ -108,8 +110,18 @@ A PixiJS-style 2D engine. The non-obvious parts, so you don't have to re-derive
108
110
  aligned. GPU vertex colors are premultiplied + packed little-endian into one u32.
109
111
  - **Inherent backend difference**: stroke/join geometry is native `ctx.stroke()` on Canvas
110
112
  vs. custom triangulation (`render/utils/verticy.ts`) on GPU — not pixel-identical by design.
113
+ - **Post-processing (WebGL)**: `app.filters = [new ColorAdjustFilter({ saturation: 1.4 })]`
114
+ runs full-screen passes after the scene. The WebGL backend draws the batch into a
115
+ `WebGLRenderTarget` (FBO) and ping-pongs the `Filter` chain to the canvas; the last pass
116
+ outputs to the screen. Extend `Filter` with any fragment shader (it samples the previous
117
+ pass through `u_texture`/`u_resolution`). Zero cost when `filters` is empty (the batch draws
118
+ straight to the canvas, unchanged); Canvas/WebGPU ignore filters. Lives in
119
+ `render/{renderTarget,filter}.ts`.
111
120
 
112
121
  Tests for the color pipeline and batch packing live next to the source as `*.test.ts`.
122
+ The colour-grade + interpolation helpers used by shaders (`fit`/`remap`/`lerp`/`smoothstep`
123
+ in `utils/number.ts`; `srgbToLinear`/`luma`/`blend*`/`saturation`/`cosinePalette` in
124
+ `utils/color.ts`) are exported from `ranuts/utils` for CPU-side reuse.
113
125
 
114
126
  ---
115
127
 
@@ -230,7 +242,7 @@ npm run doc:api # regenerate docs/API.md from source + JSDoc
230
242
  | A module-level factory that keeps mutable state shared by everything it produces | Give each produced function its own state (this is why `generateThrottle` was removed). |
231
243
  | Reaching for `memoize` expecting per-argument caching | It only runs once and ignores later arguments. Use `once` (its new name), `singleFlight` for async, or a `Map` for real keyed caching. |
232
244
  | Assuming `createSignal` deep-compares | It uses `Object.is` since 0.3. Pass `{ equals: isEqual }` when you want deep comparison. |
233
- | Testing a boolean URL flag with `getQuery(url).embed` | `?embed` (no value) is the usual spelling and reads as `''`, which is falsy. Use `queryFlag('embed')`. |
245
+ | Testing a boolean URL flag with `getAllQueryString(url).embed` | `?embed` (no value) is the usual spelling and reads as `''`, which is falsy. Use `queryFlag('embed')`. |
234
246
  | `Promise.race([task, timeoutPromise])` for a deadline | Leaks the timer when the task wins. Use `withTimeout` / `withTimeoutFallback` — they always clear it. |
235
247
  | Expecting `rewriteZip` to recompress | Rewritten and injected entries are written STORED, so the output is larger. Untouched entries keep their original compressed bytes. |
236
248
  | Expecting `zip.ts` to open a >4 GiB archive | No ZIP64, no encryption, no multi-disk. `readZipEntries` returns `[]` for anything it cannot parse. |
@@ -264,3 +276,27 @@ Each fixed a defect rather than changing a preference.
264
276
  | `hexToRgb` | Return type narrowed from `RegExpExecArray \| null \| Array<number>` to `Array<number> \| null`, and 3-digit shorthand (`#abc`) is now expanded per CSS rules instead of failing to parse. | None — strictly more inputs accepted, narrower type. |
265
277
  | `hsbToRgb` / `hsvToRgb` | Rounds instead of floors the final 0–255 channels. Flooring biased every channel down by up to 1, so `rgb → hsb → rgb` never converged (a colour picker lost saturation on repeated drags). | Values may differ by 1 per channel. None if you weren't asserting exact bytes. |
266
278
  | `Chain` / `create` (`ranuts/vnode`) | `src/vnode/chainDom.ts` was a second copy missing SVG namespace support and listener management. Both entries now export the fuller `utils/chain` implementation. | None — the surviving one is a superset. |
279
+
280
+ ## Breaking changes in 0.4
281
+
282
+ A pruning pass: every symbol below had zero call sites anywhere in this monorepo (checked with
283
+ a repo-wide grep, not just this package), no test, and — except `getQuery` — no narrative doc
284
+ page. Removed rather than deprecated, per the same `0.x`-experimental rationale as 0.3.
285
+
286
+ | Symbol | Why removed | Migration |
287
+ | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
288
+ | `getQuery` | Byte-identical alias of `getAllQueryString` since 0.3; the alias itself was never a reason to keep it. | `getAllQueryString`. |
289
+ | `audioVendor` / `canvasVendor` / `webglVendor` | Browser-fingerprinting helpers (canvas/audio/webgl hashing) in `behavior.ts`. No consumer, no docs. | None. |
290
+ | `setAttributeByGlobal` | Wrote to `window`/`global` by string key with no guard — a footgun with no caller in this repo. | Assign the global directly. |
291
+ | `getRegionalLatitudeAndLongitude` | Never re-exported from the `ranuts/utils` barrel — unreachable through the public API. | `navigator.geolocation` directly. |
292
+ | `sameValueZero` | Same — defined in `obj.ts` but never wired into the barrel or into `isEqual`. | `Object.is`. |
293
+ | `isBangDevice` | Notch heuristic hard-coded `screen.width`/`height` pairs through the iPhone 12 line only; already stale for 13–16 and rots further every generation. | `env('viewport-fit=cover')` + CSS `env(safe-area-inset-*)`. |
294
+ | `str2Xml` | Thin wrapper over `DOMParser` (plus a dead `ActiveXObject` branch for pre-2016 IE). | `new DOMParser().parseFromString(str, type)`. |
295
+ | `changeHumpToLowerCase` | One-line camelCase→snake_case wrapper, no caller. | `str.replace(/[A-Z]/g, (c) => '_' + c.toLowerCase())`. |
296
+ | `removeGhosting` | Real but narrow drag-ghost-image hack; documented but never called from anywhere in this repo. | Inline at the call site if needed. |
297
+ | `retain` | Real but narrow back-button-override hack; same story as `removeGhosting`. | Inline at the call site if needed. |
298
+
299
+ `packages/docs/.vitepress/plugins/env.ts` and `.vitepress/theme/index.ts` were the only actual
300
+ in-repo consumers found (`isBangDevice` for an unused `$env.isBang` field, `setAttributeByGlobal`
301
+ for a one-line `window.__VUE_PROD_DEVTOOLS__ = false`) — both inlined rather than kept as a
302
+ reason to preserve the library export.
package/README.md CHANGED
@@ -60,7 +60,7 @@ Import as required. You can select:
60
60
  - `ranuts/i18n` — the i18n engine on its own, without the rest of `utils`
61
61
 
62
62
  ```js
63
- import { str2Xml } from 'ranuts/utils';
63
+ import { debounce } from 'ranuts/utils';
64
64
  import { readFile } from 'ranuts/node';
65
65
  import { createI18n } from 'ranuts/i18n';
66
66
  ```
@@ -70,15 +70,13 @@ Full import,(Full import will introduce many unnecessary modules. You are advise
70
70
  - ESM
71
71
 
72
72
  ```js
73
- import { str2Xml } from 'ranuts';
73
+ import { debounce } from 'ranuts';
74
74
 
75
- const data = `
76
- <svg t="1688378016663" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2608" width="128" height="128"><path d="M568 515.008l254.016-255.008q12-11.008 12-27.488t-11.488-28-28-11.488-27.488 12l-255.008 254.016-255.008-254.016q-11.008-12-27.488-12t-28 11.488-11.488 28 12 27.488l254.016 255.008-254.016 255.008q-12 11.008-12 27.488t11.488 28 28 11.488 27.488-12l255.008-255.008 255.008 255.008q11.008 12 27.488 12t28-11.488 11.488-28-12-27.488z" p-id="2609" ></path></svg>
77
- `;
75
+ const onResize = debounce(() => {
76
+ console.log('window resized');
77
+ }, 200);
78
78
 
79
- const html = str2Xml(data, 'image/svg+xml');
80
-
81
- document.body.appendChild(html);
79
+ window.addEventListener('resize', onResize);
82
80
  ```
83
81
 
84
82
  - UMD, IIFE, CJS
@@ -87,15 +85,12 @@ document.body.appendChild(html);
87
85
  <script src="./ranuts/dist/umd/index.umd.cjs"></script>
88
86
 
89
87
  <script>
90
- const { str2Xml } = require('ranuts')
91
- const data = `
92
- <svg t="1688378016663" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2608" width="128" height="128"><path d="M568 515.008l254.016-255.008q12-11.008 12-27.488t-11.488-28-28-11.488-27.488 12l-255.008 254.016-255.008-254.016q-11.008-12-27.488-12t-28 11.488-11.488 28 12 27.488l254.016 255.008-254.016 255.008q-12 11.008-12 27.488t11.488 28 28 11.488 27.488-12l255.008-255.008 255.008 255.008q11.008 12 27.488 12t28-11.488 11.488-28-12-27.488z" p-id="2609" ></path></svg>
93
- `
94
-
95
- const html = str2Xml(data, 'image/svg+xml');
96
-
97
- document.body.appendChild(html);
88
+ const { debounce } = require('ranuts')
89
+ const onResize = debounce(() => {
90
+ console.log('window resized');
91
+ }, 200);
98
92
 
93
+ window.addEventListener('resize', onResize);
99
94
  <script>
100
95
  ```
101
96
 
package/README.zh-CN.md CHANGED
@@ -47,7 +47,7 @@ npm install ranuts@latest --save
47
47
  - `ranuts/i18n` —— 单独的 i18n 引擎,不牵入 `utils` 的其余部分
48
48
 
49
49
  ```js
50
- import { str2Xml } from 'ranuts/utils';
50
+ import { debounce } from 'ranuts/utils';
51
51
  import { readFile } from 'ranuts/node';
52
52
  import { createI18n } from 'ranuts/i18n';
53
53
  ```
@@ -57,15 +57,13 @@ import { createI18n } from 'ranuts/i18n';
57
57
  - ESM
58
58
 
59
59
  ```js
60
- import { str2Xml } from 'ranuts';
60
+ import { debounce } from 'ranuts';
61
61
 
62
- const data = `
63
- <svg t="1688378016663" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2608" width="128" height="128"><path d="M568 515.008l254.016-255.008q12-11.008 12-27.488t-11.488-28-28-11.488-27.488 12l-255.008 254.016-255.008-254.016q-11.008-12-27.488-12t-28 11.488-11.488 28 12 27.488l254.016 255.008-254.016 255.008q-12 11.008-12 27.488t11.488 28 28 11.488 27.488-12l255.008-255.008 255.008 255.008q11.008 12 27.488 12t28-11.488 11.488-28-12-27.488z" p-id="2609" ></path></svg>
64
- `;
62
+ const onResize = debounce(() => {
63
+ console.log('窗口尺寸发生变化');
64
+ }, 200);
65
65
 
66
- const html = str2Xml(data, 'image/svg+xml');
67
-
68
- document.body.appendChild(html);
66
+ window.addEventListener('resize', onResize);
69
67
  ```
70
68
 
71
69
  - UMD, IIFE, CJS
@@ -74,15 +72,12 @@ document.body.appendChild(html);
74
72
  <script src="./ranuts/dist/umd/index.umd.cjs"></script>
75
73
 
76
74
  <script>
77
- const { str2Xml } = require('ranuts')
78
- const data = `
79
- <svg t="1688378016663" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2608" width="128" height="128"><path d="M568 515.008l254.016-255.008q12-11.008 12-27.488t-11.488-28-28-11.488-27.488 12l-255.008 254.016-255.008-254.016q-11.008-12-27.488-12t-28 11.488-11.488 28 12 27.488l254.016 255.008-254.016 255.008q-12 11.008-12 27.488t11.488 28 28 11.488 27.488-12l255.008-255.008 255.008 255.008q11.008 12 27.488 12t28-11.488 11.488-28-12-27.488z" p-id="2609" ></path></svg>
80
- `
81
-
82
- const html = str2Xml(data, 'image/svg+xml');
83
-
84
- document.body.appendChild(html);
75
+ const { debounce } = require('ranuts')
76
+ const onResize = debounce(() => {
77
+ console.log('窗口尺寸发生变化');
78
+ }, 200);
85
79
 
80
+ window.addEventListener('resize', onResize);
86
81
  <script>
87
82
  ```
88
83