Siteit has undergone profound changes as I did some significant refactoring and upgrading. It was a time-consuming and thought-provoking procedure overall. Nonetheless, it improved the source code and also my coding skills.
Converting to ESM
I have longed to try out the new ECMAScript features, so converting the source code into a module was necessary. This process was not as simple as updating the package.json by adding the property type: module. I had to also set up Babel and Webpack configuration for Siteit to benefit from the new and experimental ES syntax.
Outcome
Instead of importing the files and modules the old way:
var fs = require('fs')
I can do the same using the following syntax:
import fs from 'fs'
Moreover, I can assign default parameters as follows:
const functionName = (value = "hello") => console.log(value)
These are some ways Siteit is benefiting from the new ES syntax. I listed only some of the features of ES I have implemented in Siteit recently, as the main focus of this blog entry is how I improved Siteit source code through refactoring techniques.
Refactoring the Code
Extracting functions
parseFileNamegenerateMarkup
Extracting parseFileName
- Extracting this function was necessary throughout the
html-generator.jsfile, as there are multiple instances where we have to chain multiple function calls to produce the filename for the renderedHTMLdocument.
const parseFileName = (filePath, newExt = '') => {
return path
.basename(filePath)
.replace(getFileExt(filePath), newExt ? newExt : '')
}
- The
parseFileNamefunction has two use cases: - Return only the file name (without extension)
- Return the file name (with extension passed as 2nd argument)
Extracting generateMarkup
-
generateMarkupis another function necessary to extract, as the lines of code responsible for producing markup are repeated several times throughout thehtml-generator.js, with slight modifications.
const generateMarkup = (data, isIndex = false, fileExt = '') => {
const contentForIndex = `<ul>${data.mainContent}</ul>`
const headingForTxtFile =
fileExt === '.txt' ? `<h1>${data.mainHeading}</h1>` : ''
let markup = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
${styles}
<title>${data.title ? data.title : 'Index'}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
${isIndex ? '<h1>Index</h1>' : headingForTxtFile}
${isIndex ? contentForIndex : data.mainContent}
</body>
</html>`
return markup
}
- The parseFileName function has three use cases:
- Return HTML
markupfor the index file. - Return HTML
markupfor a.txtformat file. - Return HTML
markupfor a.mdformat file.
Extracting the FileParser class
- There were many functions in
utility.jsthat operated on a shared source, depended on one another, and all dealt with process file operation. It made sense to combine all this logic into one class. This was hectic as some lines of code were introduced by the project contributors.
export class FileParser {
constructor(source) {
this.source = source[1].splice(1).toString().replace(',', ' ')
}
distManager() {
// manage creation and deletion of the output directory
}
processFile(altSrc) {
// process a single file
// invokes distManager
}
processDir(altSrc) {
// processes a directory
// invokes processFile
}
processInput(altSrc) {
// invokes processFile or processDir based on the source
}
processConfig() {
/// parsed JSON object and invokes processInput
}
}
I have omitted the member function logic as it would make this blog entry long. Click here to see the full implementation
Splitting the Code
Since FileParser as a class was massive in utility.js, I moved it to a new file named file-parser.
Outcome
- Less repetition in code as a single call to
parseFileNameandgenerateMarkupwith correct parameters is enough. - The
utility.jsis shorter now, as we have grouped the logic associated with incoming file management into a single class calledFileParser, which is in a different file.
Make code Prettier
Earlier in the semester, I got feedback to format my source code and the rendered HTML using Prettier instead of Pretty. I have modified the scripts in package.json to ensure the code is formatted each time the user executes the npm scripts; prettier reformats the source code.
The updated scripts look as follows:
scripts": {
"build": "babel ./src -d build && npx prettier --write .",
"start": "npm run build && node build/index.js -v"
}
Conclusion
Not only did I learn different techniques to refactor my code, but I also learned how to interactively rebase my code and merge it to the master branch.
It's really interesting how much progress I have made in a span of a few weeks.
Top comments (0)