diff options
| author | Shipwreckt <me@shipwreckt.co.uk> | 2025-10-31 20:02:14 +0000 |
|---|---|---|
| committer | Shipwreckt <me@shipwreckt.co.uk> | 2025-10-31 20:02:14 +0000 |
| commit | 7a52ddeba2a68388b544f529d2d92104420f77b0 (patch) | |
| tree | 15ddd47457a2cb4a96060747437d36474e4f6b4e /node_modules/@11ty/eleventy-utils/src/TemplatePath.js | |
| parent | 53d6ae2b5568437afa5e4995580a3fb679b7b91b (diff) | |
Changed from static to 11ty!
Diffstat (limited to 'node_modules/@11ty/eleventy-utils/src/TemplatePath.js')
| -rw-r--r-- | node_modules/@11ty/eleventy-utils/src/TemplatePath.js | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/node_modules/@11ty/eleventy-utils/src/TemplatePath.js b/node_modules/@11ty/eleventy-utils/src/TemplatePath.js new file mode 100644 index 0000000..807af54 --- /dev/null +++ b/node_modules/@11ty/eleventy-utils/src/TemplatePath.js @@ -0,0 +1,373 @@ +const path = require("path"); +const fs = require("fs"); + +function TemplatePath() {} + +/** + * @returns {String} the absolute path to Eleventy’s project directory. + */ +TemplatePath.getWorkingDir = function () { + return TemplatePath.normalize(path.resolve(".")); +}; + +/** + * Returns the directory portion of a path. + * Works for directory and file paths and paths ending in a glob pattern. + * + * @param {String} path - A path + * @returns {String} the directory portion of a path. + */ +TemplatePath.getDir = function (path) { + if (TemplatePath.isDirectorySync(path)) { + return path; + } + + return TemplatePath.getDirFromFilePath(path); +}; + +/** + * Returns the directory portion of a path that either points to a file + * or ends in a glob pattern. If `path` points to a directory, + * the returned value will have its last path segment stripped + * due to how [`path.parse`][1] works. + * + * [1]: https://nodejs.org/api/path.html#path_path_parse_path + * + * @returns {String} the directory portion of a path. + * @param {String} filePath - A path + */ +TemplatePath.getDirFromFilePath = function (filePath) { + return path.parse(filePath).dir || "."; +}; + +/** + * Returns the last path segment in a path (no leading/trailing slashes). + * + * Assumes [`path.parse`][1] was called on `path` before. + * + * [1]: https://nodejs.org/api/path.html#path_path_parse_path + * + * @param {String} path - A path + * @returns {String} the last path segment in a path + */ +TemplatePath.getLastPathSegment = function (path) { + if (!path.includes("/")) { + return path; + } + + // Trim a trailing slash if there is one + path = path.replace(/\/$/, ""); + + return path.slice(path.lastIndexOf("/") + 1); +}; + +/** + * @param {String} path - A path + * @returns {String[]} an array of paths pointing to each path segment of the + * provided `path`. + */ +TemplatePath.getAllDirs = function (path) { + // Trim a trailing slash if there is one + path = path.replace(/\/$/, ""); + + if (!path.includes("/")) { + return [path]; + } + + return path + .split("/") + .map((segment, index, array) => array.slice(0, index + 1).join("/")) + .filter((path) => path !== ".") + .reverse(); +}; + +/** + * Normalizes a path, resolving single-dot and double-dot segments. + * + * Node.js’ [`path.normalize`][1] is called to strip a possible leading `"./"` segment. + * + * [1]: https://nodejs.org/api/path.html#path_path_normalize_path + * + * @param {String} thePath - The path that should be normalized. + * @returns {String} the normalized path. + */ +TemplatePath.normalize = function (thePath) { + let filePath = path.normalize(thePath).split(path.sep).join("/"); + if(filePath !== "/" && filePath.endsWith("/")) { + return filePath.slice(0, -1); + } + return filePath; +}; + +/** + * Joins all given path segments together. + * + * It uses Node.js’ [`path.join`][1] method. + * + * [1]: https://nodejs.org/api/path.html#path_path_join_paths + * + * @param {...String} paths - An arbitrary amount of path segments. + * @returns {String} the normalized and joined path. + */ +TemplatePath.join = function (...paths) { + return TemplatePath.normalize(path.join(...paths)); +}; + +/** + * Joins the given URL path segments and normalizes the resulting path. + * Maintains a single trailing slash if the last URL path argument + * had at least one. + * + * @param {...String} urlPaths + * @returns {String} a normalized URL path described by the given URL path segments. + */ +TemplatePath.normalizeUrlPath = function (...urlPaths) { + const urlPath = path.posix.join(...urlPaths); + return urlPath.replace(/\/+$/, "/"); +}; + +/** + * Joins the given path segments. Since the first path is absolute, + * the resulting path will be absolute as well. + * + * @param {...String} paths + * @returns {String} the absolute path described by the given path segments. + */ +TemplatePath.absolutePath = function (...paths) { + let i = 0; + // check all the paths before we short circuit from the first index + for (let p of paths) { + if (path.isAbsolute(p) && i > 0) { + throw new Error( + `Only the first parameter to Template.absolutePath can be an absolute path. Received: ${p} from ${paths}` + ); + } + i++; + } + + let j = 0; + for (let p of paths) { + if (j === 0 && path.isAbsolute(p)) { + return TemplatePath.join(...paths); + } + j++; + } + + return TemplatePath.join(TemplatePath.getWorkingDir(), ...paths); +}; + +/** + * Turns an absolute path into a path relative to the project directory. + * + * @param {String} absolutePath + * @returns {String} the relative path. + */ +TemplatePath.relativePath = function (absolutePath) { + return TemplatePath.stripLeadingSubPath( + absolutePath, + TemplatePath.getWorkingDir() + ); +}; + +/** + * Adds a leading dot-slash segment to each path in the `paths` array. + * + * @param {String[]} paths + * @returns {String[]} + */ +TemplatePath.addLeadingDotSlashArray = function (paths) { + return paths.map((path) => TemplatePath.addLeadingDotSlash(path)); +}; + +/** + * Adds a leading dot-slash segment to `path`. + * + * @param {String} pathArg + * @returns {String} + */ +TemplatePath.addLeadingDotSlash = function (pathArg) { + if (pathArg === "." || pathArg === "..") { + return pathArg + "/"; + } + + if ( + path.isAbsolute(pathArg) || + pathArg.startsWith("./") || + pathArg.startsWith("../") + ) { + return pathArg; + } + + return "./" + pathArg; +}; + +/** + * Removes a leading dot-slash segment. + * + * @param {String} path + * @returns {String} the `path` without a leading dot-slash segment. + */ +TemplatePath.stripLeadingDotSlash = function (path) { + return typeof path === "string" ? path.replace(/^\.\//, "") : path; +}; + +/** + * Determines whether a path starts with a given sub path. + * + * @param {String} path - A path + * @param {String} subPath - A path + * @returns {Boolean} whether `path` starts with `subPath`. + */ +TemplatePath.startsWithSubPath = function (path, subPath) { + path = TemplatePath.normalize(path); + subPath = TemplatePath.normalize(subPath); + + return path.startsWith(subPath); +}; + +/** + * Removes the `subPath` at the start of `path` if present + * and returns the remainding path. + * + * @param {String} path - A path + * @param {String} subPath - A path + * @returns {String} the `path` without `subPath` at the start of it. + */ +TemplatePath.stripLeadingSubPath = function (path, subPath) { + path = TemplatePath.normalize(path); + subPath = TemplatePath.normalize(subPath); + + if (subPath !== "." && path.startsWith(subPath)) { + return path.slice(subPath.length + 1); + } + + return path; +}; + +/** + * @param {String} path - A path + * @returns {Boolean} whether `path` points to an existing directory. + */ +TemplatePath.isDirectorySync = function (path) { + return fs.existsSync(path) && fs.statSync(path).isDirectory(); +}; + +/** + * @param {String} path - A path + * @returns {Boolean} whether `path` points to an existing directory. + */ +TemplatePath.isDirectory = async function (path) { + return new Promise((resolve) => { + fs.stat(path, (err, stats) => { + if (stats) { + resolve(stats.isDirectory()); + } + resolve(false); + }); + }); +}; + +/** + * Appends a recursive wildcard glob pattern to `path` + * unless `path` is not a directory; then, `path` is assumed to be a file path + * and is left unchaged. + * + * @param {String} path + * @returns {String} + */ +TemplatePath.convertToRecursiveGlobSync = function (path) { + if (path === "") { + return "./**"; + } + + path = TemplatePath.addLeadingDotSlash(path); + + if (TemplatePath.isDirectorySync(path)) { + return path + (!path.endsWith("/") ? "/" : "") + "**"; + } + + return path; +}; + +/** + * Appends a recursive wildcard glob pattern to `path` + * unless `path` is not a directory; then, `path` is assumed to be a file path + * and is left unchaged. + * + * @param {String} path + * @returns {String} + */ +TemplatePath.convertToRecursiveGlob = async function (path) { + if (path === "") { + return "./**"; + } + + path = TemplatePath.addLeadingDotSlash(path); + + if (await TemplatePath.isDirectory(path)) { + return path + (!path.endsWith("/") ? "/" : "") + "**"; + } + + return path; +}; + +/** + * Returns the extension of the path without the leading dot. + * If the path has no extensions, the empty string is returned. + * + * @param {String} thePath + * @returns {String} the path’s extension if it exists; + * otherwise, the empty string. + */ +TemplatePath.getExtension = function (thePath) { + return path.extname(thePath).replace(/^\./, ""); +}; + +/** + * Removes the extension from a path. + * + * @param {String} path + * @param {String} [extension] + * @returns {String} + */ +TemplatePath.removeExtension = function (path, extension = undefined) { + if (extension === undefined) { + return path; + } + + const pathExtension = TemplatePath.getExtension(path); + if (pathExtension !== "" && extension.endsWith(pathExtension)) { + return path.substring(0, path.lastIndexOf(pathExtension) - 1); + } + + return path; +}; + +/** + * Accepts a relative file path that is using a standard directory separator and + * normalizes it using the local operating system separator. + * e.g. `./my/dir/` stays `./my/dir/` on *nix and becomes `.\\my\\dir\\` on Windows + * + * @param {String} filePath + * @param {String} [sep="/"] + * @returns {String} a file path with the correct local directory separator. + */ +TemplatePath.normalizeOperatingSystemFilePath = function (filePath, sep = "/") { + return filePath.split(sep).join(path.sep); +}; + +/** + * Accepts a relative file path with the local operating system directory separator and + * normalizes it using a forward slash directory separator. (Leaves trailing slash as-is) + * e.g. `./my/dir/` stays `./my/dir/` on *nix + * e.g. `.\\my\\dir\\` becomes `./my/dir/` on *nix and Windows + * + * @param {String} filePath + * @param {String} [sep="/"] + * @returns {String} a file path with the correct local directory separator. + */ +TemplatePath.standardizeFilePath = function (filePath, sep = "/") { + return TemplatePath.addLeadingDotSlash(filePath.split(path.sep).join(sep)); +}; + +module.exports = TemplatePath; |
