@sanpjs/core
Version:
@sanpjs/core
138 lines • 5.93 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const resolve_1 = __importDefault(require("resolve"));
const utils_1 = require("@sanpjs/utils");
const resolveSync = resolve_1.default.sync;
const ALLOWED_ENTRY_EXTENSIONS = ['.js', '.ts', '.san'];
class ModuleNotFoundError extends Error {
code = 'MODULE_NOT_FOUND';
requireStack;
moduleName;
}
class Resolver {
config;
pagesDir;
projectRoot;
sanpDir;
constructor(projectRoot, config) {
this.config = config;
this.projectRoot = projectRoot || process.cwd();
// resolver内部使用时采用相对路径
const { sanpDir = '.sanp', pagesDir = 'pages' } = this.config;
this.sanpDir = sanpDir && path_1.default.isAbsolute(sanpDir) ? path_1.default.relative(this.projectRoot, sanpDir) : sanpDir;
this.pagesDir = pagesDir && path_1.default.isAbsolute(pagesDir) ? path_1.default.relative(this.projectRoot, pagesDir) : pagesDir;
this.resolve = this.resolve.bind(this);
this.resolveEntry = this.resolveEntry.bind(this);
this.resolvePage = this.resolvePage.bind(this);
this.resolveComponent = this.resolveComponent.bind(this);
this.resolveSanp = this.resolveSanp.bind(this);
this.resolveLayout = this.resolveLayout.bind(this);
this.relativeImport = this.relativeImport.bind(this);
}
// 解析模块路径 root/node_modules, package/node_modules
resolve(id, opts = {}, optionalDir = path_1.default.resolve(__dirname, '../../bundler-webpack')) {
let absPath = '';
try {
try {
// 先找工程内的
absPath = resolveSync(id, {
basedir: this.projectRoot,
...opts
});
}
catch (e) {
// 再找用户指定的
absPath = resolveSync(id, {
basedir: optionalDir,
...opts
});
}
}
catch (error) {
const e = error;
if (e.code !== 'MODULE_NOT_FOUND') {
throw e;
}
}
return absPath;
}
// 注意需要传入绝对路径,否则命令执行和解析路径可能会不符
relative(filePath) {
if (!path_1.default.isAbsolute(filePath)) {
filePath = path_1.default.resolve(this.projectRoot, filePath);
}
return path_1.default.relative(this.projectRoot, filePath);
}
// 传入相对工程路径,解析入口文件,可以是dir/app.js或dir/app/index.js或dir/app/index.san
resolveEntry(filePath, isModule = true) {
const absPath = path_1.default.resolve(this.projectRoot, filePath);
return isModule ? this.resolve(absPath, { extensions: ALLOWED_ENTRY_EXTENSIONS }) : absPath;
}
// 传入相对pages下的文件路径,返回完整路径
resolvePage(filePath) {
return this.resolve(filePath, {
paths: [`${this.projectRoot}/${this.pagesDir}`],
extensions: ALLOWED_ENTRY_EXTENSIONS
});
}
// 传入相对components下的文件路径,返回完整路径
resolveComponent(filePath) {
return this.resolve(filePath, {
paths: [`${this.projectRoot}/components`],
extensions: ALLOWED_ENTRY_EXTENSIONS
});
}
// 传入相对sanp临时目录的文件路径,返回完整路径
resolveSanp(filePath, isMove = false) {
// mpa等入口处理从root/pages移动到root/.sanp/app的情况
if (isMove) {
return filePath.replace(`/${this.pagesDir}/`, `/${this.sanpDir}/app/`);
}
return path_1.default.resolve(`${this.projectRoot}/${this.sanpDir}`, filePath);
}
// 解析layouts下模板ejs文件路径
resolveLayout(filePath) {
let layout = '';
// 优先拿用户目录指定的layout
if (filePath) {
layout = this.resolve(filePath, {
// 兼容 layouts/myPage.ejs 和 myPage.ejs 两种形式
paths: [`${this.projectRoot}`, `${this.projectRoot}/layouts`]
});
if (!layout) {
throw new Error(`layout [${filePath}] not found`);
}
}
else {
// 没有的话拿 .sanp/layouts/default.ejs
layout = `${this.projectRoot}/${this.sanpDir}/layouts/default.ejs`;
}
return layout;
}
/**
* 发生文件移动时,处理文件内组件引用路径变更
* @param {string} importPath 文件内引用路径,例如:"../../components/header"
* @param {string} oriPath 源文件路径,相对于root。例如:'pages'
* @param {string} targetPath 目标文件路径,相对于root。例如:'.sanp/app/demo'
* @returns {string} 移动后的相对路径
*/
relativeImport(importPath, oriPath, targetPath) {
// 1.获取ori和target路径的完整路径
const oriFullPath = this.resolveEntry(oriPath) || '';
const targetFullPath = this.resolveEntry(targetPath) || '';
// 2.得到语句内相对路径的完整路径: multiple-page/components/header.san
const importFullPath = this.resolveEntry(path_1.default.resolve(oriFullPath, importPath));
if (!importFullPath) {
utils_1.logger.error(`${importPath} is not an available path`);
return;
}
// 3.返回引用相对路径,注意去掉.san等扩展名
return path_1.default.relative(targetFullPath, importFullPath).replace(path_1.default.extname(importFullPath), '');
}
}
exports.default = Resolver;
//# sourceMappingURL=Resolver.js.map