Recently we have seen .Ignore
files a lot in many places, GitHub has .gitignore
to ignore file that will not be committed also prettier .prettierignore
to ignore files that will not be formatted and more others. So how can I build such a mechanism ?
How it will work ?
We will load the file and change all of it's content to regex
so that we can make the comparing functionality more efficient.
fs
module
We will be using fs
module which is one of NodeJS core modules, fs
have promises object which contains a promise version of core fs
functions like raedFile
and writeFile
to help us work with async/await
to make the code cleaner.
Loading the file
const fs = require("fs");
const loadIgnoreFile = async (file) => {
let loadedFile = await fs.promises.readFile(path, { encoding: "utf8" });
};
Change *
to .*
for pattern ignore
In .ignore
files, a person could want to ignore a pattern of files, for example all *.json
files, but regex could understand * with a character before because * means that the preceding character can be repeater more than one time.
//change all * to .*
loadedFile = loadedFile.replace(/\*/g, ".*");
File content to array
//change file to array
loadedFile = loadedFile.split("\n");
Resolve array items to paths
For example, if a person wanted to ignore dist
folder he could enter dist
, ./dest
or /dist
which can make the comparison operation more difficult. So we change what ever he entered to a full file path, so the three options of dist
folder will be for example /home/user/project/dist
.
//resolve all files
loadedFile = loadedFile.map((item) => join(resolve("."), item));
Change paths to groups of regex
A group in regex in something between two ()
for example (ABC) is a group. And then separate each group from other by or operator |
and then to make the regex only restricted to that path we will add ^ $
to each regex path. So in our work if we have two paths, let us say /home/user/project/dist
and /home/user/project/node_mdules
they are at the end after converting them to regex will be (^/home/user/project/dist&)|(^/home/user/project/node_mdules$)
//add (^filename$) to all content
loadedFile = "(^" + loadedFile.join("$)|(^") + "$)";
Returning the result in RegExp object
//change loaded file content to regex
return new RegExp(loadedFile);
We could also add some checks to see if the file exits and return a default regex if not before we go to all these steps.
Final code
const fs = require("fs");
const { resolve, join } = require("path");
//load ignore file
const loadIgnoreFile = async ( const path = ".ignore") => {
const dfReg = "(.git$)|(node_modules$)";
//check if .ignore exits
const ptIgnoreExits = fs.existsSync(path);
if (!ptIgnoreExits) return new RegExp(dfReg);
//load .ignore
let loadedFile = await fs.promises.readFile(path, { encoding: "utf8" });
// add .git and node_modules to loaded file
loadedFile += "\n.git\nnode_modules";
//change all * to .*
loadedFile = loadedFile.replace(/\*/g, ".*");
//change .ignore to array
loadedFile = loadedFile.split("\n");
//resolve all files
loadedFile = loadedFile.map((item) => join(resolve("."), item));
//add (^filename$) to all content
loadedFile = "(^" + loadedFile.join("$)|(^") + "$)";
//change loaded file content to regex
return new RegExp(loadedFile);
};
module.exports = loadIgnoreFile;
Test it
This is a simple test and will not contain any test runners or any frameworks like jest or others
Create a file say .ignore
and add to it some dummy names say dist1
and dist2
and put the .ignore
along with this code in the same folder. Create a new file called ignore.test.js
and import the loadIgnore
function and run a function in loadIgnore
called test
since loadIgnore
is actually a regex object as we see above, the test
function will return a boolean value.
const loadIgnore = require('./loadIgnore.js');
const filePath = join(resolve("."), "dist1"))
console.log(loadIgnore.test(filePath));
Top comments (0)