pathz
v0.11.0
Published
Functional utils for FS paths
Downloads
29
Maintainers
Readme
Pathz
Functional toolkit for file/dir paths. Drop-in path
replacement.
Originally built for a static site generator where path transformations are common, but use-cases
are really unlimited.
Features
- High-level path manipulations
- Curried composable API
- Crossplatform: works in NodeJS and all modern browsers
- Extensive test suite
Peer dependencies:
@paqmind/ramdax
(temp. until basic Ramda)
Dependencies:
path
(Server)path-webpack
(Browser)
Usage
$ npm install pathz
let P = require("pathz") // defaults to either POSIX or WIN32
let P_posix = require("pathz/posix") // POSIX (P.sep is / etc.)
let P_win32 = require("pathz/win32") // WIN32 (P.sep is \ etc.)
// The following snippets also use shortcuts for:
let R = require("ramdax")
let PP = require("path")
Browser
Usage hint. Webpack's path-browserify
dependency (polyfill of path
) is very old and severily broken.
It doesn't even provide a parse
function! If you want to import path
directly, be sure to
substitute it with another package. Add the following to your webpack.config.js
:
resolve: {
alias: {
path: "path-webpack"
}
}
This can fix other libraries naively depending on path
btw. Other bundlers, like Browserify
or Rollup, should support such replacement. You can use this approach to keep import P from "path"
or import P from pathz/lib/browser
instead. There's no support for Win-32 separators in Browser a.t.m.
Motivation
1. Original format
/ parse
provide limited, low-level, mutable API
2. pathz
respects trailing separators as possible directory indicator
console.log(PP.dirname("/foo/bar/")) // "/foo"
console.log(P.dir("/foo/bar/")) // "/foo/bar/"
console.log(PP.basename("/foo/bar/")) // "bar"
console.log(P.base("/foo/bar/")) // ""
3. pathz
respects "relativeness" and "absoluteness" of paths
console.log(P.addLeftDir("bar", "/foo.txt")) // "/bar/foo.txt" (+)
console.log(PP.join("bar", "/foo.txt")) // "bar/foo.txt" (-) naive
console.log(P.addRightDir("bar", "/foo.txt")) // "/bar/foo.txt" (+)
console.log(PP.join("/foo.txt", "bar")) // "/foo.txt/bar" (-) naive
4. pathz
is composition friendly
let R = require("ramdax")
let src = "content/team/about.md"
let dst = R.pipe(
P.withLeftDir("public"),
P.addRightDir(P.name(src)),
P.withBase("index.html")
)(src)
console.log(dst) // "public/team/about/index.html"
// corresponding to "/team/about/" URL
5. pathz
is like CRUD for path fragments
// GET
console.log(P.leftDir("/foo/bar/baz.txt")) // "foo"
console.log(P.rightDir("/foo/bar/baz.txt")) // "bar"
// UPDATE
console.log(P.withLeftDir ("qux", "/foo/bar/baz.txt")) // "/qux/bar/baz.txt"
console.log(P.withRightDir("qux", "/foo/bar/baz.txt")) // "/foo/qux/baz.txt"
// DELETE
console.log(P.dropLeftDir ("/foo/bar/baz.txt")) // "/bar/baz.txt"
console.log(P.dropRightDir("/foo/bar/baz.txt")) // "/foo/baz.txt"
// ...
6. pathz
provides extra utils
R.sortBy(P.padPath(2))([
"foo/bar/11.1/2.1",
"foo/bar/2.1/10.1",
"foo/bar/10.1/2.1",
"foo/bar/2.1/2.1",
])
// [ 'foo/bar/2.1/2.1',
// 'foo/bar/2.1/10.1',
// 'foo/bar/10.1/2.1',
// 'foo/bar/11.1/2.1' ]
API
dir :: String -> String
P.dir("foo/bar/baz.txt") // "foo/bar/" (P.dirname + "/")
P.dir("foo/bar/") // "foo/bar/" (identity)
P.dir("/foo/bar/baz.txt") // "/foo/bar/" (P.dirname + "/")
P.dir("/foo/bar/") // "/foo/bar/" (identity)
splitDirs :: String -> [String]
P.splitDirs("foo/bar/baz.txt") // ["foo", "bar"]
P.splitDirs("/foo/bar/") // ["foo", "bar"]
base :: String -> String
P.base("foo/bar/baz.txt") // "baz.txt" (P.basename)
P.base("foo/bar/") // "" (zero)
name :: String -> String
P.name("whatever/index.html") // "index"
P.name("whatever/.gitignore") // ".gitignore"
ext :: String -> String
P.ext("whatever/index.html") // ".html"
P.ext("whatever/.gitignore") // ""
leftDir :: String -> String
P.leftDir("foo/bar/index.html") // "foo"
P.leftDir("foo") // ""
P.leftDir("foo/") // "foo"
rightDir :: String -> String
P.rightDir("foo/bar/index.html") // "bar"
P.rightDir("foo") // ""
P.rightDir("foo/") // "foo"
leftDirs :: Number -> String -> String
P.leftDirs(1) == P.leftDir
P.leftDirs(2, "foo/bar/baz/qux.txt") // "foo/bar"
P.leftDirs(3, "foo/bar/baz/qux.txt") // "foo/bar/baz"
P.leftDirs(4, "/foo/bar/baz/qux.txt") // "foo/bar/baz"
rightDirs :: Number -> String -> String
P.rightDirs(1) == P.rightDir
P.rightDirs(2, "foo/bar/baz/qux.txt") // "bar/baz"
P.rightDirs(3, "foo/bar/baz/qux.txt") // "foo/bar/baz"
P.rightDirs(4, "/foo/bar/baz/qux.txt") // "foo/bar/baz"
addLeftDir :: String -> String -> String
P.addLeftDir("foo", "bar/index.html") // "foo/bar/index.html"
P.addLeftDir("foo", "") // "foo/"
addRightDir :: String -> String -> String
P.addLeftDir("foo", "bar/index.html") // "foo/bar/index.html"
P.addLeftDir("foo", "") // "foo/"
withLeftDir :: String -> String -> String
P.withLeftDir("qux", "foo/bar/index.html") // "qux/bar/index.html"
P.withLeftDir("qux", "index.html") // "qux/index.html"
P.withLeftDir("qux", "") // "qux/"
withRightDir :: String -> String -> String
P.withRightDir("qux", "foo/bar/index.html") // "foo/qux/index.html"
P.withRightDir("qux", "index.html") // "qux/index.html"
P.withRightDir("qux", "") // "qux/"
dropLeftDir :: String -> String
P.addRightDir("bar", "foo/index.html") // "foo/bar/index.html"
P.addRightDir("bar", "") // "bar/"
dropRightDir :: String -> String
P.dropRightDir("foo/bar/index.html") // "foo/index.html"
P.dropRightDir("index.html") // "index.html"
withDir :: String -> String -> String
P.withDir("bar", "foo/index.html") // "bar/index.html"
P.withDir("bar", "") // "bar/"
withBase :: String -> String -> String
P.withBase("index", "foo/page.html") // "foo/index"
P.withBase("index", "") // "index"
withName :: String -> String
P.withName("index", "foo/page.html") // "foo/index.html"
P.withName("index", "") // "index"
withExt :: String -> String
P.withExt(".html", "foo/index.md") // "foo/index.html"
P.withExt(".html", "") // ".html"
dropBase :: String -> String
P.dropBase("foo/bar/index.html") // "foo/bar/"
P.dropBase("index.html") // ""
dropExt :: String -> String
P.dropExt("foo/bar/index.html") // "foo/bar/index"
P.dropExt(".gitignore") // ".gitignore"
padNumeric :: Number -> String
P.padNumeric(4, "x") // "x"
P.padNumeric(4, "1") // "0001"
padName :: Number -> String
P.padName(2, "1.1.foo.js") // "01.01.foo.js"
padPath :: Number -> String
P.padPath(2, "1.folder/file.1.md") // "01.folder/file.01.md"
Original API
delimiter
: low-level, import directlyposix
: low-level, import directlysep
: low-level, import directlywin32
: low-level, import directlybasename
: wrapped, useP.base
insteaddirname
: wrapped, useP.dir
insteadextname
: wrapped, useP.ext
insteadformat
: wrapped, useP
helpers insteadparse
: wrapped, useP
helpers insteadisAbsolute
: reexportedjoin
: reexportednormalize
: reexportedrelative
: reexportedresolve
: reexported