modify-babel-preset icon indicating copy to clipboard operation
modify-babel-preset copied to clipboard

Rewrite path parsing using the `path` module instead of regexes

Open sorgloomer opened this issue 9 years ago • 6 comments

In the recent weeks we had multiple high priority bugs, which were caused by the same reason: parsing paths with regexes.

I happily create a PR for this, but I have no idea what does the getModuleName function do. Are there some test cases for that?

sorgloomer avatar Aug 22 '16 12:08 sorgloomer

I don't believe there are tests for it. getModuleName() accepts a file path (a package main) and attempts to pluck out the NPM package name from it. Basically the next directory within the deepest node_modules directory. There is a slight twist in that namespaced modules consist of two path segments. I don't mind writing some tests for the function, or refactoring it to split on path.separator and inspect the parts.

developit avatar Aug 22 '16 12:08 developit

It turns out nodejs still does not have path.split, we cant bypass regexes entirely

sorgloomer avatar Aug 22 '16 12:08 sorgloomer

We could use something like this, but I don't particularly like the idea of a loop that I can't prove it will terminate.

var path = require("path");
function pathSplit(pathname) {
  var parts = [];
  for (;;) {
    var basename = path.basename(pathname);
    var dirname = path.dirname(pathname);
    if (dirname === pathname) {
      break;
    }
    pathname = dirname;
    parts.push(basename);
  }
  parts.reverse();
  return parts;
}

console.log(pathSplit("a/b/sdfsdf//cccv/node_modules/dsgdgfh")); // [ 'a', 'b', 'sdfsdf', 'cccv', 'node_modules', 'dsgdgfh' ]

sorgloomer avatar Aug 22 '16 13:08 sorgloomer

This looks better, only that it still doesn't use the path module:

function getModuleName(pathname) {
  var parts = pathname.split(/[\\/]/g).filter(p => p !== "" && p !== "." && p !== "..");
  if (parts.length <= 0) {
    return null;
  }
  var nodeModulesIdx = parts.lastIndexOf("node_modules");
  if (nodeModulesIdx < 0 || nodeModulesIdx + 1 >= parts.length) {
    return parts[parts.length - 1];
  }
  return parts[nodeModulesIdx + 1];
}

console.log(getModuleName("../../babel-plugin-asd")); // babel-plugin-asd
console.log(getModuleName("../..//babel-plugin-asd")); // babel-plugin-asd
console.log(getModuleName("..//../babel-plugin-asd")); // babel-plugin-asd
console.log(getModuleName("c:\\node_modules/babel-plugin-asd")); // babel-plugin-asd
console.log(getModuleName("../node_modules/xxx/../node_modules///babel-plugin-asd/xyz")); // babel-plugin-asd
console.log(getModuleName("xxx/../node_modules/..//babel-plugin-asd/xyz")); // babel-plugin-asd

What do you think?

sorgloomer avatar Aug 22 '16 13:08 sorgloomer

@sorgloomer Needs some extra logic to support namespaced packages. @foo/bar - they show up as directories within node_modules.

developit avatar Aug 22 '16 14:08 developit

Also, it might be easier to use path.resolve(pathname) so we don't have to worry about jumps? For the split(), could do: pathname.split(path.separator).

developit avatar Aug 22 '16 14:08 developit