UNPKG

@foolishchow/vue-cli-plugin-ts-router-gen

Version:
370 lines (369 loc) 16.3 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); var tsutil_1 = require("@foolishchow/tsutil"); var fs = __importStar(require("fs")); var path_1 = require("path"); var ts = __importStar(require("typescript")); var debounce_1 = require("./debounce"); var glob_utils_1 = require("./glob-utils"); var route_template_1 = require("./route-template"); var events_1 = require("events"); var isSameExport = function (from, to) { if (from === void 0) { from = {}; } if (to === void 0) { to = {}; } return (from.pageName == to.pageName && from.path == to.path && from.title == to.title && from.parent == to.parent && from.show == to.show && from.sort == to.sort && from.meta == to.meta); }; var Programer = /** @class */ (function (_super) { __extends(Programer, _super); function Programer(config, watch) { if (watch === void 0) { watch = true; } var _this = _super.call(this) || this; _this.config = config; _this.watch = watch; _this.cacher = new Map(); _this.RouteNames = new Set(); _this.CachedNames = new Map(); _this.routeFile = path_1.resolve(process.cwd(), config.file); _this.routePath = path_1.dirname(_this.routeFile); _this.emit = debounce_1.debounce(_this.emit, 500); _this.init(); return _this; } Programer.prototype.init = function () { return __awaiter(this, void 0, void 0, function () { var watcher, files; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!this.watch) return [3 /*break*/, 1]; watcher = glob_utils_1.Watch(this.config.glob); watcher.on("change", function (path, stat) { _this.parseFile(path, Date.now()); }); watcher.on("add", function (path, stat) { // console.info("add", path) _this.parseFile(path, Date.now()); }); watcher.on("unlink", function (path, stat) { // console.info("unlink", path) _this.cacher.delete(path); _this.emitFile(); }); return [3 /*break*/, 3]; case 1: return [4 /*yield*/, glob_utils_1.Glob(this.config.glob)]; case 2: files = _a.sent(); files.forEach(function (file) { return _this.parseFile(file, Date.now()); }); _a.label = 3; case 3: return [2 /*return*/]; } }); }); }; Programer.prototype.resloveRoutePath = function (fileName, path) { if (path === void 0) { path = ""; } var routePath = fileName.replace(this.config.root, "").replace(/\.tsx?$/, "").split(path_1.sep).join("/") + "/" + path; return routePath.replace(/\/+/g, "/").replace(/\/index\/?$/, "/"); }; Programer.prototype.parseFile = function (fileName, time) { var _this = this; var content = fs.readFileSync(path_1.resolve(process.cwd(), fileName)).toString(); var sourcefile = ts.createSourceFile(fileName, content, ts.ScriptTarget.ESNext); var pageConfigs = tsutil_1.$(sourcefile).find("ClassDeclaration").map(function (node) { var ClassDeclaration = node; if (isExported(ClassDeclaration) && ClassDeclaration.decorators) { var name_1 = (ClassDeclaration.name); if (name_1) { var tags = parseJsDoc(ClassDeclaration); if (tags.show == undefined) tags.show = true; if (tags.ignore || !tags.title) { _this.cacher.delete(fileName); } else { var config = { path: tags.path ? tags.path.toString() : _this.resloveRoutePath(fileName, (tags.path || "").toString()), pageName: name_1.text, title: (tags.title || "").toString(), show: tags.show, sort: tags.sort || 255, meta: new Function("return " + (tags.meta || "{}"))(), extra: tags.extra }; if (tags.parent) { config.parent = tags.parent.toString(); } return config; } } } }).filter(function (s) { return s; }); if (pageConfigs.length > 0) { var config_1 = { fileName: fileName, lastModified: time, exports: pageConfigs }; var cache = this.cacher.get(fileName); if (cache != undefined) { if (cache.exports.every(function (i, index) { return isSameExport(config_1.exports[index], i); })) { return; } } this.cacher.set(fileName, config_1); this.emitFile(); } }; Programer.prototype.importPath = function (filename) { var path = path_1.relative(this.routePath, path_1.resolve(process.cwd(), filename)).replace(/\.tsx?$/, ''); if (!path.startsWith('.')) { path = './' + path; } return path.replace(/\/index$/, ""); }; Programer.prototype.getConstName = function (name, constName) { if (!constName) constName = name; if (this.RouteNames.has(constName)) { return this.getConstName(name, constName + "_1"); } this.CachedNames.set(name, constName); this.RouteNames.add(constName); return name; }; Programer.prototype.emitFile = function () { var _this = this; this.RouteNames = new Set(); this.CachedNames = new Map(); var Import = []; var RoutePath = []; route_template_1.LoopMap(this.cacher, function (key, item) { Import.push({ file: _this.importPath(item.fileName), name: item.exports.map(function (e) { return _this.getConstName(e.pageName); }) }); }); route_template_1.LoopMap(this.cacher, function (key, item) { item.exports.forEach(function (route) { RoutePath.push({ fileName: item.fileName, name: route.title, constName: _this.CachedNames.get(route.pageName), path: route.path, parent: route.parent ? _this.CachedNames.get(route.parent) : undefined, show: route.show, meta: route.meta, sort: route.sort, extra: route.extra }); }); }); var AppRoute = this.generateRoute(RoutePath); var content = route_template_1.Template(Import, RoutePath, AppRoute.route, AppRoute.menu); fs.writeFileSync(this.routeFile, content); this.emit("emit"); }; Programer.prototype.generateRoute = function (RoutePath) { RoutePath = JSON.parse(JSON.stringify(RoutePath)); var RoutePaths = {}; var Routes = {}; var rootRoute = []; var MenuRoutes = {}; RoutePath.forEach(function (item) { if (item.path != "" && !item.parent) { var parent_1 = RoutePath .filter(function (route) { return route.path != "/"; }) .filter(function (route) { return (item.path != route.path && item.path.startsWith(route.path)); }) .sort(function (a, b) { return b.path.length - a.path.length; }); if (parent_1.length > 0) { item.parent = parent_1[0].constName; } } // cache route path by name RoutePaths[item.constName] = item.path; Routes[item.constName] = ({ sort: item.sort, show: item.show, name: item.name, path: item.path, meta: item.meta, extra: item.extra, component: "class " + item.constName + " {}" }); if (item.show) { MenuRoutes[item.constName] = ({ name: item.name, path: item.path }); } }); RoutePath .filter(function (e) { return e.parent; }) .forEach(function (e) { var parentName = e.parent, childName = e.constName, parenetPath = RoutePaths[parentName], childPath = RoutePaths[childName], child = Routes[childName], parent = Routes[parentName]; child.path = childPath; (parent.children || (parent.children = [])).push(child); parent.children.sort(function (a, b) { return a.sort - b.sort; }); if (child.show) { var MenuParent = MenuRoutes[parentName]; if (MenuParent) { (MenuParent.children || (MenuParent.children = [])).push(MenuRoutes[childName]); } } }); RoutePath.filter(function (e) { return !e.parent; }) .forEach(function (item) { rootRoute.push(Routes[item.constName]); }); rootRoute.sort(function (a, b) { return a.sort - b.sort; }); // RoutePath.filter(e => !e.parent && e.show) // .forEach(item => { // RootMenuRoutes.push(MenuRoutes[item.constName]) // }) var route = JSON.stringify(rootRoute, function (key, value) { if (!value) { return undefined; } if (value.sort) { // value.meta = value.meta || {}; // value.meta.Sort = value.sort // delete value.sort return value; } if (key == "extra") { if (!value) return undefined; return "_$extra$_" + value + "_$extra$_"; } if (key == "sort") return undefined; if (key == "show") return undefined; return value; }, 4); var menuRoute = JSON.stringify(rootRoute.filter(function (s) { return s.show; }), function (key, value) { if (!value) { return undefined; } if (value.children) { value.children = value.children.filter(function (c) { return c.show; }); } if (value.show == false) { return undefined; } if (key == "extra") { if (!value) return undefined; return "_$extra$_" + value + "_$extra$_"; } if (key == "component") return undefined; return value; }, 4); return { route: route.replace(/"class\s(\w+)\s{}"/g, function (w, $1) { return $1; }).replace(/\"_\$extra\$_/g, "").replace(/_\$extra\$_\"/g, ""), menu: menuRoute.replace(/"class\s(\w+)\s{}"/g, function (w, $1) { return $1; }).replace(/\"_\$extra\$_/g, "").replace(/_\$extra\$_\"/g, ""), }; }; return Programer; }(events_1.EventEmitter)); exports.Programer = Programer; function escape(content) { return content .replace(/"class\s(\w+)\s{}"/g, function (w, $1) { return $1; }) .replace(/\"_\$extra\$_/g, "").replace(/_\$extra\$_\"/g, ""); } var isExported = function (node) { return node.modifiers && node.modifiers.some(function (s) { return s.kind == ts.SyntaxKind.ExportKeyword; }); }; var parseJsDoc = function (node) { // @ts-ignore if (!node.jsDoc) return {}; var docs = node.jsDoc; var result = {}; docs.forEach(function (doc) { if (doc.tags) doc.tags.forEach(function (tag) { var name = tag.tagName.text; var value = tag.comment || ""; if (name == "show") { result[name] = value == "false" ? false : true; } else if (name == "ignore") { result[name] = true; } else { result[name] = value; } }); }); return result; }; // Start the watcher process.on("uncaughtException", function (e) { console.info(e); });