lcd-router-webpack-plugin 9.0.0-alpha.6 → 9.0.0-alpha.7
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/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/package.json +4 -1
- package/.lecprc.ts +0 -5
- package/src/Generator.ts +0 -46
- package/src/ReducersGenerator.ts +0 -90
- package/src/RoutersGenerator.ts +0 -295
- package/src/SagasGenerator.ts +0 -101
- package/src/index.ts +0 -220
- package/src/utils/files.ts +0 -54
- package/src/utils/index.ts +0 -4
- package/src/utils/paths.ts +0 -77
- package/src/utils/resolver.ts +0 -37
- package/src/utils/types.ts +0 -76
- package/tsconfig.json +0 -14
package/lib/index.js
CHANGED
|
@@ -61,7 +61,7 @@ class LcdRouterWebpackPlugin {
|
|
|
61
61
|
* 不太方便去垫一个 reducer 函数,reducer 的路径计算比较复杂, 所以直接报错
|
|
62
62
|
* 同时,从逻辑上讲,如果开启了 mobx,那么必须要有 reducer 文件
|
|
63
63
|
*/
|
|
64
|
-
throw Error(
|
|
64
|
+
throw Error(`开启 mobx 后,reducer 文件必须存在 ${absFilePath}`);
|
|
65
65
|
}
|
|
66
66
|
chunkCode.push(`export function reducer(){ return {} }`);
|
|
67
67
|
}
|
|
@@ -76,7 +76,7 @@ class LcdRouterWebpackPlugin {
|
|
|
76
76
|
chunkCode.push(`export { default as saga } from '${sagaPath}';`);
|
|
77
77
|
} catch (e) {
|
|
78
78
|
// feat: saga 也可以不存在, 方便结合reactive 和 ak,默认创建一个reducers
|
|
79
|
-
chunkCode.push(`export function saga
|
|
79
|
+
chunkCode.push(`export function* saga(){ return {} }`);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
if (meJSON.errorComponent) {
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_globby","_interopRequireDefault","require","_chokidar","_deepmerge","_utils","_ReducersGenerator","_SagasGenerator","_RoutersGenerator","_nodePath","obj","__esModule","default","LcdRouterWebpackPlugin","options","constructor","apply","compiler","mergeOptions","hooks","afterPlugins","tap","pathService","PathService","resolver","Resolver","fileService","FileService","reducersGenerator","ReducersGenerator","sagasGenerator","SagasGenerator","routersGenerator","RoutersGenerator","isDev","mode","process","env","NODE_ENV","writeCode","writeCodeToFile","getReducersCacheFileAbs","getSagasCacheFileAbs","getRoutersCacheFileAbs","resolveFile","filepath","absFilePath","getCurrentFileAbs","currentDir","path","dirname","absCurrentDir","chunkCode","meJSON","readJSONSync","reducerPath","getReducerFile","push","e","mobx","Error","viewPath","getViewFile","theme","hash","sagaPath","getSagaFile","errorComponent","errorCompPath","getErrorComFile","themePath","getThemeJSCacheFileAbs","writeThemeFile","meJSONPath","getMeJSONCacheFileAbs","writeMeJSONFile","isExternal","externals","some","x","hasChildStore","globby","sync","reducerName","cwd","length","set","namespace","page","exact","RegExp","index","test","_key","replace","list","getPageRootAbs","console","warn","sortedList","map","sort","a","b","startsWith","localeCompare","dir","forEach","watcher","chokidar","watch","ignoreInitial","fn","on","defaultOptions","context","enablePreFetch","pageDir","disableBuiltInRoute","deepmerge","exports"],"sources":["../index.ts"],"sourcesContent":["import type { Compiler, WebpackPluginInstance } from 'webpack';\nimport globby from 'globby';\nimport chokidar from 'chokidar';\nimport deepmerge from 'deepmerge';\nimport { PathService, Resolver, Options, FileService } from './utils';\nimport { ReducersGenerator } from './ReducersGenerator';\nimport { SagasGenerator } from './SagasGenerator';\nimport { RoutersGenerator } from './RoutersGenerator';\n\nimport path from 'node:path';\n\nexport default class LcdRouterWebpackPlugin implements WebpackPluginInstance {\n options: Options;\n constructor(options: Options) {\n this.options = options;\n }\n\n apply(compiler: Compiler) {\n this.mergeOptions(compiler);\n\n compiler.hooks.afterPlugins.tap('LcdRouterWebpackPlugin', (compiler) => {\n const options = this.options;\n\n const pathService = new PathService(options);\n const resolver = new Resolver(compiler, options);\n const fileService = new FileService(pathService);\n\n const reducersGenerator = new ReducersGenerator();\n const sagasGenerator = new SagasGenerator();\n const routersGenerator = new RoutersGenerator(options, pathService);\n\n function isDev(compiler) {\n if (compiler.options.mode === 'production' || process.env.NODE_ENV === 'production') return false;\n return true;\n }\n\n function writeCode() {\n reducersGenerator.writeCodeToFile(pathService.getReducersCacheFileAbs());\n sagasGenerator.writeCodeToFile(pathService.getSagasCacheFileAbs());\n routersGenerator.writeCodeToFile(pathService.getRoutersCacheFileAbs());\n }\n\n function resolveFile(filepath: string) {\n const absFilePath = pathService.getCurrentFileAbs(filepath);\n const currentDir = path.dirname(filepath);\n const absCurrentDir = path.dirname(absFilePath);\n\n const chunkCode = [] as string[];\n const meJSON = fileService.readJSONSync(absFilePath);\n try {\n const reducerPath = resolver.getReducerFile(absCurrentDir);\n chunkCode.push(`export { default as reducer } from '${reducerPath}';`);\n } catch (e) {\n // feat: reducers 可以不存在, 方便结合reactive 和 ak,默认创建一个reducers\n if (meJSON.mobx) {\n /**\n * mobx 模式下, 需要垫一个被 mobx-adapter 包裹的 reducer 函数\n * 如果存在reducer文件,是默认会被 babel-plugin-enhance-reducer 处理的\n *\n * import storeHoc from 'rrc-loader-helper/lib/mobx-adapter';\n * export const reducer = storeHoc({\n * state: {},\n * }, 'report/other-table')\n *\n * 不太方便去垫一个 reducer 函数,reducer 的路径计算比较复杂, 所以直接报错\n * 同时,从逻辑上讲,如果开启了 mobx,那么必须要有 reducer 文件\n */\n throw Error('开启 mobx 后,reducer 文件必须存在');\n }\n chunkCode.push(`export function reducer(){ return {} }`);\n }\n\n const viewPath = resolver.getViewFile(absCurrentDir);\n chunkCode.push(`export { default as view } from '${viewPath}';`);\n\n if (meJSON.theme && !options.theme?.hash) {\n throw Error(`开启页面级主题之前,请优先开启全局主题 ${absFilePath}`);\n }\n\n if (!meJSON.mobx) {\n try {\n const sagaPath = resolver.getSagaFile(absCurrentDir);\n chunkCode.push(`export { default as saga } from '${sagaPath}';`);\n } catch (e) {\n // feat: saga 也可以不存在, 方便结合reactive 和 ak,默认创建一个reducers\n chunkCode.push(`export function saga*(){ return {} }`);\n }\n }\n\n if (meJSON.errorComponent) {\n const errorCompPath = resolver.getErrorComFile(absCurrentDir, meJSON.errorComponent);\n chunkCode.push(`export { default as ErrorComponent } from '${errorCompPath}';`);\n }\n\n if (options.theme?.hash) {\n const themePath = pathService.getThemeJSCacheFileAbs(options.theme?.hash);\n chunkCode.push(`export * from '${themePath}';`);\n }\n\n if (meJSON.theme) {\n fileService.writeThemeFile(meJSON.theme, 'toGlobalTheme');\n const themePath = pathService.getThemeJSCacheFileAbs(meJSON.theme);\n chunkCode.push(`export * from '${themePath}';`);\n }\n\n const meJSONPath = pathService.getMeJSONCacheFileAbs(filepath);\n\n fileService.writeMeJSONFile(meJSONPath, chunkCode);\n\n const isExternal = options.externals?.some?.((x) => x === path.dirname(filepath)) ?? false;\n\n // 处理是否存在多store的场景\n const hasChildStore = globby.sync(`**/*.${options.reducerName}.{t,j}s`, { cwd: absCurrentDir }).length > 0;\n if (hasChildStore && (meJSON.sync || isExternal)) {\n throw Error(`如果开启了Sync模式或当前页面存在于LCD的external中,那么则不支持多Store功能,${absCurrentDir}`);\n }\n\n /** reducers.js */\n reducersGenerator.set(filepath, {\n meJSON,\n isExternal,\n namespace: currentDir,\n meJSONPath: meJSONPath,\n });\n\n /** saga.js */\n sagasGenerator.set(currentDir, {\n meJSON,\n isExternal,\n namespace: currentDir,\n meJSONPath: meJSONPath,\n });\n\n /** router */\n routersGenerator.set(currentDir, {\n meJSON,\n isExternal,\n page: currentDir,\n path: currentDir,\n exact: false,\n meJSONPath: meJSONPath,\n });\n\n /** 处理 /list 的路由 */\n if (new RegExp(`\\/${options.index}$`).test(absCurrentDir)) {\n const _key = absCurrentDir.replace(new RegExp(`\\/${options.index}$`), '');\n routersGenerator.set(_key, {\n meJSON,\n isExternal,\n page: absCurrentDir,\n path: _key,\n exact: true,\n meJSONPath: meJSONPath,\n });\n }\n }\n\n if (options.theme?.hash) {\n fileService.writeThemeFile(options.theme.hash, 'toGlobalTheme');\n }\n\n const list = globby.sync('**/me.json', {\n cwd: pathService.getPageRootAbs(),\n });\n\n if (list.length === 0) {\n console.warn('没有找到me.json文件');\n }\n\n /**\n * glob 的排序 是包含文件名 me.json 的完整路径,存在问题\n * 比如 会将 /xx/ss/me.json 排到 /xx/ss/zz/me.json 前面\n * glob 的 noSort option 会将 文件夹排到前面, 因此需要手动排序, 并且统一成 globby, 速度更快\n */\n const sortedList = list\n .map((filepath) => filepath?.replace(/me.json$/, ''))\n .sort((a, b) => {\n if (a?.startsWith(b)) return -1;\n return a.localeCompare(b, 'en');\n })\n .map((dir) => `${dir}me.json`);\n\n sortedList.forEach((filepath) => {\n resolveFile(filepath);\n });\n\n writeCode();\n\n if (isDev(compiler)) {\n const watcher = chokidar.watch('**/me.json', {\n cwd: pathService.getPageRootAbs(),\n ignoreInitial: true,\n });\n const fn = async (filepath) => {\n await resolveFile(filepath);\n writeCode();\n };\n watcher.on('add', fn);\n watcher.on('addDir', fn);\n watcher.on('change', fn);\n watcher.on('unlink', fn);\n watcher.on('unlinkDir', fn);\n watcher.on('error', fn);\n }\n });\n }\n\n mergeOptions(compiler: Compiler) {\n const defaultOptions = {\n context: compiler.context,\n enablePreFetch: false,\n index: 'list',\n externals: [],\n pageDir: 'component',\n reducerName: 'reducers',\n disableBuiltInRoute: false,\n };\n this.options = deepmerge(defaultOptions, this.options);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["_globby","_interopRequireDefault","require","_chokidar","_deepmerge","_utils","_ReducersGenerator","_SagasGenerator","_RoutersGenerator","_nodePath","obj","__esModule","default","LcdRouterWebpackPlugin","options","constructor","apply","compiler","mergeOptions","hooks","afterPlugins","tap","pathService","PathService","resolver","Resolver","fileService","FileService","reducersGenerator","ReducersGenerator","sagasGenerator","SagasGenerator","routersGenerator","RoutersGenerator","isDev","mode","process","env","NODE_ENV","writeCode","writeCodeToFile","getReducersCacheFileAbs","getSagasCacheFileAbs","getRoutersCacheFileAbs","resolveFile","filepath","absFilePath","getCurrentFileAbs","currentDir","path","dirname","absCurrentDir","chunkCode","meJSON","readJSONSync","reducerPath","getReducerFile","push","e","mobx","Error","viewPath","getViewFile","theme","hash","sagaPath","getSagaFile","errorComponent","errorCompPath","getErrorComFile","themePath","getThemeJSCacheFileAbs","writeThemeFile","meJSONPath","getMeJSONCacheFileAbs","writeMeJSONFile","isExternal","externals","some","x","hasChildStore","globby","sync","reducerName","cwd","length","set","namespace","page","exact","RegExp","index","test","_key","replace","list","getPageRootAbs","console","warn","sortedList","map","sort","a","b","startsWith","localeCompare","dir","forEach","watcher","chokidar","watch","ignoreInitial","fn","on","defaultOptions","context","enablePreFetch","pageDir","disableBuiltInRoute","deepmerge","exports"],"sources":["../index.ts"],"sourcesContent":["import type { Compiler, WebpackPluginInstance } from 'webpack';\nimport globby from 'globby';\nimport chokidar from 'chokidar';\nimport deepmerge from 'deepmerge';\nimport { PathService, Resolver, Options, FileService } from './utils';\nimport { ReducersGenerator } from './ReducersGenerator';\nimport { SagasGenerator } from './SagasGenerator';\nimport { RoutersGenerator } from './RoutersGenerator';\n\nimport path from 'node:path';\n\nexport default class LcdRouterWebpackPlugin implements WebpackPluginInstance {\n options: Options;\n constructor(options: Options) {\n this.options = options;\n }\n\n apply(compiler: Compiler) {\n this.mergeOptions(compiler);\n\n compiler.hooks.afterPlugins.tap('LcdRouterWebpackPlugin', (compiler) => {\n const options = this.options;\n\n const pathService = new PathService(options);\n const resolver = new Resolver(compiler, options);\n const fileService = new FileService(pathService);\n\n const reducersGenerator = new ReducersGenerator();\n const sagasGenerator = new SagasGenerator();\n const routersGenerator = new RoutersGenerator(options, pathService);\n\n function isDev(compiler) {\n if (compiler.options.mode === 'production' || process.env.NODE_ENV === 'production') return false;\n return true;\n }\n\n function writeCode() {\n reducersGenerator.writeCodeToFile(pathService.getReducersCacheFileAbs());\n sagasGenerator.writeCodeToFile(pathService.getSagasCacheFileAbs());\n routersGenerator.writeCodeToFile(pathService.getRoutersCacheFileAbs());\n }\n\n function resolveFile(filepath: string) {\n const absFilePath = pathService.getCurrentFileAbs(filepath);\n const currentDir = path.dirname(filepath);\n const absCurrentDir = path.dirname(absFilePath);\n\n const chunkCode = [] as string[];\n const meJSON = fileService.readJSONSync(absFilePath);\n try {\n const reducerPath = resolver.getReducerFile(absCurrentDir);\n chunkCode.push(`export { default as reducer } from '${reducerPath}';`);\n } catch (e) {\n // feat: reducers 可以不存在, 方便结合reactive 和 ak,默认创建一个reducers\n if (meJSON.mobx) {\n /**\n * mobx 模式下, 需要垫一个被 mobx-adapter 包裹的 reducer 函数\n * 如果存在reducer文件,是默认会被 babel-plugin-enhance-reducer 处理的\n *\n * import storeHoc from 'rrc-loader-helper/lib/mobx-adapter';\n * export const reducer = storeHoc({\n * state: {},\n * }, 'report/other-table')\n *\n * 不太方便去垫一个 reducer 函数,reducer 的路径计算比较复杂, 所以直接报错\n * 同时,从逻辑上讲,如果开启了 mobx,那么必须要有 reducer 文件\n */\n throw Error(`开启 mobx 后,reducer 文件必须存在 ${absFilePath}`);\n }\n chunkCode.push(`export function reducer(){ return {} }`);\n }\n\n const viewPath = resolver.getViewFile(absCurrentDir);\n chunkCode.push(`export { default as view } from '${viewPath}';`);\n\n if (meJSON.theme && !options.theme?.hash) {\n throw Error(`开启页面级主题之前,请优先开启全局主题 ${absFilePath}`);\n }\n\n if (!meJSON.mobx) {\n try {\n const sagaPath = resolver.getSagaFile(absCurrentDir);\n chunkCode.push(`export { default as saga } from '${sagaPath}';`);\n } catch (e) {\n // feat: saga 也可以不存在, 方便结合reactive 和 ak,默认创建一个reducers\n chunkCode.push(`export function* saga(){ return {} }`);\n }\n }\n\n if (meJSON.errorComponent) {\n const errorCompPath = resolver.getErrorComFile(absCurrentDir, meJSON.errorComponent);\n chunkCode.push(`export { default as ErrorComponent } from '${errorCompPath}';`);\n }\n\n if (options.theme?.hash) {\n const themePath = pathService.getThemeJSCacheFileAbs(options.theme?.hash);\n chunkCode.push(`export * from '${themePath}';`);\n }\n\n if (meJSON.theme) {\n fileService.writeThemeFile(meJSON.theme, 'toGlobalTheme');\n const themePath = pathService.getThemeJSCacheFileAbs(meJSON.theme);\n chunkCode.push(`export * from '${themePath}';`);\n }\n\n const meJSONPath = pathService.getMeJSONCacheFileAbs(filepath);\n\n fileService.writeMeJSONFile(meJSONPath, chunkCode);\n\n const isExternal = options.externals?.some?.((x) => x === path.dirname(filepath)) ?? false;\n\n // 处理是否存在多store的场景\n const hasChildStore = globby.sync(`**/*.${options.reducerName}.{t,j}s`, { cwd: absCurrentDir }).length > 0;\n if (hasChildStore && (meJSON.sync || isExternal)) {\n throw Error(`如果开启了Sync模式或当前页面存在于LCD的external中,那么则不支持多Store功能,${absCurrentDir}`);\n }\n\n /** reducers.js */\n reducersGenerator.set(filepath, {\n meJSON,\n isExternal,\n namespace: currentDir,\n meJSONPath: meJSONPath,\n });\n\n /** saga.js */\n sagasGenerator.set(currentDir, {\n meJSON,\n isExternal,\n namespace: currentDir,\n meJSONPath: meJSONPath,\n });\n\n /** router */\n routersGenerator.set(currentDir, {\n meJSON,\n isExternal,\n page: currentDir,\n path: currentDir,\n exact: false,\n meJSONPath: meJSONPath,\n });\n\n /** 处理 /list 的路由 */\n if (new RegExp(`\\/${options.index}$`).test(absCurrentDir)) {\n const _key = absCurrentDir.replace(new RegExp(`\\/${options.index}$`), '');\n routersGenerator.set(_key, {\n meJSON,\n isExternal,\n page: absCurrentDir,\n path: _key,\n exact: true,\n meJSONPath: meJSONPath,\n });\n }\n }\n\n if (options.theme?.hash) {\n fileService.writeThemeFile(options.theme.hash, 'toGlobalTheme');\n }\n\n const list = globby.sync('**/me.json', {\n cwd: pathService.getPageRootAbs(),\n });\n\n if (list.length === 0) {\n console.warn('没有找到me.json文件');\n }\n\n /**\n * glob 的排序 是包含文件名 me.json 的完整路径,存在问题\n * 比如 会将 /xx/ss/me.json 排到 /xx/ss/zz/me.json 前面\n * glob 的 noSort option 会将 文件夹排到前面, 因此需要手动排序, 并且统一成 globby, 速度更快\n */\n const sortedList = list\n .map((filepath) => filepath?.replace(/me.json$/, ''))\n .sort((a, b) => {\n if (a?.startsWith(b)) return -1;\n return a.localeCompare(b, 'en');\n })\n .map((dir) => `${dir}me.json`);\n\n sortedList.forEach((filepath) => {\n resolveFile(filepath);\n });\n\n writeCode();\n\n if (isDev(compiler)) {\n const watcher = chokidar.watch('**/me.json', {\n cwd: pathService.getPageRootAbs(),\n ignoreInitial: true,\n });\n const fn = async (filepath) => {\n await resolveFile(filepath);\n writeCode();\n };\n watcher.on('add', fn);\n watcher.on('addDir', fn);\n watcher.on('change', fn);\n watcher.on('unlink', fn);\n watcher.on('unlinkDir', fn);\n watcher.on('error', fn);\n }\n });\n }\n\n mergeOptions(compiler: Compiler) {\n const defaultOptions = {\n context: compiler.context,\n enablePreFetch: false,\n index: 'list',\n externals: [],\n pageDir: 'component',\n reducerName: 'reducers',\n disableBuiltInRoute: false,\n };\n this.options = deepmerge(defaultOptions, this.options);\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
package/.lecprc.ts
DELETED
package/src/Generator.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { types } from '@babel/core';
|
|
2
|
-
export class Generator<T> {
|
|
3
|
-
protected cache: Map<string, T>;
|
|
4
|
-
constructor() {
|
|
5
|
-
this.cache = new Map<string, T>();
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
set(name: string, value: T) {
|
|
9
|
-
this.cache.set(name, value);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
protected identifierString(arg: string) {
|
|
13
|
-
return arg.replace(/(\/|-)/g, '_');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
protected importDefaultDeclaration(name: string, source: string) {
|
|
17
|
-
return types.importDeclaration(
|
|
18
|
-
[types.importDefaultSpecifier(types.identifier(this.identifierString(name)))],
|
|
19
|
-
types.stringLiteral(source),
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* 创建一条 import 语句, 例如:
|
|
25
|
-
* importNamedDeclaration(['a', 'b'], 'xxx/c') 会生成 import {a, b} from 'xxx/c'
|
|
26
|
-
*
|
|
27
|
-
* 也支持 alias, 例如:
|
|
28
|
-
* importNamedDeclaration([['a', 'aliasName'], 'b'], 'xxx/c') 会生成 import {a as aliasName, b} from 'xxx/c'
|
|
29
|
-
*/
|
|
30
|
-
protected importNamedDeclaration(
|
|
31
|
-
names: Array<string | [name: string, alias: string]>,
|
|
32
|
-
source: string,
|
|
33
|
-
) {
|
|
34
|
-
return types.importDeclaration(
|
|
35
|
-
names.map((x) =>
|
|
36
|
-
typeof x === 'string'
|
|
37
|
-
? types.importSpecifier(types.identifier(x), types.identifier(x))
|
|
38
|
-
: types.importSpecifier(
|
|
39
|
-
types.identifier(this.identifierString(x[1])),
|
|
40
|
-
types.identifier(x[0]),
|
|
41
|
-
),
|
|
42
|
-
),
|
|
43
|
-
types.stringLiteral(source),
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
}
|
package/src/ReducersGenerator.ts
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import babelCore, { transformSync, types } from '@babel/core';
|
|
3
|
-
import type { MeJSON } from './utils';
|
|
4
|
-
import { Generator } from './Generator';
|
|
5
|
-
|
|
6
|
-
interface GetReducersBabelPluginItem {
|
|
7
|
-
meJSON: MeJSON;
|
|
8
|
-
namespace: string;
|
|
9
|
-
isExternal: boolean;
|
|
10
|
-
meJSONPath: string;
|
|
11
|
-
}
|
|
12
|
-
export class ReducersGenerator extends Generator<GetReducersBabelPluginItem> {
|
|
13
|
-
constructor() {
|
|
14
|
-
super();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// TODO: 这里类型 加了个 any, 不太希望写else, 所以导致的问题,ts类型推导似乎不合理
|
|
18
|
-
objectPropertyValue(type: 'call' | 'string' | 'identifier', value: string): any {
|
|
19
|
-
if (type === 'call') {
|
|
20
|
-
return types.callExpression(types.identifier('decorate'), [
|
|
21
|
-
types.identifier(this.identifierString(value)),
|
|
22
|
-
types.stringLiteral(value),
|
|
23
|
-
]);
|
|
24
|
-
}
|
|
25
|
-
if (type === 'string') {
|
|
26
|
-
return types.stringLiteral('');
|
|
27
|
-
}
|
|
28
|
-
if (type === 'identifier') {
|
|
29
|
-
return types.identifier(this.identifierString(value));
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
writeCodeToFile(absPath: string) {
|
|
34
|
-
const items = Array.from(this.cache.values());
|
|
35
|
-
const code = transformSync('', {
|
|
36
|
-
plugins: [
|
|
37
|
-
() => {
|
|
38
|
-
return {
|
|
39
|
-
name: 'babel-plugin-replace-react-redux',
|
|
40
|
-
visitor: {
|
|
41
|
-
Program: {
|
|
42
|
-
enter: (path) => {
|
|
43
|
-
const codes: (
|
|
44
|
-
| babelCore.types.ImportDeclaration
|
|
45
|
-
| babelCore.types.ExportDefaultDeclaration
|
|
46
|
-
)[] = [
|
|
47
|
-
this.importDefaultDeclaration(
|
|
48
|
-
'decorate',
|
|
49
|
-
'rrc-loader-helper/lib/reducer-decorate',
|
|
50
|
-
),
|
|
51
|
-
];
|
|
52
|
-
items
|
|
53
|
-
.filter((x) => x.meJSON.sync || x.isExternal)
|
|
54
|
-
.map((x) =>
|
|
55
|
-
this.importNamedDeclaration([['reducer', x.namespace]], x.meJSONPath),
|
|
56
|
-
)
|
|
57
|
-
.forEach((x) => codes.push(x));
|
|
58
|
-
|
|
59
|
-
const properties = items.map((x) => {
|
|
60
|
-
if (x.isExternal || x.meJSON.sync) {
|
|
61
|
-
if (x.meJSON.mobx) {
|
|
62
|
-
return types.objectProperty(
|
|
63
|
-
types.stringLiteral(x.namespace),
|
|
64
|
-
this.objectPropertyValue('call', x.namespace),
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
return types.objectProperty(
|
|
68
|
-
types.stringLiteral(x.namespace),
|
|
69
|
-
this.objectPropertyValue('identifier', x.namespace),
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
return types.objectProperty(
|
|
73
|
-
types.stringLiteral(x.namespace),
|
|
74
|
-
this.objectPropertyValue('string', x.namespace),
|
|
75
|
-
);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
codes.push(types.exportDefaultDeclaration(types.objectExpression(properties)));
|
|
79
|
-
|
|
80
|
-
path.pushContainer('body', codes);
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
};
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
});
|
|
88
|
-
fs.writeFileSync(absPath, code?.code!, { encoding: 'utf8' });
|
|
89
|
-
}
|
|
90
|
-
}
|
package/src/RoutersGenerator.ts
DELETED
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import { transformSync, types } from '@babel/core';
|
|
3
|
-
import type { Options, MeJSON, PathService } from './utils';
|
|
4
|
-
import { Generator } from './Generator';
|
|
5
|
-
|
|
6
|
-
interface Item {
|
|
7
|
-
meJSONPath: string;
|
|
8
|
-
meJSON: MeJSON;
|
|
9
|
-
isExternal: boolean;
|
|
10
|
-
path: string;
|
|
11
|
-
page: string;
|
|
12
|
-
exact: boolean;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface TransformItem extends Item, MeJSON {}
|
|
16
|
-
|
|
17
|
-
export class RoutersGenerator extends Generator<Item> {
|
|
18
|
-
config: Options;
|
|
19
|
-
pathService: PathService;
|
|
20
|
-
|
|
21
|
-
constructor(config: Options, pathService: PathService) {
|
|
22
|
-
super();
|
|
23
|
-
this.config = config;
|
|
24
|
-
this.pathService = pathService;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
private errorComponentVariableDeclaration() {
|
|
28
|
-
return types.variableDeclaration('const', [
|
|
29
|
-
types.variableDeclarator(
|
|
30
|
-
types.identifier('ErrorComponent'),
|
|
31
|
-
types.arrowFunctionExpression(
|
|
32
|
-
[types.identifier('props')],
|
|
33
|
-
types.blockStatement([
|
|
34
|
-
types.returnStatement(
|
|
35
|
-
types.jsxElement(
|
|
36
|
-
types.jsxOpeningElement(types.jsxIdentifier('div'), [], false),
|
|
37
|
-
types.jsxClosingElement(types.jsxIdentifier('div')),
|
|
38
|
-
[
|
|
39
|
-
types.jsxElement(
|
|
40
|
-
types.jsxOpeningElement(types.jsxIdentifier('h1'), [], false),
|
|
41
|
-
types.jsxClosingElement(types.jsxIdentifier('h1')),
|
|
42
|
-
[types.jsxText('页面渲染发生异常')],
|
|
43
|
-
),
|
|
44
|
-
types.jsxElement(
|
|
45
|
-
types.jsxOpeningElement(types.jsxIdentifier('span'), [], false),
|
|
46
|
-
types.jsxClosingElement(types.jsxIdentifier('span')),
|
|
47
|
-
[
|
|
48
|
-
types.jsxExpressionContainer(
|
|
49
|
-
types.optionalMemberExpression(
|
|
50
|
-
types.memberExpression(
|
|
51
|
-
types.identifier('props'),
|
|
52
|
-
types.identifier('errorStack'),
|
|
53
|
-
),
|
|
54
|
-
types.identifier('message'),
|
|
55
|
-
false,
|
|
56
|
-
true,
|
|
57
|
-
),
|
|
58
|
-
),
|
|
59
|
-
],
|
|
60
|
-
),
|
|
61
|
-
],
|
|
62
|
-
false,
|
|
63
|
-
),
|
|
64
|
-
),
|
|
65
|
-
]),
|
|
66
|
-
),
|
|
67
|
-
),
|
|
68
|
-
]);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
private loadingVariableDeclaration() {
|
|
72
|
-
return types.variableDeclaration('const', [
|
|
73
|
-
types.variableDeclarator(
|
|
74
|
-
types.identifier('Loading'),
|
|
75
|
-
types.arrowFunctionExpression(
|
|
76
|
-
[],
|
|
77
|
-
types.blockStatement([
|
|
78
|
-
types.returnStatement(
|
|
79
|
-
types.jsxFragment(types.jsxOpeningFragment(), types.jsxClosingFragment(), []),
|
|
80
|
-
),
|
|
81
|
-
]),
|
|
82
|
-
),
|
|
83
|
-
),
|
|
84
|
-
]);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
private createDowngradeValue(meJSON: MeJSON) {
|
|
88
|
-
return <T extends keyof MeJSON>(name: T, defaultValue: MeJSON[T]) => {
|
|
89
|
-
/** @ts-ignore */
|
|
90
|
-
return meJSON[name] ?? this.config[name] ?? defaultValue;
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
private transform(item: Item): TransformItem {
|
|
95
|
-
const downgradeValue = this.createDowngradeValue(item.meJSON);
|
|
96
|
-
// 路由参数
|
|
97
|
-
let route = item.meJSON.route ?? '';
|
|
98
|
-
const keepAlive = downgradeValue('keepAlive', false);
|
|
99
|
-
const retain = downgradeValue('retain', false);
|
|
100
|
-
const title = downgradeValue('title', undefined);
|
|
101
|
-
// FUCK keep-alive 特性的坑, 为了兼容同一个页面多次打开 动态拓展 redux 的reducer 节点
|
|
102
|
-
const linkExtendable = downgradeValue('linkExtendable', false);
|
|
103
|
-
route = linkExtendable ? `${route}/:id?` : route;
|
|
104
|
-
let injectStore = downgradeValue('injectStore', false);
|
|
105
|
-
if (injectStore === true) injectStore = 'store';
|
|
106
|
-
return {
|
|
107
|
-
...item,
|
|
108
|
-
route,
|
|
109
|
-
keepAlive,
|
|
110
|
-
retain,
|
|
111
|
-
title,
|
|
112
|
-
linkExtendable,
|
|
113
|
-
injectStore,
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
private pageImportExpression(item: TransformItem) {
|
|
118
|
-
const returnObjectProperties = [
|
|
119
|
-
types.objectProperty(types.identifier('module'), types.identifier('module')),
|
|
120
|
-
];
|
|
121
|
-
if (item.meJSON.sync) {
|
|
122
|
-
returnObjectProperties.push(
|
|
123
|
-
types.objectProperty(types.identifier('sync'), types.booleanLiteral(true)),
|
|
124
|
-
);
|
|
125
|
-
} else {
|
|
126
|
-
returnObjectProperties.push(
|
|
127
|
-
types.objectProperty(types.identifier('sync'), types.booleanLiteral(false)),
|
|
128
|
-
types.objectProperty(types.identifier('reducers'), types.identifier('reducers')),
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
const sourceAst = types.stringLiteral(item.meJSONPath);
|
|
132
|
-
|
|
133
|
-
if (this.config.enablePreFetch) {
|
|
134
|
-
types.addComment(sourceAst, 'leading', 'webpackPrefetch: true');
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return types.callExpression(
|
|
138
|
-
types.memberExpression(
|
|
139
|
-
types.callExpression(types.import(), [sourceAst]),
|
|
140
|
-
types.identifier('then'),
|
|
141
|
-
),
|
|
142
|
-
[
|
|
143
|
-
types.arrowFunctionExpression(
|
|
144
|
-
[types.identifier('module')],
|
|
145
|
-
types.blockStatement([
|
|
146
|
-
// TODO
|
|
147
|
-
types.returnStatement(types.objectExpression(returnObjectProperties)),
|
|
148
|
-
]),
|
|
149
|
-
),
|
|
150
|
-
],
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
private loadableCallExpression(item: TransformItem) {
|
|
155
|
-
return types.callExpression(types.identifier('Loadable'), [
|
|
156
|
-
types.objectExpression([
|
|
157
|
-
types.objectProperty(
|
|
158
|
-
types.identifier('title'),
|
|
159
|
-
item.title ? types.stringLiteral(item.title) : types.nullLiteral(),
|
|
160
|
-
),
|
|
161
|
-
types.objectProperty(types.identifier('keepAlive'), types.booleanLiteral(item.keepAlive!)),
|
|
162
|
-
types.objectProperty(types.identifier('route'), types.stringLiteral(item.route!)),
|
|
163
|
-
types.objectProperty(types.identifier('retain'), types.booleanLiteral(item.retain!)),
|
|
164
|
-
types.objectProperty(
|
|
165
|
-
types.identifier('injectStore'),
|
|
166
|
-
typeof item.injectStore === 'boolean'
|
|
167
|
-
? types.booleanLiteral(item.injectStore)
|
|
168
|
-
: types.stringLiteral(item.injectStore!),
|
|
169
|
-
),
|
|
170
|
-
types.objectProperty(types.identifier('page'), types.stringLiteral(item.page)),
|
|
171
|
-
types.objectProperty(types.identifier('loading'), types.identifier('Loading')),
|
|
172
|
-
types.objectProperty(
|
|
173
|
-
types.identifier('errorComponent'),
|
|
174
|
-
types.identifier('ErrorComponent'),
|
|
175
|
-
),
|
|
176
|
-
types.objectProperty(
|
|
177
|
-
types.identifier('metaInfo'),
|
|
178
|
-
types.callExpression(
|
|
179
|
-
types.memberExpression(types.identifier('JSON'), types.identifier('parse')),
|
|
180
|
-
[types.stringLiteral(JSON.stringify(item.meJSON))],
|
|
181
|
-
),
|
|
182
|
-
),
|
|
183
|
-
types.objectProperty(
|
|
184
|
-
types.identifier('loader'),
|
|
185
|
-
types.arrowFunctionExpression([], this.pageImportExpression(item)),
|
|
186
|
-
),
|
|
187
|
-
]),
|
|
188
|
-
]);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
writeCodeToFile(absPath: string) {
|
|
192
|
-
const items = Array.from(this.cache.values());
|
|
193
|
-
const code = transformSync('', {
|
|
194
|
-
plugins: [
|
|
195
|
-
() => {
|
|
196
|
-
return {
|
|
197
|
-
name: 'babel-plugin-replace-react-redux',
|
|
198
|
-
visitor: {
|
|
199
|
-
Program: {
|
|
200
|
-
enter: (path) => {
|
|
201
|
-
const ast: (
|
|
202
|
-
| types.ImportDeclaration
|
|
203
|
-
| types.VariableDeclaration
|
|
204
|
-
| types.ExportDefaultDeclaration
|
|
205
|
-
| types.ExpressionStatement
|
|
206
|
-
)[] = [
|
|
207
|
-
this.importNamedDeclaration([], 'rrc-loader-helper/lib/fake-react'),
|
|
208
|
-
this.importDefaultDeclaration('Loadable', 'rrc-loader-helper/lib/loadable'),
|
|
209
|
-
this.importDefaultDeclaration('React', 'react'),
|
|
210
|
-
];
|
|
211
|
-
|
|
212
|
-
/** 如果用户没有指定loading组件,那么自动生成一个空 loading */
|
|
213
|
-
if (this.config.loading) {
|
|
214
|
-
ast.push(this.importDefaultDeclaration('Loading', this.config.loading));
|
|
215
|
-
} else {
|
|
216
|
-
ast.push(this.loadingVariableDeclaration());
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (this.config.errorComponent) {
|
|
220
|
-
ast.push(
|
|
221
|
-
this.importDefaultDeclaration('ErrorComponent', this.config.errorComponent),
|
|
222
|
-
);
|
|
223
|
-
} else {
|
|
224
|
-
ast.push(this.errorComponentVariableDeclaration());
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
if (this.config.theme?.hash) {
|
|
228
|
-
ast.push(
|
|
229
|
-
this.importNamedDeclaration(
|
|
230
|
-
['toGlobalTheme'],
|
|
231
|
-
this.pathService.getThemeJSCacheFileAbs(this.config.theme?.hash),
|
|
232
|
-
),
|
|
233
|
-
);
|
|
234
|
-
ast.push(
|
|
235
|
-
types.expressionStatement(
|
|
236
|
-
types.optionalCallExpression(types.identifier('toGlobalTheme'), [], true),
|
|
237
|
-
),
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const _ = items
|
|
242
|
-
.filter((x) => !x.isExternal)
|
|
243
|
-
.map((x) => this.transform(x))
|
|
244
|
-
.map((x) => {
|
|
245
|
-
const path =
|
|
246
|
-
this.config.dangerousRoute || !x.exact
|
|
247
|
-
? `/${x.path}${x.route}`
|
|
248
|
-
: `/${x.path}`;
|
|
249
|
-
return types.objectExpression([
|
|
250
|
-
types.objectProperty(
|
|
251
|
-
types.identifier('exact'),
|
|
252
|
-
types.booleanLiteral(x.exact),
|
|
253
|
-
),
|
|
254
|
-
types.objectProperty(
|
|
255
|
-
types.identifier('keepAlive'),
|
|
256
|
-
types.booleanLiteral(x.keepAlive!),
|
|
257
|
-
),
|
|
258
|
-
types.objectProperty(types.identifier('key'), types.stringLiteral(path)),
|
|
259
|
-
types.objectProperty(types.identifier('path'), types.stringLiteral(path)),
|
|
260
|
-
types.objectProperty(
|
|
261
|
-
types.identifier('component'),
|
|
262
|
-
this.loadableCallExpression(x),
|
|
263
|
-
),
|
|
264
|
-
]);
|
|
265
|
-
});
|
|
266
|
-
ast.push(
|
|
267
|
-
types.exportDefaultDeclaration(
|
|
268
|
-
types.arrowFunctionExpression(
|
|
269
|
-
[types.identifier('reducers')],
|
|
270
|
-
types.blockStatement([types.returnStatement(types.arrayExpression(_))]),
|
|
271
|
-
),
|
|
272
|
-
),
|
|
273
|
-
);
|
|
274
|
-
|
|
275
|
-
path.pushContainer('body', ast);
|
|
276
|
-
},
|
|
277
|
-
},
|
|
278
|
-
},
|
|
279
|
-
};
|
|
280
|
-
},
|
|
281
|
-
],
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
fs.writeFileSync(
|
|
285
|
-
absPath,
|
|
286
|
-
[
|
|
287
|
-
JSON.stringify(`👹 pages total count is ${Array.from(this.cache.keys()).length}`),
|
|
288
|
-
code?.code!,
|
|
289
|
-
].join(';\r\n'),
|
|
290
|
-
{
|
|
291
|
-
encoding: 'utf8',
|
|
292
|
-
},
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
}
|
package/src/SagasGenerator.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { Generator } from './Generator';
|
|
2
|
-
import type { MeJSON } from './utils';
|
|
3
|
-
import { transformSync, types } from '@babel/core';
|
|
4
|
-
import fs from 'fs';
|
|
5
|
-
interface Item {
|
|
6
|
-
namespace: string;
|
|
7
|
-
meJSONPath: string;
|
|
8
|
-
isExternal: boolean;
|
|
9
|
-
meJSON: MeJSON;
|
|
10
|
-
}
|
|
11
|
-
export class SagasGenerator extends Generator<Item> {
|
|
12
|
-
constructor() {
|
|
13
|
-
super();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
private setCtxExpressionStatement(namespace: string) {
|
|
17
|
-
return types.expressionStatement(
|
|
18
|
-
types.yieldExpression(
|
|
19
|
-
types.callExpression(types.identifier('setCtx'), [
|
|
20
|
-
types.objectExpression([
|
|
21
|
-
types.objectProperty(types.identifier('mobxStyle'), types.booleanLiteral(true)),
|
|
22
|
-
types.objectProperty(types.identifier('page'), types.stringLiteral(namespace)),
|
|
23
|
-
types.objectProperty(types.identifier('url'), types.stringLiteral('')),
|
|
24
|
-
]),
|
|
25
|
-
]),
|
|
26
|
-
),
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
private callExpressionStatement(namespace: string) {
|
|
31
|
-
return types.expressionStatement(
|
|
32
|
-
types.yieldExpression(
|
|
33
|
-
types.callExpression(types.identifier('call'), [
|
|
34
|
-
types.memberExpression(
|
|
35
|
-
types.identifier(this.identifierString(namespace)),
|
|
36
|
-
types.identifier('saga'),
|
|
37
|
-
),
|
|
38
|
-
]),
|
|
39
|
-
),
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
writeCodeToFile(absPath: string) {
|
|
44
|
-
const items = Array.from(this.cache.values());
|
|
45
|
-
const code = transformSync('', {
|
|
46
|
-
plugins: [
|
|
47
|
-
() => {
|
|
48
|
-
return {
|
|
49
|
-
visitor: {
|
|
50
|
-
Program: {
|
|
51
|
-
enter: (path) => {
|
|
52
|
-
const ast: (types.ImportDeclaration | types.ExportDefaultDeclaration)[] = [
|
|
53
|
-
this.importNamedDeclaration(['setCtx'], 'rrc-loader-helper/lib/retain'),
|
|
54
|
-
this.importNamedDeclaration(
|
|
55
|
-
['call'],
|
|
56
|
-
'rrc-loader-helper/lib/sagas/redux-saga/effects',
|
|
57
|
-
),
|
|
58
|
-
];
|
|
59
|
-
|
|
60
|
-
items
|
|
61
|
-
.filter((x) => x.meJSON.sync || x.isExternal)
|
|
62
|
-
.forEach((x) =>
|
|
63
|
-
// 如果是mobx, 取 reducer, 否则取 saga
|
|
64
|
-
ast.push(
|
|
65
|
-
this.importNamedDeclaration(
|
|
66
|
-
[[x.meJSON.mobx ? 'reducer' : 'saga', x.namespace]],
|
|
67
|
-
x.meJSONPath,
|
|
68
|
-
),
|
|
69
|
-
),
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
const arrayItem = items.map((x) => {
|
|
73
|
-
if (!x.isExternal && !x.meJSON.sync) {
|
|
74
|
-
return types.stringLiteral('');
|
|
75
|
-
}
|
|
76
|
-
if (x.meJSON.mobx) {
|
|
77
|
-
return types.functionExpression(
|
|
78
|
-
null,
|
|
79
|
-
[],
|
|
80
|
-
types.blockStatement([
|
|
81
|
-
this.setCtxExpressionStatement(x.namespace),
|
|
82
|
-
this.callExpressionStatement(x.namespace),
|
|
83
|
-
]),
|
|
84
|
-
true,
|
|
85
|
-
false,
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
return types.identifier(this.identifierString(x.namespace));
|
|
89
|
-
});
|
|
90
|
-
ast.push(types.exportDefaultDeclaration(types.arrayExpression(arrayItem)));
|
|
91
|
-
path.pushContainer('body', ast);
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
},
|
|
97
|
-
],
|
|
98
|
-
});
|
|
99
|
-
fs.writeFileSync(absPath, code?.code!, { encoding: 'utf8' });
|
|
100
|
-
}
|
|
101
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import type { Compiler, WebpackPluginInstance } from 'webpack';
|
|
2
|
-
import globby from 'globby';
|
|
3
|
-
import chokidar from 'chokidar';
|
|
4
|
-
import deepmerge from 'deepmerge';
|
|
5
|
-
import { PathService, Resolver, Options, FileService } from './utils';
|
|
6
|
-
import { ReducersGenerator } from './ReducersGenerator';
|
|
7
|
-
import { SagasGenerator } from './SagasGenerator';
|
|
8
|
-
import { RoutersGenerator } from './RoutersGenerator';
|
|
9
|
-
|
|
10
|
-
import path from 'node:path';
|
|
11
|
-
|
|
12
|
-
export default class LcdRouterWebpackPlugin implements WebpackPluginInstance {
|
|
13
|
-
options: Options;
|
|
14
|
-
constructor(options: Options) {
|
|
15
|
-
this.options = options;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
apply(compiler: Compiler) {
|
|
19
|
-
this.mergeOptions(compiler);
|
|
20
|
-
|
|
21
|
-
compiler.hooks.afterPlugins.tap('LcdRouterWebpackPlugin', (compiler) => {
|
|
22
|
-
const options = this.options;
|
|
23
|
-
|
|
24
|
-
const pathService = new PathService(options);
|
|
25
|
-
const resolver = new Resolver(compiler, options);
|
|
26
|
-
const fileService = new FileService(pathService);
|
|
27
|
-
|
|
28
|
-
const reducersGenerator = new ReducersGenerator();
|
|
29
|
-
const sagasGenerator = new SagasGenerator();
|
|
30
|
-
const routersGenerator = new RoutersGenerator(options, pathService);
|
|
31
|
-
|
|
32
|
-
function isDev(compiler) {
|
|
33
|
-
if (compiler.options.mode === 'production' || process.env.NODE_ENV === 'production') return false;
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function writeCode() {
|
|
38
|
-
reducersGenerator.writeCodeToFile(pathService.getReducersCacheFileAbs());
|
|
39
|
-
sagasGenerator.writeCodeToFile(pathService.getSagasCacheFileAbs());
|
|
40
|
-
routersGenerator.writeCodeToFile(pathService.getRoutersCacheFileAbs());
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function resolveFile(filepath: string) {
|
|
44
|
-
const absFilePath = pathService.getCurrentFileAbs(filepath);
|
|
45
|
-
const currentDir = path.dirname(filepath);
|
|
46
|
-
const absCurrentDir = path.dirname(absFilePath);
|
|
47
|
-
|
|
48
|
-
const chunkCode = [] as string[];
|
|
49
|
-
const meJSON = fileService.readJSONSync(absFilePath);
|
|
50
|
-
try {
|
|
51
|
-
const reducerPath = resolver.getReducerFile(absCurrentDir);
|
|
52
|
-
chunkCode.push(`export { default as reducer } from '${reducerPath}';`);
|
|
53
|
-
} catch (e) {
|
|
54
|
-
// feat: reducers 可以不存在, 方便结合reactive 和 ak,默认创建一个reducers
|
|
55
|
-
if (meJSON.mobx) {
|
|
56
|
-
/**
|
|
57
|
-
* mobx 模式下, 需要垫一个被 mobx-adapter 包裹的 reducer 函数
|
|
58
|
-
* 如果存在reducer文件,是默认会被 babel-plugin-enhance-reducer 处理的
|
|
59
|
-
*
|
|
60
|
-
* import storeHoc from 'rrc-loader-helper/lib/mobx-adapter';
|
|
61
|
-
* export const reducer = storeHoc({
|
|
62
|
-
* state: {},
|
|
63
|
-
* }, 'report/other-table')
|
|
64
|
-
*
|
|
65
|
-
* 不太方便去垫一个 reducer 函数,reducer 的路径计算比较复杂, 所以直接报错
|
|
66
|
-
* 同时,从逻辑上讲,如果开启了 mobx,那么必须要有 reducer 文件
|
|
67
|
-
*/
|
|
68
|
-
throw Error('开启 mobx 后,reducer 文件必须存在');
|
|
69
|
-
}
|
|
70
|
-
chunkCode.push(`export function reducer(){ return {} }`);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const viewPath = resolver.getViewFile(absCurrentDir);
|
|
74
|
-
chunkCode.push(`export { default as view } from '${viewPath}';`);
|
|
75
|
-
|
|
76
|
-
if (meJSON.theme && !options.theme?.hash) {
|
|
77
|
-
throw Error(`开启页面级主题之前,请优先开启全局主题 ${absFilePath}`);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (!meJSON.mobx) {
|
|
81
|
-
try {
|
|
82
|
-
const sagaPath = resolver.getSagaFile(absCurrentDir);
|
|
83
|
-
chunkCode.push(`export { default as saga } from '${sagaPath}';`);
|
|
84
|
-
} catch (e) {
|
|
85
|
-
// feat: saga 也可以不存在, 方便结合reactive 和 ak,默认创建一个reducers
|
|
86
|
-
chunkCode.push(`export function saga*(){ return {} }`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (meJSON.errorComponent) {
|
|
91
|
-
const errorCompPath = resolver.getErrorComFile(absCurrentDir, meJSON.errorComponent);
|
|
92
|
-
chunkCode.push(`export { default as ErrorComponent } from '${errorCompPath}';`);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (options.theme?.hash) {
|
|
96
|
-
const themePath = pathService.getThemeJSCacheFileAbs(options.theme?.hash);
|
|
97
|
-
chunkCode.push(`export * from '${themePath}';`);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (meJSON.theme) {
|
|
101
|
-
fileService.writeThemeFile(meJSON.theme, 'toGlobalTheme');
|
|
102
|
-
const themePath = pathService.getThemeJSCacheFileAbs(meJSON.theme);
|
|
103
|
-
chunkCode.push(`export * from '${themePath}';`);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const meJSONPath = pathService.getMeJSONCacheFileAbs(filepath);
|
|
107
|
-
|
|
108
|
-
fileService.writeMeJSONFile(meJSONPath, chunkCode);
|
|
109
|
-
|
|
110
|
-
const isExternal = options.externals?.some?.((x) => x === path.dirname(filepath)) ?? false;
|
|
111
|
-
|
|
112
|
-
// 处理是否存在多store的场景
|
|
113
|
-
const hasChildStore = globby.sync(`**/*.${options.reducerName}.{t,j}s`, { cwd: absCurrentDir }).length > 0;
|
|
114
|
-
if (hasChildStore && (meJSON.sync || isExternal)) {
|
|
115
|
-
throw Error(`如果开启了Sync模式或当前页面存在于LCD的external中,那么则不支持多Store功能,${absCurrentDir}`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/** reducers.js */
|
|
119
|
-
reducersGenerator.set(filepath, {
|
|
120
|
-
meJSON,
|
|
121
|
-
isExternal,
|
|
122
|
-
namespace: currentDir,
|
|
123
|
-
meJSONPath: meJSONPath,
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
/** saga.js */
|
|
127
|
-
sagasGenerator.set(currentDir, {
|
|
128
|
-
meJSON,
|
|
129
|
-
isExternal,
|
|
130
|
-
namespace: currentDir,
|
|
131
|
-
meJSONPath: meJSONPath,
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
/** router */
|
|
135
|
-
routersGenerator.set(currentDir, {
|
|
136
|
-
meJSON,
|
|
137
|
-
isExternal,
|
|
138
|
-
page: currentDir,
|
|
139
|
-
path: currentDir,
|
|
140
|
-
exact: false,
|
|
141
|
-
meJSONPath: meJSONPath,
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
/** 处理 /list 的路由 */
|
|
145
|
-
if (new RegExp(`\/${options.index}$`).test(absCurrentDir)) {
|
|
146
|
-
const _key = absCurrentDir.replace(new RegExp(`\/${options.index}$`), '');
|
|
147
|
-
routersGenerator.set(_key, {
|
|
148
|
-
meJSON,
|
|
149
|
-
isExternal,
|
|
150
|
-
page: absCurrentDir,
|
|
151
|
-
path: _key,
|
|
152
|
-
exact: true,
|
|
153
|
-
meJSONPath: meJSONPath,
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (options.theme?.hash) {
|
|
159
|
-
fileService.writeThemeFile(options.theme.hash, 'toGlobalTheme');
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const list = globby.sync('**/me.json', {
|
|
163
|
-
cwd: pathService.getPageRootAbs(),
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
if (list.length === 0) {
|
|
167
|
-
console.warn('没有找到me.json文件');
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* glob 的排序 是包含文件名 me.json 的完整路径,存在问题
|
|
172
|
-
* 比如 会将 /xx/ss/me.json 排到 /xx/ss/zz/me.json 前面
|
|
173
|
-
* glob 的 noSort option 会将 文件夹排到前面, 因此需要手动排序, 并且统一成 globby, 速度更快
|
|
174
|
-
*/
|
|
175
|
-
const sortedList = list
|
|
176
|
-
.map((filepath) => filepath?.replace(/me.json$/, ''))
|
|
177
|
-
.sort((a, b) => {
|
|
178
|
-
if (a?.startsWith(b)) return -1;
|
|
179
|
-
return a.localeCompare(b, 'en');
|
|
180
|
-
})
|
|
181
|
-
.map((dir) => `${dir}me.json`);
|
|
182
|
-
|
|
183
|
-
sortedList.forEach((filepath) => {
|
|
184
|
-
resolveFile(filepath);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
writeCode();
|
|
188
|
-
|
|
189
|
-
if (isDev(compiler)) {
|
|
190
|
-
const watcher = chokidar.watch('**/me.json', {
|
|
191
|
-
cwd: pathService.getPageRootAbs(),
|
|
192
|
-
ignoreInitial: true,
|
|
193
|
-
});
|
|
194
|
-
const fn = async (filepath) => {
|
|
195
|
-
await resolveFile(filepath);
|
|
196
|
-
writeCode();
|
|
197
|
-
};
|
|
198
|
-
watcher.on('add', fn);
|
|
199
|
-
watcher.on('addDir', fn);
|
|
200
|
-
watcher.on('change', fn);
|
|
201
|
-
watcher.on('unlink', fn);
|
|
202
|
-
watcher.on('unlinkDir', fn);
|
|
203
|
-
watcher.on('error', fn);
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
mergeOptions(compiler: Compiler) {
|
|
209
|
-
const defaultOptions = {
|
|
210
|
-
context: compiler.context,
|
|
211
|
-
enablePreFetch: false,
|
|
212
|
-
index: 'list',
|
|
213
|
-
externals: [],
|
|
214
|
-
pageDir: 'component',
|
|
215
|
-
reducerName: 'reducers',
|
|
216
|
-
disableBuiltInRoute: false,
|
|
217
|
-
};
|
|
218
|
-
this.options = deepmerge(defaultOptions, this.options);
|
|
219
|
-
}
|
|
220
|
-
}
|
package/src/utils/files.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import fse from 'fs-extra';
|
|
2
|
-
import { PathService } from './paths';
|
|
3
|
-
import fetchSync from 'sync-fetch';
|
|
4
|
-
|
|
5
|
-
export class FileService {
|
|
6
|
-
pathService: PathService;
|
|
7
|
-
|
|
8
|
-
constructor(pathService) {
|
|
9
|
-
this.pathService = pathService;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
writeFileSync = (path: string, content: string) => {
|
|
13
|
-
fse.outputFileSync(path, content, { encoding: 'utf8' });
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* 创建 meJSON.js 文件, 包含部分内容
|
|
18
|
-
*/
|
|
19
|
-
writeMeJSONFile = (filepath: string, chunkCode: string[]) => {
|
|
20
|
-
const code = chunkCode.join('\n');
|
|
21
|
-
this.writeFileSync(filepath, code);
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* 书写主题文件
|
|
26
|
-
*/
|
|
27
|
-
writeThemeFile = (hash: string, funcName: string) => {
|
|
28
|
-
const code = this.fetchThemeFileContent(hash);
|
|
29
|
-
const target = this.pathService.getThemeJSCacheFileAbs(hash);
|
|
30
|
-
if (!fse.pathExistsSync(target)) {
|
|
31
|
-
fse.outputFileSync(target, ` export function ${funcName}(){ ${code} }`, { encoding: 'utf8' });
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* 获取 主题 文件内容
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
fetchThemeFileContent = (hash: string) => {
|
|
40
|
-
// TODO: 需要加错误处理, 以及重试机制
|
|
41
|
-
const code = fetchSync(`https://assets.dotfashion.cn/unpkg/@shein-components/shineout-theme@0.0.0-${hash}/index.js`).text();
|
|
42
|
-
if (!code.includes('(function(){')) {
|
|
43
|
-
throw new Error(`获取主题文件失败,hash:${hash}`);
|
|
44
|
-
}
|
|
45
|
-
return code;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* 读 json 文件
|
|
50
|
-
*/
|
|
51
|
-
readJSONSync = (path: string) => {
|
|
52
|
-
return fse.readJSONSync(path, { encoding: 'utf8' });
|
|
53
|
-
};
|
|
54
|
-
}
|
package/src/utils/index.ts
DELETED
package/src/utils/paths.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import type { Options } from '../utils';
|
|
3
|
-
|
|
4
|
-
export const dir = 'lessCoding';
|
|
5
|
-
|
|
6
|
-
export const themes = 'themes';
|
|
7
|
-
|
|
8
|
-
export const LcdTempDir = '.lego';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 路径处理服务
|
|
12
|
-
*/
|
|
13
|
-
export class PathService {
|
|
14
|
-
options: Options;
|
|
15
|
-
|
|
16
|
-
legoAbs: string;
|
|
17
|
-
|
|
18
|
-
constructor(options) {
|
|
19
|
-
this.options = options;
|
|
20
|
-
this.legoAbs = path.join(this.options.context!, 'src', LcdTempDir);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* 页面根目录绝对路径
|
|
25
|
-
* 通常都是
|
|
26
|
-
* - src
|
|
27
|
-
* - components
|
|
28
|
-
* */
|
|
29
|
-
getPageRootAbs() {
|
|
30
|
-
return path.join(this.options.context!, 'src', this.options.pageDir);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
getSrcRootAbs() {
|
|
34
|
-
return path.join(this.options.context!, 'src');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* 当前文件的绝对路径
|
|
39
|
-
* */
|
|
40
|
-
getCurrentFileAbs(relativeFilePath: string) {
|
|
41
|
-
return path.join(this.getPageRootAbs(), relativeFilePath);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** 当前文件的绝对目录路径 */
|
|
45
|
-
getCurrentDirAbs(relativeFilePath: string) {
|
|
46
|
-
return path.join(this.getPageRootAbs(), path.dirname(relativeFilePath));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** 生成的 reducers 文件路径 */
|
|
50
|
-
getReducersCacheFileAbs() {
|
|
51
|
-
return path.join(this.legoAbs, dir, 'reducers.js');
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** 生成的 sagas 文件路径 */
|
|
55
|
-
getSagasCacheFileAbs() {
|
|
56
|
-
return path.join(this.legoAbs, dir, 'sagas.js');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/** 生成的 routers 文件路径 */
|
|
60
|
-
getRoutersCacheFileAbs() {
|
|
61
|
-
return path.join(this.legoAbs, dir, 'routers.js');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** 主题文件cache 的路径 */
|
|
65
|
-
getThemeJSCacheFileAbs(hash: string) {
|
|
66
|
-
return path.join(this.legoAbs, dir, themes, `${hash}.js`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** 获取 mejson 编译后的文件路径 */
|
|
70
|
-
getMeJSONCacheFileAbs(relativeFilePath: string) {
|
|
71
|
-
return path.join(this.legoAbs, dir, 'me-json', this.getMeJsonCacheFileName(relativeFilePath));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
getMeJsonCacheFileName(relativeFilePath: string) {
|
|
75
|
-
return relativeFilePath.replace(/(.*)\/me\.json$/, '$1.js').replace(/\//g, '-_-');
|
|
76
|
-
}
|
|
77
|
-
}
|
package/src/utils/resolver.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { create } from 'enhanced-resolve';
|
|
2
|
-
import type { Compiler } from 'webpack';
|
|
3
|
-
import type { Options } from './types';
|
|
4
|
-
|
|
5
|
-
export class Resolver {
|
|
6
|
-
resolver: any;
|
|
7
|
-
options: Options;
|
|
8
|
-
constructor(compiler: Compiler, options: Options) {
|
|
9
|
-
this.options = options;
|
|
10
|
-
this.resolver = create.sync({
|
|
11
|
-
extensions: compiler.options.resolve.extensions,
|
|
12
|
-
alias: compiler.options.resolve.alias,
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* 获取 当前目录下 reducer文件的路径
|
|
18
|
-
*/
|
|
19
|
-
getReducerFile = (dirname) => this.resolver(dirname, `./${this.options.reducerName}`);
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* 获取 当前目录下 view文件的路径
|
|
23
|
-
*/
|
|
24
|
-
getViewFile = (dirname) => this.resolver(dirname, `./view`);
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 获取 当前目录下 saga 文件的路径
|
|
28
|
-
* @param isMobx 如果是 mobx 则返回 reducers 的地址
|
|
29
|
-
*/
|
|
30
|
-
getSagaFile = (dirname, isMobx?: boolean) =>
|
|
31
|
-
isMobx ? this.getReducerFile(dirname) : this.resolver(dirname, `./saga`);
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* 获取 me.json 配置的 errorComponent 地址
|
|
35
|
-
*/
|
|
36
|
-
getErrorComFile = (dirname, errorComponent) => this.resolver(dirname, errorComponent);
|
|
37
|
-
}
|
package/src/utils/types.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
export interface Options {
|
|
2
|
-
/**
|
|
3
|
-
* 组件上下文, 默认取 compiler.context
|
|
4
|
-
* @default compiler.context
|
|
5
|
-
*/
|
|
6
|
-
context?: string;
|
|
7
|
-
/**
|
|
8
|
-
* 是否禁用内置路由
|
|
9
|
-
* 默认会将 react-router-dom 转换到 rrc-loader-helper/router
|
|
10
|
-
* 如果你是新项目,建议将该配置配置为true,因为内置路由针对react-router做了大量的改动,可能会引起一些无法预测的故障
|
|
11
|
-
* @default false
|
|
12
|
-
*/
|
|
13
|
-
disableBuiltInRoute?: boolean;
|
|
14
|
-
/**
|
|
15
|
-
* 是否开启 webpack prefetch预加载
|
|
16
|
-
* @default false
|
|
17
|
-
*/
|
|
18
|
-
enablePreFetch?: boolean;
|
|
19
|
-
/**
|
|
20
|
-
* 指定页面路径 不进行注册路由
|
|
21
|
-
* @default []
|
|
22
|
-
*/
|
|
23
|
-
externals?: string[];
|
|
24
|
-
/**
|
|
25
|
-
* 页面目录
|
|
26
|
-
* @default component
|
|
27
|
-
*/
|
|
28
|
-
pageDir: string;
|
|
29
|
-
/**
|
|
30
|
-
* shineout 主题
|
|
31
|
-
*/
|
|
32
|
-
theme?: {
|
|
33
|
-
hash: string;
|
|
34
|
-
};
|
|
35
|
-
/**
|
|
36
|
-
* reducer 文件名称
|
|
37
|
-
* @default reducers
|
|
38
|
-
*/
|
|
39
|
-
reducerName: string;
|
|
40
|
-
/**
|
|
41
|
-
* loading 组件路径
|
|
42
|
-
*/
|
|
43
|
-
loading?: string;
|
|
44
|
-
/**
|
|
45
|
-
* 一个神奇的属性,用于处理 /xxx/order/list 这种路由过长的问题
|
|
46
|
-
* 也可以用来作为父路由的默认路由目录
|
|
47
|
-
* 会生成一个新路由 /xxx/order,实际目录指向为 /xxx/order/list
|
|
48
|
-
* @default list
|
|
49
|
-
*/
|
|
50
|
-
index?: string;
|
|
51
|
-
/**
|
|
52
|
-
* 渲染出错时的组件地址
|
|
53
|
-
*/
|
|
54
|
-
errorComponent?: string;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* 是否允许页面内生成自定义路由
|
|
58
|
-
* 例如在 component/order/detail/me.json 中 配置 route: '/:id',此时会生成动态路由 /order/detail/:id
|
|
59
|
-
* 非常不推荐使用的一个属性,因为此功能受 me.json 中 exact 属性影响, 仅当 exact: true 时候,才不会拼接路由
|
|
60
|
-
* 当开启 dangerousRoute 后, 不再受 exact 影响, 都会生成 拼接路由 /order/detail/:id
|
|
61
|
-
* @default false
|
|
62
|
-
*/
|
|
63
|
-
dangerousRoute?: boolean;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface MeJSON {
|
|
67
|
-
theme?: string;
|
|
68
|
-
sync?: boolean;
|
|
69
|
-
mobx?: boolean;
|
|
70
|
-
keepAlive?: boolean;
|
|
71
|
-
retain?: boolean;
|
|
72
|
-
title?: string;
|
|
73
|
-
linkExtendable?: boolean;
|
|
74
|
-
injectStore?: boolean | string;
|
|
75
|
-
route?: string;
|
|
76
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"moduleResolution": "Node",
|
|
4
|
-
"target": "ES5",
|
|
5
|
-
"esModuleInterop": true,
|
|
6
|
-
"jsx": "react",
|
|
7
|
-
"lib": ["ESNext"],
|
|
8
|
-
"sourceMap": true,
|
|
9
|
-
"noEmitOnError": true,
|
|
10
|
-
"allowSyntheticDefaultImports": true,
|
|
11
|
-
"declaration": true,
|
|
12
|
-
"declarationDir": "lib"
|
|
13
|
-
}
|
|
14
|
-
}
|