route-ui-sync 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,10 +9,11 @@
9
9
  ## 特性
10
10
 
11
11
  - 🎯 **框架无关**:不依赖 React、Vue 或任何路由库
12
- - 🚀 **轻量级**:零依赖,体积小
12
+ - 🚀 **极轻量级**:零依赖,压缩后仅 ~314 字节(ES 模块)或 ~321 字节(CommonJS)
13
13
  - 🔧 **类型安全**:完整的 TypeScript 类型定义
14
14
  - ✅ **测试覆盖**:完整的单元测试
15
15
  - 📦 **多格式支持**:同时支持 ES 模块和 CommonJS
16
+ - ⚡ **高度优化**:使用 Terser 进行激进压缩,生产环境不包含 sourcemap
16
17
 
17
18
  ## 安装
18
19
 
@@ -319,15 +320,23 @@ npm run build
319
320
 
320
321
  ### 测试
321
322
 
323
+ 项目使用 Vitest 进行单元测试,包括源代码测试和打包后代码测试。
324
+
322
325
  ```bash
323
- # 运行测试
326
+ # 运行源代码测试
324
327
  npm test
325
328
 
326
- # 监听模式
329
+ # 监听模式运行测试
327
330
  npm run test:watch
328
331
 
329
- # 生成覆盖率报告
332
+ # 运行测试并生成覆盖率报告
330
333
  npm run test:coverage
334
+
335
+ # 测试打包后的代码(自动构建并测试)
336
+ npm run test:bundle
337
+
338
+ # 运行所有测试(源代码 + 打包后代码)
339
+ npm run test:all
331
340
  ```
332
341
 
333
342
  ### 类型检查
@@ -338,9 +347,22 @@ npm run type-check
338
347
 
339
348
  ### 测试覆盖
340
349
 
341
- - **测试用例数**: 39 个
350
+ 项目包含完整的单元测试,覆盖了各种使用场景:
351
+
352
+ - **测试用例数**: 39 个(源代码测试)+ 22 个(打包后代码测试)= **61 个测试用例**
342
353
  - **代码覆盖率**: 100%
343
354
  - **测试场景**: 包括基础功能、复杂场景、边界情况、实际项目场景等
355
+ - **打包验证**: 自动测试打包后的 ES 模块和 CommonJS 模块功能
356
+
357
+ **打包后代码测试说明:**
358
+
359
+ `test:bundle` 命令会:
360
+ 1. 自动构建项目(`npm run build`)
361
+ 2. 测试打包后的 ES 模块(`dist/index.js`)
362
+ 3. 测试打包后的 CommonJS 模块(`dist/index.cjs`)
363
+ 4. 验证打包文件大小和完整性
364
+
365
+ 这确保了打包后的代码功能与源代码完全一致,验证了压缩和优化过程没有破坏功能。
344
366
 
345
367
  查看 [TEST_COVERAGE.md](./TEST_COVERAGE.md) 了解详细的测试覆盖情况。
346
368
 
package/dist/index.cjs CHANGED
@@ -1,38 +1 @@
1
- 'use strict';
2
-
3
- // 一个与 UI 框架无关的"小核心",用于根据当前路由信息计算选中 key。
4
- /**
5
- * 根据当前路由信息和一组规则,计算"当前应该选中的 key"
6
- *
7
- * - 不依赖 React / react-router / 任何 UI 库
8
- * - 只关心最基础的 location 对象和规则数组
9
- * - 未来做成 npm 包时,只需要把这个函数原样搬过去即可
10
- */
11
- function getSelectedKeyFromLocation(location, rules) {
12
- if (!location || !rules || rules.length === 0) {
13
- return undefined;
14
- }
15
- const { pathname, search = "", hash = "" } = location;
16
- const safeLocation = { pathname, search, hash };
17
- // 找出所有命中的规则
18
- const matched = rules.filter((rule) => {
19
- try {
20
- return rule.match(safeLocation);
21
- }
22
- catch {
23
- // 某个规则内部异常时,忽略该规则,避免影响整体
24
- return false;
25
- }
26
- });
27
- if (matched.length === 0)
28
- return undefined;
29
- // 如果只有一个命中,直接返回
30
- if (matched.length === 1)
31
- return matched[0].key;
32
- // 多个命中时,按 priority 从高到低排序,取第一个
33
- matched.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
34
- return matched[0].key;
35
- }
36
-
37
- exports.getSelectedKeyFromLocation = getSelectedKeyFromLocation;
38
- //# sourceMappingURL=index.cjs.map
1
+ "use strict";exports.getSelectedKeyFromLocation=function(t,e){if(!t||!e||0===e.length)return;const{pathname:r,search:h="",hash:n=""}=t,a={pathname:r,search:h,hash:n},c=e.filter(t=>{try{return t.match(a)}catch{return!1}});return 0!==c.length?(1===c.length||c.sort((t,e)=>(e.priority??0)-(t.priority??0)),c[0].key):void 0};
package/dist/index.d.ts CHANGED
@@ -4,27 +4,10 @@ type RouteMatchPredicate = (location: {
4
4
  hash?: string;
5
5
  }) => boolean;
6
6
  interface RouteSelectionRule {
7
- /**
8
- * 唯一 key,用于传给 UI 组件(例如 Menu.Item 的 key 或 className 中的一部分)
9
- */
10
7
  key: string;
11
- /**
12
- * 匹配函数:根据当前 location 判断这个规则是否命中
13
- */
14
8
  match: RouteMatchPredicate;
15
- /**
16
- * 优先级:数字越大优先级越高(可选)
17
- * 当多个规则同时命中时,用它来决定最终选中哪个
18
- */
19
9
  priority?: number;
20
10
  }
21
- /**
22
- * 根据当前路由信息和一组规则,计算"当前应该选中的 key"
23
- *
24
- * - 不依赖 React / react-router / 任何 UI 库
25
- * - 只关心最基础的 location 对象和规则数组
26
- * - 未来做成 npm 包时,只需要把这个函数原样搬过去即可
27
- */
28
11
  declare function getSelectedKeyFromLocation(location: {
29
12
  pathname: string;
30
13
  search?: string;
package/dist/index.js CHANGED
@@ -1,36 +1 @@
1
- // 一个与 UI 框架无关的"小核心",用于根据当前路由信息计算选中 key
2
- /**
3
- * 根据当前路由信息和一组规则,计算"当前应该选中的 key"
4
- *
5
- * - 不依赖 React / react-router / 任何 UI 库
6
- * - 只关心最基础的 location 对象和规则数组
7
- * - 未来做成 npm 包时,只需要把这个函数原样搬过去即可
8
- */
9
- function getSelectedKeyFromLocation(location, rules) {
10
- if (!location || !rules || rules.length === 0) {
11
- return undefined;
12
- }
13
- const { pathname, search = "", hash = "" } = location;
14
- const safeLocation = { pathname, search, hash };
15
- // 找出所有命中的规则
16
- const matched = rules.filter((rule) => {
17
- try {
18
- return rule.match(safeLocation);
19
- }
20
- catch {
21
- // 某个规则内部异常时,忽略该规则,避免影响整体
22
- return false;
23
- }
24
- });
25
- if (matched.length === 0)
26
- return undefined;
27
- // 如果只有一个命中,直接返回
28
- if (matched.length === 1)
29
- return matched[0].key;
30
- // 多个命中时,按 priority 从高到低排序,取第一个
31
- matched.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
32
- return matched[0].key;
33
- }
34
-
35
- export { getSelectedKeyFromLocation };
36
- //# sourceMappingURL=index.js.map
1
+ function t(t,r){if(!t||!r||0===r.length)return;const{pathname:e,search:h="",hash:n=""}=t,a={pathname:e,search:h,hash:n},i=r.filter(t=>{try{return t.match(a)}catch{return!1}});return 0!==i.length?(1===i.length||i.sort((t,r)=>(r.priority??0)-(t.priority??0)),i[0].key):void 0}export{t as getSelectedKeyFromLocation};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "route-ui-sync",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "A lightweight, framework-agnostic utility for automatically matching routes to menu keys. Zero dependencies, TypeScript support, for navigation menus.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -19,11 +19,14 @@
19
19
  ],
20
20
  "scripts": {
21
21
  "build": "rollup -c",
22
+ "build:prod": "rollup -c",
22
23
  "test": "vitest run",
23
24
  "test:watch": "vitest",
24
25
  "test:coverage": "vitest run --coverage",
26
+ "test:bundle": "npm run build && vitest run src/index.bundle.test.ts",
27
+ "test:all": "npm run test && npm run test:bundle",
25
28
  "type-check": "tsc --noEmit",
26
- "prepublishOnly": "npm run build && npm run test"
29
+ "prepublishOnly": "npm run build && npm run test:all"
27
30
  },
28
31
  "keywords": [
29
32
  "route",
@@ -37,6 +40,7 @@
37
40
  "license": "MIT",
38
41
  "devDependencies": {
39
42
  "@rollup/plugin-typescript": "^12.1.1",
43
+ "@rollup/plugin-terser": "^0.4.4",
40
44
  "@types/node": "^22.7.4",
41
45
  "@vitest/coverage-v8": "^4.0.15",
42
46
  "rollup": "^4.22.0",
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAAA;AAwBA;;;;;;AAMG;AACG,SAAU,0BAA0B,CACxC,QAA8D,EAC9D,KAA2B,EAAA;AAE3B,IAAA,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;AAC7C,QAAA,OAAO,SAAS;IAClB;AAEA,IAAA,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,EAAE,EAAE,IAAI,GAAG,EAAE,EAAE,GAAG,QAAQ;IACrD,MAAM,YAAY,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;;IAG/C,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KAAI;AACpC,QAAA,IAAI;AACF,YAAA,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;QACjC;AAAE,QAAA,MAAM;;AAEN,YAAA,OAAO,KAAK;QACd;AACF,IAAA,CAAC,CAAC;AAEF,IAAA,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;AAAE,QAAA,OAAO,SAAS;;AAG1C,IAAA,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;AAAE,QAAA,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG;;IAG/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;AAC7D,IAAA,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG;AACvB;;;;"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;AAwBA;;;;;;AAMG;AACG,SAAU,0BAA0B,CACxC,QAA8D,EAC9D,KAA2B,EAAA;AAE3B,IAAA,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;AAC7C,QAAA,OAAO,SAAS;IAClB;AAEA,IAAA,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,EAAE,EAAE,IAAI,GAAG,EAAE,EAAE,GAAG,QAAQ;IACrD,MAAM,YAAY,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;;IAG/C,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KAAI;AACpC,QAAA,IAAI;AACF,YAAA,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;QACjC;AAAE,QAAA,MAAM;;AAEN,YAAA,OAAO,KAAK;QACd;AACF,IAAA,CAAC,CAAC;AAEF,IAAA,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;AAAE,QAAA,OAAO,SAAS;;AAG1C,IAAA,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;AAAE,QAAA,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG;;IAG/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;AAC7D,IAAA,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG;AACvB;;;;"}