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 +27 -5
- package/dist/index.cjs +1 -38
- package/dist/index.d.ts +0 -17
- package/dist/index.js +1 -36
- package/package.json +6 -2
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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",
|
package/dist/index.cjs.map
DELETED
|
@@ -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;;;;"}
|