Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regex creation problem through command line interface #37

Closed
connelly-steve opened this issue Dec 18, 2017 · 10 comments
Closed

Regex creation problem through command line interface #37

connelly-steve opened this issue Dec 18, 2017 · 10 comments

Comments

@connelly-steve
Copy link

Hi!
I need to replace source file paths in CSS source maps I create using a Windows batch file. I am glad I found this tool, but I had trouble getting regex search to work. Here is an example of my final answer:

call replace-in-file \"sources\":\[\".*\\\\(.*\.css)\"\] \"sources\":[\"../../src/css/$1\"] ..\..\dist\css\protections.min.css.map --isRegex
call replace-in-file \"file\":\".*\\\\(.*\.css)\" \"file\":\"../../src/css/$1\" ..\..\dist\css\protections.min.css.map --isRegex

But, to achieve this, I had to modify 'cli.js' to better split the pattern and flags:

//If the isRegex flag is passed, convert the from parameter to a RegExp object
if (isRegex) {
  //const flags = from.replace(/.*\/([gimy]*)$/, '$1');
  //const pattern = from.replace(new RegExp(`^/(.*?)/${flags}$`), '$1');
  const exp = /^(.+?)(?:\/([gimy]*))?$/.exec(from);
  const pattern = exp[1];
  const flags = exp[2] || "";
  //console.log(pattern, flags);
  try {
    options.from = new RegExp(pattern, flags);
  }
  catch (error) {
    errorHandler(error, 'Error creating RegExp from `from` parameter');
  }
}

//Log
console.log(`Replacing '${options.from}' with '${to}'`);

Before this change, I had problems with slashes and flags, whether I used flags, a trailing slash or neither of them. Furthermore, I believe logging 'options.from' makes it more transparent than logging 'from'.

@adamreisnz
Copy link
Owner

Hi there, would the solution for you perhaps be to use a configuration file with the regex in there instead of passing them via the command line? That would support more complex use cases.

If you want to create a PR for this change though feel free to open one and I'll review it there. Would be good to have unit tests for it somehow as well.

@connelly-steve
Copy link
Author

Thanks for your reply! I tried using a configuation file. I guess it would work. Also, it would allow me to call replace-in-file only once per file since I put both regular expressions in there. But the CLI resolves the configuration file path relatively to the current "working folder", which is deeper than my utils folder, no matter if I prepend a slash or not. It makes no sense for me to reprogram the entire batch file so that the working folder is my utils folder. I assume using node.js instead of a Windows batch file would definitely be better and more flexible...

@adamreisnz
Copy link
Owner

Happy to look into it if you provide more details about your folder structure and use case. You can still use the CLI but have it use a configuration file. I think you can put that configuration file anywhere you'd like, from memory.

@connelly-steve
Copy link
Author

replace-in-file being installed globally, please consider the following folder/file structure:

\javascript\utilitaires\replace-in-file.config.js
\javascript\developpement\protections\src\js\protections.js
\javascript\developpement\protections\src\css\protections.css
\javascript\developpement\protections\dist\js\protections.min.js
\javascript\developpement\protections\dist\js\protections.min.js.map
\javascript\developpement\protections\dist\css\protections.min.css
\javascript\developpement\protections\dist\css\protections.min.css.map

Excerpt from the Windows batch file:

cd \javascript\developpement\protections\src\js
call uglifyjs protections.js --config-file \javascript\utilitaires\uglify-js.config.json --output ..\..\dist\js\protections.min.js --source-map "url='protections.min.js.map',root='../../src/js'"
cd ..\css
call csso protections.css --restructure-off --output ..\..\dist\css\protections.min.css --map file
call replace-in-file from to ..\..\dist\css\protections.min.css.map --config-file=\javascript\utilitaires\replace-in-file.config.js

Result is that it tries to load the configuration file like this:

\javascript\developpement\protections\src\css\javascript\utilitaires\replace-in-file.config.js

instead of:

\javascript\utilitaires\replace-in-file.config.js

Sure, in that use case, it would be easy to rewrite the batch file, but later on it looks deeper into other folders and subfolders, where JS and CSS folders and files might not exist, all of this using for loops and exist commands to trigger uglify-js, csso and replace-in-file accordingly. That being said, until we review our deployment process, I have to make-do with this batch file way of doing it.

Maybe I am doing something wrong, but I found out that the configuration helper uses path.join with the process.cwd() and the file. May it use another method or use only the file when it begins with a slash?

@adamreisnz
Copy link
Owner

@connelly-steve you are right, I have addressed this in 3.1.0 by using path.resolve instead, which now handles both absolute and relative paths to the config file.

Please note that if you specify files in the config file, they will still be resolved related to the current working directory, not the path where the config file sits.

Also note in your example that when you call the CLI, you don't need to specify the from to arguments; those are just examples from the readme, you can specify the from and to parameters in the config file.

@connelly-steve
Copy link
Author

@adamreisnz, thank you for the update!

I removed 'from' and 'to'. I had left them in there although I had a configuration file because I was also specifying the file to search. The command line interface kept on asking for 3 arguments. I moved the file to search in the configuration file, used the '--configFile' argument alone and now the command line interface seems happy.

call replace-in-file --configFile=\javascript\utilitaires\replace-in-file.config.js

But still, I get this error:

Error: Must specify string or regex to replace
    at parseConfig (C:\Users\connelly\AppData\Roaming\npm\node_modules\replace-in-file\lib\helpers\parse-config.js:33:11)
    at combineConfig (C:\Users\connelly\AppData\Roaming\npm\node_modules\replace-in-file\lib\helpers\combine-config.js:50:10)
    at Object.<anonymous> (C:\Users\connelly\AppData\Roaming\npm\node_modules\replace-in-file\bin\cli.js:24:17)
    at Module._compile (module.js:660:30)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
    at Function.Module.runMain (module.js:701:10)
    at startup (bootstrap_node.js:194:16)

Here is my 'replace-in-file.config.js':

const options = {
    from: [
        /"sources":\[".*\\\\(.+.css)"\]/g,
        /"file":".*\\\\(.+.css)"/g
    ],
    to: [
        "\"sources\":[\"../../src/css/$1\"]",
        "\"file\":\"../../src/css/$1\""
    ],
    files: "../../dist/css/*.min.css.map"
};
return options;

@adamreisnz
Copy link
Owner

Hi @connelly-steve, the config file is require'd by the library, so try exporting from it or using plain JSON, e.g.:

module.exports = {
    from: [
        /"sources":\[".*\\\\(.+.css)"\]/g,
        /"file":".*\\\\(.+.css)"/g
    ],
    to: [
        "\"sources\":[\"../../src/css/$1\"]",
        "\"file\":\"../../src/css/$1\""
    ],
    files: "../../dist/css/*.min.css.map"
};

@connelly-steve
Copy link
Author

It works! Thank you!

@adamreisnz
Copy link
Owner

Awesome, let me know if there's anything else.

@adamreisnz
Copy link
Owner

Will close this now, but if you have any other issues feel free to reopen or create a new issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants