vitarx-router 4.0.3 → 4.0.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.
@@ -9,7 +9,7 @@
9
9
  */
10
10
  import { type PageDirConfig, type ResolvedConfig } from '../config/index.js';
11
11
  import { type FileInfo } from '../parser/parsePage.js';
12
- import type { PageOptions, PageParseResult, ScanNode } from '../types/index.js';
12
+ import type { PageParseResult, ScanNode } from '../types/index.js';
13
13
  /**
14
14
  * 扫描阶段的目录配置
15
15
  *
@@ -97,24 +97,4 @@ export interface ProcessPageFileParams {
97
97
  * @returns 新创建的路由节点;合并到已有路由时返回 null
98
98
  */
99
99
  export declare function processPageFile(params: ProcessPageFileParams, context: ProcessorContext): ScanNode | null;
100
- /**
101
- * 解析分组目录的自定义路径和选项
102
- *
103
- * 通过 groupParser 解析目录名,支持两种返回格式:
104
- * 1. 字符串:仅自定义路径
105
- * 2. 对象:自定义路径 + 路由选项(如 meta、name 等)
106
- *
107
- * 未配置 groupParser 时,直接使用原始目录名作为路径。
108
- *
109
- * @param fileName - 目录名
110
- * @param filePath - 目录完整路径
111
- * @param groupParser - 分组解析器,可选
112
- * @returns 解析后的路径和选项
113
- */
114
- export declare function parseGroupResult(fileName: string, filePath: string, groupParser?: (dirName: string, dirPath: string) => string | {
115
- path: string;
116
- options?: PageOptions;
117
- }): {
118
- routePath: string;
119
- options?: PageOptions;
120
- };
100
+ export { parseGroupResult } from '../utils/groupParser.js';
@@ -104,27 +104,5 @@ export function processPageFile(params, context) {
104
104
  pageMapping.set(parsed.path, route);
105
105
  return route;
106
106
  }
107
- /**
108
- * 解析分组目录的自定义路径和选项
109
- *
110
- * 通过 groupParser 解析目录名,支持两种返回格式:
111
- * 1. 字符串:仅自定义路径
112
- * 2. 对象:自定义路径 + 路由选项(如 meta、name 等)
113
- *
114
- * 未配置 groupParser 时,直接使用原始目录名作为路径。
115
- *
116
- * @param fileName - 目录名
117
- * @param filePath - 目录完整路径
118
- * @param groupParser - 分组解析器,可选
119
- * @returns 解析后的路径和选项
120
- */
121
- export function parseGroupResult(fileName, filePath, groupParser) {
122
- if (!groupParser) {
123
- return { routePath: fileName };
124
- }
125
- const result = groupParser(fileName, filePath);
126
- if (typeof result === 'string') {
127
- return { routePath: result };
128
- }
129
- return { routePath: result.path, options: result.options };
130
- }
107
+ // parseGroupResult 已移至 utils/groupParser.ts,此处重新导出以保持向后兼容
108
+ export { parseGroupResult } from '../utils/groupParser.js';
@@ -122,6 +122,7 @@ export class FileRouter {
122
122
  fileMap: this.fileMap,
123
123
  pages: this.config.pages,
124
124
  pageParser: this.config.pageParser,
125
+ groupParser: this.config.groupParser,
125
126
  pathStrategy: this.config.pathStrategy
126
127
  });
127
128
  }
@@ -1,10 +1,11 @@
1
1
  import { type PageDirConfig } from '../config/resolve.js';
2
- import type { PageParser, PathStrategy, ScanNode } from '../types/index.js';
2
+ import type { GroupParser, PageParser, PathStrategy, ScanNode } from '../types/index.js';
3
3
  import { type FileInfo } from './parsePage.js';
4
4
  interface RouteFullPathContext {
5
5
  fileMap: Map<string, ScanNode>;
6
6
  pages: readonly PageDirConfig[];
7
7
  pageParser?: PageParser;
8
+ groupParser?: GroupParser;
8
9
  pathStrategy: PathStrategy;
9
10
  }
10
11
  /**
@@ -5,6 +5,7 @@
5
5
  * 支持已跟踪(在路由树中)和未跟踪(尚未扫描)两种场景。
6
6
  */
7
7
  import nodePath from 'node:path';
8
+ import { parseGroupResult } from '../utils/groupParser.js';
8
9
  import { applyPathStrategy } from '../utils/pathStrategy.js';
9
10
  import { normalizeRoutePath, resolvePathVariable } from '../utils/pathUtils.js';
10
11
  import { isPageFileInDirs } from './filterUtils.js';
@@ -48,27 +49,39 @@ function computeNodeFullPath(node) {
48
49
  * @returns 完整路由路径,非页面文件返回 null
49
50
  */
50
51
  export function computeRouteFullPath(filePath, fileInfo, context) {
51
- const { fileMap, pages, pageParser, pathStrategy } = context;
52
+ const { fileMap, pages, pageParser, groupParser, pathStrategy } = context;
53
+ // 场景一:文件已在路由树中,直接沿 parent 链计算 fullPath
52
54
  const node = fileMap.get(filePath);
53
55
  if (node) {
54
56
  return computeNodeFullPath(node);
55
57
  }
58
+ // 场景二:文件尚未被扫描跟踪,需要从文件路径手动计算
56
59
  const page = isPageFileInDirs(filePath, pages);
57
60
  if (!page)
58
61
  return null;
62
+ // 解析文件名得到路径段(index 文件不产生路径段)
59
63
  const parsed = parsePageFile(filePath, pageParser, fileInfo);
60
- const pathSegment = parsed.path === 'index' ? '' : applyFullPathStrategy(parsed.path, pathStrategy);
64
+ const pathSegment = parsed.path === 'index' ? '' : parsed.path;
61
65
  const segments = pathSegment ? [pathSegment] : [];
66
+ // 从文件所在目录向上遍历至 pages.dir 根目录,逐级收集路径段
62
67
  let dirPath = nodePath.dirname(filePath);
63
68
  while (dirPath.length > page.dir.length) {
64
69
  const dirNode = fileMap.get(dirPath);
65
70
  if (dirNode) {
71
+ // 目录已在路由树中,直接复用其 fullPath 作为前缀,无需继续向上遍历
66
72
  const parentFullPath = computeNodeFullPath(dirNode);
67
- return normalizeRoutePath(parentFullPath + '/' + segments.join('/'));
73
+ segments.unshift(parentFullPath);
74
+ return normalizeRoutePath(applyFullPathStrategy(segments.join('/'), pathStrategy));
68
75
  }
69
- segments.unshift(applyFullPathStrategy(nodePath.basename(dirPath), pathStrategy));
76
+ // 目录未被跟踪,通过 groupParser 解析目录名(如 "1.user" → "user"),再作为路径段
77
+ const dirName = nodePath.basename(dirPath);
78
+ const { routePath: parsedDirName } = parseGroupResult(dirName, dirPath, groupParser);
79
+ segments.unshift(parsedDirName);
70
80
  dirPath = nodePath.dirname(dirPath);
71
81
  }
72
- const prefix = page.prefix ? applyFullPathStrategy(page.prefix, pathStrategy) : '';
73
- return normalizeRoutePath(prefix + '/' + segments.join('/'));
82
+ // 顶层路由拼接 prefix
83
+ if (page.prefix)
84
+ segments.unshift(page.prefix);
85
+ // 统一应用路径策略(命名转换 + 动态参数转换)并规范化
86
+ return normalizeRoutePath(applyFullPathStrategy(segments.join('/'), pathStrategy));
74
87
  }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @fileoverview 分组目录解析工具
3
+ *
4
+ * 提供 groupParser 的调用封装,将目录名解析为路由路径和选项。
5
+ * 供扫描器和路径计算等模块共同使用。
6
+ */
7
+ import type { PageOptions } from '../types/index.js';
8
+ /**
9
+ * 解析分组目录的自定义路径和选项
10
+ *
11
+ * 通过 groupParser 解析目录名,支持两种返回格式:
12
+ * 1. 字符串:仅自定义路径
13
+ * 2. 对象:自定义路径 + 路由选项(如 meta、name 等)
14
+ *
15
+ * 未配置 groupParser 时,直接使用原始目录名作为路径。
16
+ *
17
+ * @param fileName - 目录名
18
+ * @param filePath - 目录完整路径
19
+ * @param groupParser - 分组解析器,可选
20
+ * @returns 解析后的路径和选项
21
+ */
22
+ export declare function parseGroupResult(fileName: string, filePath: string, groupParser?: (dirName: string, dirPath: string) => string | {
23
+ path: string;
24
+ options?: PageOptions;
25
+ }): {
26
+ routePath: string;
27
+ options?: PageOptions;
28
+ };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * 解析分组目录的自定义路径和选项
3
+ *
4
+ * 通过 groupParser 解析目录名,支持两种返回格式:
5
+ * 1. 字符串:仅自定义路径
6
+ * 2. 对象:自定义路径 + 路由选项(如 meta、name 等)
7
+ *
8
+ * 未配置 groupParser 时,直接使用原始目录名作为路径。
9
+ *
10
+ * @param fileName - 目录名
11
+ * @param filePath - 目录完整路径
12
+ * @param groupParser - 分组解析器,可选
13
+ * @returns 解析后的路径和选项
14
+ */
15
+ export function parseGroupResult(fileName, filePath, groupParser) {
16
+ if (!groupParser) {
17
+ return { routePath: fileName };
18
+ }
19
+ const result = groupParser(fileName, filePath);
20
+ if (typeof result === 'string') {
21
+ return { routePath: result };
22
+ }
23
+ return { routePath: result.path, options: result.options };
24
+ }
@@ -10,3 +10,4 @@ export * from './pathStrategy.js';
10
10
  export * from '../config/validate.js';
11
11
  export * from './fileReader.js';
12
12
  export * from './findRoute.js';
13
+ export * from './groupParser.js';
@@ -10,3 +10,4 @@ export * from './pathStrategy.js';
10
10
  export * from '../config/validate.js';
11
11
  export * from './fileReader.js';
12
12
  export * from './findRoute.js';
13
+ export * from './groupParser.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitarx-router",
3
- "version": "4.0.3",
3
+ "version": "4.0.4",
4
4
  "description": "Official routing solution for Vitarx framework with declarative routing, navigation guards, dynamic routes, file-based routing with HMR, and full TypeScript support.",
5
5
  "author": "ZhuChonglin <8210856@qq.com>",
6
6
  "license": "MIT",