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
parseFileName
generateMarkup
Extracting parseFileName
- Extracting this function was necessary throughout the
html-generator.js
file, as there are multiple instances where we have to chain multiple function calls to produce the filename for the renderedHTML
document.
const parseFileName = (filePath, newExt = '') => {
return path
.basename(filePath)
.replace(getFileExt(filePath), newExt ? newExt : '')
}
- The
parseFileName
function has two use cases: - Return only the file name (without extension)
- Return the file name (with extension passed as 2nd argument)
Extracting generateMarkup
-
generateMarkup
is 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
markup
for the index file. - Return HTML
markup
for a.txt
format file. - Return HTML
markup
for a.md
format file.
Extracting the FileParser
class
- There were many functions in
utility.js
that 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
parseFileName
andgenerateMarkup
with correct parameters is enough. - The
utility.js
is 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)