@oazmi/kitchensink - v0.9.13
    Preparing search index...

    Function resolvePosixPathFactory

    • this is a factory function for creating customizable posix path-resolving functions. a path-resolving function is one that takes in a list of path-segments, and then computes the absolute normalized path of all the segments combined.

      since it is not possible for this submodule to know the context under which you are computing/resolving paths, it becomes impossible to give a meaning to a list of path segmensts that begin with a relative path. which is why you would need to feed this factory function with the (static or dynamic) location of your current working path (directory), and it will spit out a path-resolver function that is tailored to your specific working-directory's path.

      Note

      if you want to preserve the starting relative segments, (i.e. you don't want an absolute path), then you're looking for the joinPosixPaths (or joinPaths) function, not this one.

      an important detail to note is that whenever an absolute path segment is encountered, all segments prior to it are discarded (i.e. not joined with a "/" separator, like the way joinPaths does). this behavior is enforced to remain consistent with popular implementations of path-resolvers, like:

      Caution

      this path resolver function works best when only absolute and relative path segments are provided. when root (but not necessarily absolute) path segments are encountered, such as /sys/bin, our function will typically assume that it is referring to an absolute local-filesystem path /sys/bin.

      but as you may be aware, the "correct" interpretation of the root path depends on the context of the preceding absolute path segment. for example:

      • if the preceding absolute path segment was C:/a/b/c/d.txt, and the current path segment is /sys/bin, then our result will be /sys/bin, but the result in most implementations (including deno-std's path module) would be C:/sys/bin.
      • similarly, if the preceding absolute path segment was http://test.com/a/b/c/d.txt, and the current path segment is /sys/bin, then our result will be /sys/bin, but the "correct" url path resolution (via new URL(...)) should have been http://test.com/sys.bin.

      this is why, if you're dealing with ambiguous root paths that are not necessarily tied down to your posix-filesystem's root, you should use the resolveAsUrl function instead, as it is aware of most common types of base contexts/domains for path evaluation. but on the other hand, you will be unable to use your custom absolute_segment_test_fn, nor be able to resolve multiple segments all at oncce.

      TODO: contemplate if it would be a good idea to add a configuration interface to this factory function, where one will be able to set their custom join rule when a root path segment is discovered, in addition to containing the absolute_segment_test_fn. the signature of the root-join function would look like: (abs_path_evaluated_up_till_now: string, current_root_path_segment: string) => string.

      Parameters

      • absolute_current_dir: string | (() => string)
      • absolute_segment_test_fn: (segment: string) => boolean = isAbsolutePath

      Returns (...segments: string[]) => string

      import { assertEquals } from "jsr:@std/assert"

      const
      cwd = "/x/y/z",
      getCwd = () => (cwd),
      // we also define a custom absolute segment path tester function that will identify "file://" and "http://" segments as absolute path,
      // in addition to the standard filesystem local path absoluteness tester `isAbsolutePath`.
      custom_absolute_path_segment_tester = (segment: string) => {
      if (isAbsolutePath(segment)) { return true }
      if (segment.startsWith("file://")) { return true }
      if (segment.startsWith("http://")) { return true }
      return false
      },
      resolvePosixPath = resolvePosixPathFactory(getCwd, custom_absolute_path_segment_tester)

      // aliasing our functions for brevity
      const eq = assertEquals, fn = resolvePosixPath

      // relative path resolution
      eq(fn("a", "b", "c.zip"), "/x/y/z/a/b/c.zip")
      eq(fn("./a", "b", "c/"), "/x/y/z/a/b/c/")
      eq(fn("a/", "b/", "c/"), "/x/y/z/a/b/c/")
      eq(fn("../a", "../b", "c/"), "/x/b/c/")
      eq(fn("../a/", "../b", "c/"), "/x/y/b/c/")
      eq(fn("a", "b", "c.zip", "./"), "/x/y/z/a/b/")
      eq(fn("a", "b", "c/", "./"), "/x/y/z/a/b/c/")
      eq(fn("a", "b", "c", "../"), "/x/y/z/a/")
      eq(fn("a", "b", "c/d.txt", "./e.txt"), "/x/y/z/a/b/c/e.txt")
      eq(fn("a", "b", "c/d.txt", "../e.txt"), "/x/y/z/a/b/e.txt")
      eq(fn("a/b", "c/d.txt", "..", "e.txt"), "/x/y/z/a/b/e.txt") // notice that you can use "." instead of "./"
      eq(fn("a/", "b/", "c/", "../", "./","d.txt"), "/x/y/z/a/b/d.txt")
      eq(fn("a/b", "c/", "..", ".","d.txt"), "/x/y/z/a/b/d.txt") // notice that you can use ".." instead of "../"
      eq(fn("a/b", "c/", ".d.txt"), "/x/y/z/a/b/c/.d.txt")
      eq(fn("a/b", "c/", "..d.txt"), "/x/y/z/a/b/c/..d.txt")
      eq(fn("a/b", "c/", ".d"), "/x/y/z/a/b/c/.d")
      eq(fn("a/b", "c/", ".d."), "/x/y/z/a/b/c/.d.")
      eq(fn("a/b", "c/", "..d"), "/x/y/z/a/b/c/..d")
      eq(fn("a/b", "c/", "..d."), "/x/y/z/a/b/c/..d.")
      eq(fn("a/b", "c/", "..d.."), "/x/y/z/a/b/c/..d..")
      eq(fn("a/b", "c/", "..d.", "e.txt"), "/x/y/z/a/b/c/..d./e.txt")
      eq(fn("a/b", "c/", "..d..", "e.txt"), "/x/y/z/a/b/c/..d../e.txt")
      eq(fn("./a", "./b", "./c"), "/x/y/z/c")

      // pre-existing absolute path resolution
      eq(fn("./a", "/b", "/c"), "/c") // both "/b" and "/c" are absolute paths, and so they purge all segments behind them.
      eq(fn("./a/", "/b/", "./c"), "/b/c") // "/b/" is an absolute path, hence it negates all segments prior to it.
      eq(fn("file:///", "a/b/c", "./d"), "file:///a/b/d") // the first "file:///" segment is an absolute path according to our `custom_absolute_path_segment_tester`
      eq(fn("file:/", "a/b/c", "./d"), "/x/y/z/file:/a/b/d") // "file:/" is not considered as an absolute path by `custom_absolute_path_segment_tester`, thus it the cwd will be prepended to the final path
      eq(fn("file:", "a/b/c", "./d"), "/x/y/z/file:/a/b/d") // same as before, but we're putting emphasis on the mandatory "/" separator that gets added after the "file:" segment
      eq(fn("a/b/c", "http://d/e/f.txt"), "http://d/e/f.txt") // the "http://" segment is identified as an absolute path by our `custom_absolute_path_segment_tester`