@foolishchow/vue-cli-plugin-ts-router-gen
Version:
vue-router typescript generator for vue-class-component
370 lines (369 loc) • 16.3 kB
JavaScript
;
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);
});