Description
This is easier to demonstrate than to explain.
Imagine the following file structure. Assume that subfolder-b is a symlinked folder.
/path/to/subfolder-a/subdir/filea.less
/path/to/subfolder-b/subdir/fileb.less
In fileb.less:
import "../../subfolder-a/subdir/filea.less";
When the value being passed gets sent along to fileExists(), it looks something like:
/path/to/subfolder-b/subdir/../../subfolder-a/subdir/filea.less
Even though this is a valid file path that should resolve, it will fail in our scenario in two ways:
- "subfolder-b" will end up as "subfolder". The reason is because the regex used in
preg_replace
matches folder names using \w. In other words, it will only match if the folder name has the characters [a-zA-Z0-9_]. - The regular expression replace will only munge a single instance of "filename/..". Since we have two relative paths in a row ("../..") these will get missed by the regex.
Both of these examples will work in the case of a regular folder, since realpath can handle those just fine. However, there are inconsistencies in the platform implementation of realpath() which can cause it to choke if there's a symlink involved in the file path (i.e. it traverses up the wrong tree).
I apologize for the obtuse explanation of the problem -- please let me know if there are any questions. It is a very real problem (which I spent this afternoon trying to work around). I will observe that the lessc bundled with less.js (1.2.2) handles paths like this correctly.
The good news is I have a solution and will submit a pull request shortly.