Node path.relative returns incorrect path
Asked Answered
G

1

16

I'm pretty sure I must be wrong but in Node, path.relative seems to output the wrong directory, or at least one I wasn't expecting:

> path.relative('a/file.js', 'a/file.css')
> '../file.css'

However I would expect the result to be something like:

> './file.css'

In essence I am trying to compute the difference in the two paths in order for one file to require the other and ../file.css is obviously wrong for my require as both the files are in the a directory. The output suggests that file.css is in the parent directory.

What am I missing?

Gehman answered 24/6, 2015 at 10:19 Comment(0)
S
19

As far as I can tell, path.relative() expects a folder rather than a file as its first argument. This works:

path.relative('a', 'a/file.css')
> 'file.css'

Here's the source code for path.relative: https://github.com/joyent/node/blob/master/lib/path.js#L504-L530 https://github.com/joyent/node/blob/master/lib/path.js#L265-L304

(Note: in case the line numbers change in the future, here's a link to the source as it is at the time I'm writing this: https://github.com/nodejs/node-v0.x-archive/blob/94beb2985b4cb25e592a9ccc226f6c824a81e510/lib/path.js)

As you can see there, the paths are split by the slashes in them and it simply compares the number of parts, so it doesn't work if you pass a file instead of a folder as the from argument.

Salutatory answered 24/6, 2015 at 10:50 Comment(5)
Yea I just figured this out myself. I just made the assumption from the docs that filenames would work as they do in some other path methods. Thanks!Gehman
It doesn't actually care if it is file or folder it was given. It doesn't even know. path.relative('a/file.js', 'a/file.css') is the same as path.relative('a/b', 'a/file.css'), and you just sliced the second level out.Korfonta
@Korfonta Good point, but I think it's still expecting a folder...actually it was probably written with the assumption that both arguments would be folders. In other words, the function does not appear to have been written intending to support both files and folders as possible arguments.Salutatory
Yea you are correct when the last part of the from path is indeed a file, the function is actually treating it as though the file is a directory so the returned path was always one ../ too many. It just so happens to work when the to argument has a filename in it as the result returns what it thinks is the directories (but also returns the filename).Gehman
@MattBrowne path module works with path names, not files or directories. You can't infer anything from a path name (file.js is a perfectly valid directory name). It is not a coincidence that path.relative('a/file.js', 'a/file.css') works but very intentional because if a/file.js is a subdirectory then ../file.css is exactly what you want. Again, path.relative doesn't know.Korfonta

© 2022 - 2024 — McMap. All rights reserved.