UNPKG

@sanpjs/core

Version:

@sanpjs/core

138 lines 5.93 kB
"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