{"version":3,"file":"path.mjs","names":[],"sources":["../src/std/path/mod.ts"],"sourcesContent":["/**\n * POSIX 路径工具模块，提供 basename、dirname、normalize 等常用路径操作。\n * 仅处理 string 路径，不涉及 URL，确保小游戏平台兼容。\n * @module path\n */\n\n// #region Internal Variables\n\nconst CHAR_FORWARD_SLASH = 47;\nconst CHAR_DOT = 46;\n\n// #endregion\n\n/**\n * 路径分隔符，始终为 '/'。\n * @since 2.4.0\n * @example\n * ```ts\n * import { path } from 'minigame-std';\n *\n * console.log(path.SEPARATOR); // '/'\n * ```\n */\nexport const SEPARATOR = '/';\n\n/**\n * 提取路径的最后一个片段（文件名）。\n * @param path - 要处理的路径字符串。\n * @param suffix - 可选的后缀，如果文件名以此结尾则去除。\n * @returns 路径中的文件名部分。\n * @since 2.4.0\n * @example\n * ```ts\n * import { path } from 'minigame-std';\n *\n * path.basename('/usr/local/file.txt');         // 'file.txt'\n * path.basename('/usr/local/file.txt', '.txt'); // 'file'\n * path.basename('/usr/local/');                 // 'local'\n * ```\n */\nexport function basename(path: string, suffix?: string): string {\n    if (path.length === 0) return '';\n\n    // 去掉尾部斜杠\n    let end = path.length;\n    while (end > 1 && path.charCodeAt(end - 1) === CHAR_FORWARD_SLASH) end--;\n\n    // 只有斜杠的路径\n    if (end === 1 && path.charCodeAt(0) === CHAR_FORWARD_SLASH) return SEPARATOR;\n\n    // 找最后一个斜杠\n    let start = 0;\n    for (let i = end - 1; i >= 0; i--) {\n        if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) {\n            start = i + 1;\n            break;\n        }\n    }\n\n    let base = path.slice(start, end);\n\n    // suffix 不能等于整个文件名\n    if (suffix && suffix.length < base.length && base.endsWith(suffix)) {\n        base = base.slice(0, -suffix.length);\n    }\n\n    return base;\n}\n\n/**\n * 提取路径的目录部分。\n * @param path - 要处理的路径字符串。\n * @returns 路径中的目录部分。\n * @since 2.4.0\n * @example\n * ```ts\n * import { path } from 'minigame-std';\n *\n * path.dirname('/usr/local/file.txt'); // '/usr/local'\n * path.dirname('/usr/local/');         // '/usr'\n * path.dirname('file.txt');            // '.'\n * path.dirname('/');                   // '/'\n * ```\n */\nexport function dirname(path: string): string {\n    if (path.length === 0) return '.';\n\n    // 去掉尾部斜杠\n    let end = path.length;\n    while (end > 1 && path.charCodeAt(end - 1) === CHAR_FORWARD_SLASH) end--;\n\n    // 找最后一个斜杠\n    let lastSlash = -1;\n    for (let i = end - 1; i >= 0; i--) {\n        if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) {\n            lastSlash = i;\n            break;\n        }\n    }\n\n    if (lastSlash === -1) return '.';\n    if (lastSlash === 0) return SEPARATOR;\n\n    // 去掉结果尾部的连续斜杠\n    let dirEnd = lastSlash;\n    while (dirEnd > 1 && path.charCodeAt(dirEnd - 1) === CHAR_FORWARD_SLASH) dirEnd--;\n\n    return path.slice(0, dirEnd);\n}\n\n/**\n * 规范化路径，解析 '.' 和 '..' 片段，合并多余斜杠。\n * @param path - 要规范化的路径字符串。\n * @returns 规范化后的路径。\n * @since 2.4.0\n * @example\n * ```ts\n * import { path } from 'minigame-std';\n *\n * path.normalize('/foo/bar//baz/asdf/quux/..'); // '/foo/bar/baz/asdf'\n * path.normalize('./foo/../bar/baz');           // 'bar/baz'\n * path.normalize('/foo/bar///baz');             // '/foo/bar/baz'\n * ```\n */\nexport function normalize(path: string): string {\n    if (path.length === 0) return '.';\n\n    const isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH;\n    const trailingSeparator = path.charCodeAt(path.length - 1) === CHAR_FORWARD_SLASH;\n\n    // 解析 . 和 .. 片段\n    path = normalizeString(path, !isAbsolute);\n\n    if (path.length === 0 && !isAbsolute) path = '.';\n    if (path.length > 0 && trailingSeparator) path += SEPARATOR;\n    if (isAbsolute) return `${SEPARATOR}${path}`;\n\n    return path;\n}\n\n// #region Internal Functions\n\n/**\n * 解析路径中的 '.' 和 '..' 片段。\n * 移植自 path-browserify。\n */\nfunction normalizeString(path: string, allowAboveRoot: boolean): string {\n    let res = '';\n    let lastSegmentLength = 0;\n    let lastSlash = -1;\n    let dots = 0;\n    let code: number;\n\n    for (let i = 0; i <= path.length; i++) {\n        if (i < path.length) {\n            code = path.charCodeAt(i);\n        } else {\n            code = CHAR_FORWARD_SLASH;\n        }\n\n        if (code === CHAR_FORWARD_SLASH) {\n            if (lastSlash === i - 1 || dots === 1) {\n                // NOOP — empty segment or single dot\n            } else if (dots === 2) {\n                if (\n                    res.length < 2\n                    || lastSegmentLength !== 2\n                    || res.charCodeAt(res.length - 1) !== CHAR_DOT\n                    || res.charCodeAt(res.length - 2) !== CHAR_DOT\n                ) {\n                    if (res.length > 2) {\n                        const lastSlashIndex = res.lastIndexOf(SEPARATOR);\n                        if (lastSlashIndex === -1) {\n                            res = '';\n                            lastSegmentLength = 0;\n                        } else {\n                            res = res.slice(0, lastSlashIndex);\n                            lastSegmentLength = res.length - 1 - res.lastIndexOf(SEPARATOR);\n                        }\n                        lastSlash = i;\n                        dots = 0;\n                        continue;\n                    } else if (res.length === 2 || res.length === 1) {\n                        res = '';\n                        lastSegmentLength = 0;\n                        lastSlash = i;\n                        dots = 0;\n                        continue;\n                    }\n                }\n                if (allowAboveRoot) {\n                    if (res.length > 0) res += `${SEPARATOR}..`;\n                    else res = '..';\n                    lastSegmentLength = 2;\n                }\n            } else {\n                if (res.length > 0) res += `${SEPARATOR}${path.slice(lastSlash + 1, i)}`;\n                else res = path.slice(lastSlash + 1, i);\n                lastSegmentLength = i - lastSlash - 1;\n            }\n            lastSlash = i;\n            dots = 0;\n        } else if (code === CHAR_DOT && dots !== -1) {\n            dots++;\n        } else {\n            dots = -1;\n        }\n    }\n\n    return res;\n}\n\n// #endregion\n"],"mappings":"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"}