UNPKG

hzengine-core

Version:

An Visual Novel Engine for Zepp OS

338 lines (293 loc) 9.23 kB
// path utils for ZeppOS // @CuberQAQ // Generated by GPT-4o mini "use strict"; var util = { isString: (x) => typeof x === "string", // 检查是否为字符串 isObject: (x) => typeof x === "object", // 检查是否为对象 }; /** * 检查路径是否包含协议 * @param {string} path - 路径字符串 * @returns {boolean} - 如果路径包含协议,则返回 true */ function isProtocolPath(path) { return /^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//.test(path); } /** * 提取协议和路径部分 * @param {string} path - 路径字符串 * @returns {{protocol: string, filepath: string}} - 包含协议和文件路径的对象 */ function extractProtocol(path) { const match = path.match(/^([a-zA-Z][a-zA-Z\d+\-.]*):\/\/(.*)$/); if (match) { return { protocol: match[1], // 获取协议 filepath: match[2], // 获取文件路径 }; } return { protocol: null, filepath: path }; // 如果没有协议,返回原路径 } /** * 解析路径数组并规范化 * @param {string[]} parts - 路径组成部分 * @param {boolean} allowAboveRoot - 是否允许上级目录 * @returns {string[]} - 规范化后的路径部分 */ function normalizeArray(parts, allowAboveRoot) { var res = []; for (var i = 0; i < parts.length; i++) { var p = parts[i]; // 忽略空部分和当前目录(.) if (!p || p === ".") continue; // 处理上级目录(..) if (p === "..") { if (res.length && res[res.length - 1] !== "..") { res.pop(); // 移除最后一个部分 } else if (allowAboveRoot) { res.push(".."); // 允许上级目录 } } else { res.push(p); // 添加有效部分 } } return res; } /** * 移除数组两端的空元素 * @param {string[]} arr - 输入数组 * @returns {string[]} - 去除空元素后的数组 */ function trimArray(arr) { var lastIndex = arr.length - 1; var start = 0; for (; start <= lastIndex; start++) { if (arr[start]) break; } var end = lastIndex; for (; end >= 0; end--) { if (arr[end]) break; } if (start === 0 && end === lastIndex) return arr; if (start > end) return []; return arr.slice(start, end + 1); } // 使用正则表达式分割路径 var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; var posix = {}; /** * 分割路径 * @param {string} filename - 输入的路径字符串 * @returns {string[]} - 分割后的路径组成部分 */ function posixSplitPath(filename) { return splitPathRe.exec(filename).slice(1); } /** * 解析路径,将相对路径转换为绝对路径 * @param {...string} paths - 要解析的路径 * @returns {string} - 解析后的绝对路径 */ posix.resolve = function () { var resolvedPath = "", resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { var path = i >= 0 ? arguments[i] : process.cwd(); // 跳过空和无效的条目 if (!util.isString(path)) { throw new TypeError("Arguments to path.resolve must be strings"); } else if (!path) { continue; } // 检查路径是否包含协议 if (isProtocolPath(path)) { const { protocol, filepath } = extractProtocol(path); resolvedPath = filepath + "/" + resolvedPath; resolvedAbsolute = true; // 将协议路径视为绝对路径 } else { resolvedPath = path + "/" + resolvedPath; resolvedAbsolute = path[0] === "/"; } } // 规范化路径 resolvedPath = normalizeArray( resolvedPath.split("/"), !resolvedAbsolute ).join("/"); return (resolvedAbsolute ? "/" : "") + resolvedPath || "."; }; /** * 规范化路径,去除多余的斜杠和当前目录 * @param {string} path - 输入的路径字符串 * @returns {string} - 规范化后的路径 */ posix.normalize = function (path) { // 检查路径是否包含协议 if (isProtocolPath(path)) { const { protocol, filepath } = extractProtocol(path); return protocol + "://" + normalizeArray(filepath.split("/")).join("/"); } var isAbsolute = posix.isAbsolute(path), trailingSlash = path && path[path.length - 1] === "/"; // 规范化路径 path = normalizeArray(path.split("/"), !isAbsolute).join("/"); if (!path && !isAbsolute) { path = "."; } if (path && trailingSlash) { path += "/"; } return (isAbsolute ? "/" : "") + path; }; /** * 检查路径是否为绝对路径 * @param {string} path - 输入的路径字符串 * @returns {boolean} - 如果路径为绝对路径,则返回 true */ posix.isAbsolute = function (path) { return path.charAt(0) === "/"; }; /** * 连接多个路径段为一个路径 * @param {...string} segments - 要连接的路径段 * @returns {string} - 连接后的路径 */ posix.join = function () { var path = ""; for (var i = 0; i < arguments.length; i++) { var segment = arguments[i]; if (!util.isString(segment)) { throw new TypeError("Arguments to path.join must be strings"); } if (segment) { if (!path) { path += segment; } else { path += "/" + segment; } } } return posix.normalize(path); }; /** * 计算相对路径 * @param {string} from - 起始路径 * @param {string} to - 目标路径 * @returns {string} - 相对路径 */ posix.relative = function (from, to) { from = posix.resolve(from).substr(1); to = posix.resolve(to).substr(1); var fromParts = trimArray(from.split("/")); var toParts = trimArray(to.split("/")); var length = Math.min(fromParts.length, toParts.length); var samePartsLength = length; for (var i = 0; i < length; i++) { if (fromParts[i] !== toParts[i]) { samePartsLength = i; break; } } var outputParts = []; for (var i = samePartsLength; i < fromParts.length; i++) { outputParts.push(".."); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join("/"); }; /** * 获取路径的目录名 * @param {string} path - 输入的路径字符串 * @returns {string} - 目录名 */ posix.dirname = function (path) { var result = posixSplitPath(path), root = result[0], dir = result[1]; if (!root && !dir) { return "."; } if (dir) { dir = dir.substr(0, dir.length - 1); // 去掉尾部斜杠 } return root + dir; }; /** * 获取路径的基本名 * @param {string} path - 输入的路径字符串 * @param {string} [ext] - 可选的扩展名,如果提供则将其从基本名中去除 * @returns {string} - 基本名 */ posix.basename = function (path, ext) { var f = posixSplitPath(path)[2]; if (ext && f.substr(-1 * ext.length) === ext) { f = f.substr(0, f.length - ext.length); } return f; }; /** * 获取路径的扩展名 * @param {string} path - 输入的路径字符串 * @returns {string} - 扩展名 */ posix.extname = function (path) { return posixSplitPath(path)[3]; }; /** * 格式化路径对象为路径字符串 * @param {Object} pathObject - 路径对象 * @param {string} pathObject.root - 根路径 * @param {string} pathObject.dir - 目录路径 * @param {string} pathObject.base - 基本文件名 * @param {string} pathObject.ext - 扩展名 * @param {string} pathObject.name - 文件名(不包含扩展名) * @returns {string} - 格式化后的路径字符串 */ posix.format = function (pathObject) { if (!util.isObject(pathObject)) { throw new TypeError( "Parameter 'pathObject' must be an object, not " + typeof pathObject ); } var root = pathObject.root || ""; if (!util.isString(root)) { throw new TypeError( "'pathObject.root' must be a string or undefined, not " + typeof pathObject.root ); } var dir = pathObject.dir ? pathObject.dir + posix.sep : ""; var base = pathObject.base || ""; return dir + base; }; /** * 解析路径字符串为路径对象 * @param {string} pathString - 输入的路径字符串 * @returns {{root: string, dir: string, base: string, ext: string, name: string}} - 路径对象 */ posix.parse = function (pathString) { if (!util.isString(pathString)) { throw new TypeError( "Parameter 'pathString' must be a string, not " + typeof pathString ); } var allParts = posixSplitPath(pathString); if (!allParts || allParts.length !== 4) { throw new TypeError("Invalid path '" + pathString + "'"); } allParts[1] = allParts[1] || ""; allParts[2] = allParts[2] || ""; allParts[3] = allParts[3] || ""; return { root: allParts[0], dir: allParts[0] + allParts[1].slice(0, -1), base: allParts[2], ext: allParts[3], name: allParts[2].slice(0, allParts[2].length - allParts[3].length), }; }; posix.sep = "/"; // POSIX 路径分隔符 posix.delimiter = ":"; // POSIX 路径分隔符(用于环境变量) export default posix; // 导出 posix 模块