Planet CDOT (Telescope)

Monday, October 18, 2021


Alex Romanova

Git rebase, amend and refactoring

The time has come! It is now an actual task to improve on our written code. Problem is... I have been doing that as I kept working on my program. Every other improvement I had in mind is already a documented issue and, frankly, not an easy one, since I tried implementing them before. Ah, yes, the old roadblocks I couldn't climb before standing here again.

Attempt at an issue

So far I have 3 "leftovers" in my issues. Sync/async, default paths (actually means I want to have the user input some options, or choose some things in the console. And for completing this issue I need to first complete the async one.) and yargs. Yargs is a more recent one, while also being an unattempted one so far. Looked doable. Note past tense in looked. It all went fine at first, I had examples to look at, I knew the steps to change my code. As it usually goes in programming fairy tales, everything was perfect until you had to run the code. I have managed to fix some things, but others I couldn't. What I noticed is the simplicity and stupidity of my mistakes, such as having a different variable name, or not including a file. Sure, some actually taught me things, such as using module.exports. The fact, however is - shit doesn't work.

Another way

Since I was already behind in the project, I decided to find something else to fix. After all, I know my code has many bad parts. It wasn't difficult to find nitpicks such as..

Yea, you know the ones. I squashed my changes, which wasn't fun at first, since I had to deal with VIM again and remember my first semester. :wq and i - literally all I had to know for this (ignoring all the other commands we learned like: replace one character, edit one word, find a specific thing, move with hjkl instead of arrows......... yeeeeeeeeeaaaa I used to know this. Long time ago. In my past life. No more!).

Rebasing was something I didn't fully understand. Specifically the part on.... why? Amend was understandable, I actually liked that one.
Here are messages that I changed with amend:

Just some clarifications on what I actually did. Yea, I'm not Einstein, I know. This was really mostly to practice git commands, rather than doing actually useful refactoring. My actual refactoring doesn't work. Look at it! Now it's not even up to date with my smol refactoring. There's honestly nothing interesting to look at in the second one.

by Alex Romanova at Mon Oct 18 2021 19:33:27 GMT+0000 (Coordinated Universal Time)


Qiwen Yu

Refactoring Code & Rewriting Git History

The easiest way to integrate the branches, as we’ve already covered, is the merge command. It performs a three-way merge between the two latest branch snapshots and the most recent common ancestor of the two , creating a new snapshot (and commit).

However, there is another way: you can take the patch of the change that was introduced on one branch and reapply it on top of another branch. In Git, this is called rebasing. With the rebase command, you can take all the changes that were committed on one branch and replay them on a different branch.

In the blog, I continued working on my repo, a static site generator (SSG) writing with Python. It started with working on a new branch git checkout -b refactoring, and the goal is to improve the structure and maintainability of the code without altering its behaviour. The main funtionality of this SSG has already been encapsulated in a class Generator, and this class was called in the main() function. Therefore, I was trying to polish the code with variables rename, making code style consistent and rewriting the support of config file functionality, which was wrote by other contributors.

The original support of config file functionality was achieved by using json parser. However, there are several packages published to support the command line config file. Here, the click_config_file module was used to support configuration file. In this way, the main() function was simlified a lot by replacing the json parser and reading json file line by line code part with a single function decorator (function annotation).

Moreover, the code style was improved on several places. For instance, inp != None was changed to inp is not None and several indentations were fixed.

Finally, an example config file was added.

Now, with several commits, we can use the terminal command git rebase main -i. This open an interactive window. Then, we can squash all commits into the first one. Additionaly, if there is a need, use git --amend to edit commit message.

Eventually, merge to main use:

git checkout main
git merge refactoring
git push origin main

The combined commit can be found here.

by Qiwen Yu at Mon Oct 18 2021 09:20:29 GMT+0000 (Coordinated Universal Time)


Irene Park

Refactoring code from ssg

Overview

This week, I was working on refactoring my own - and collaborated - code.
There were some fields of improvements that I wanted to work on.
Below are some problems that I wanted to improve.

Long main class

Originally I had very long lines of code in my main method.
Except for passing command line arguments, I decided to remove everything else from main method.
I refactored by extracting several functions and called it in main method.
https://github.com/irenejoeunpark/ssgApplication/commit/37c753470847aa9235af8b2e30b2dbdb1b7ec764 , https://github.com/irenejoeunpark/ssgApplication/commit/516dad3829f06b3336232fcc9fedb036d8f5b15d
I created an Util class called TextUtils and put all the methods that are needed for text file processing into TextUtils class.

Repeated Jobs

Text processing part was written by myself and markdown processing was written by Tracy and Diana, we were having different methods which are somewhat functioning similar.
Writing an html file was in both MDUtils and TextUtils.
We were using different styles, but I extracted the part, that is writing html header and footers except for the body part, and putted it in a utility class called HTMLBuilder.
This class works as a bridge between main and utility classes. I did not want to ruin the basic structures and way of the codes written by other students, I only extracted the part that is repeated.

It processes the input by its filetypes. If it is markdown, it asks MDUtils to create Html file. Then MDUtils borrows writeHtmlHeader and writeHtmlFoot from HTMLBuilder to write pre-defined html file forms.
It works the same for the text files.
By creating HTMLBuilder, I was able to shorten both TextUtils and MDUtils.
And it would be easier to add another feature to support different file types in the future.
These changes can be found here. https://github.com/irenejoeunpark/ssgApplication/commit/1ce8501b925c42a912507945019ac097a7fea597

Bad Naming

The naming that I wrote in the first was very hard to recognize.
Even I weren't able to recognize right away.
I wanted to improve the variable names so that anyone who would work on this project can understand what is going on.
While I was working on the naming, I found that there were several declarations that could be combined to one lines.

For example,

            String fName = fileName.toString().split("\\.")[0];

            //only getting the file name from the entire file address
            String[] getOnlyName = fName.split("\\\\");
            String name = getOnlyName[getOnlyName.length-1];

The variable fName was to remove ".txt" from the fileName, and getOnlyName was an array containing the file path spilitted by "\".
Finally name was extracting only the last element in the array to get the file name only without .txt.

I was working on the naming, and I found that those codes could be combined into one line instead of using three different variables.

            String name = fileName.toString().split("\\.")[0].split("\\\\")[fileName.toString().split("\\.")[0].split("\\\\").length-1];

After combining, it would use less memory with declaring new variables, and even easier to understand the process.
This was done with some other variable name improvements.
https://github.com/irenejoeunpark/ssgApplication/commit/63ee4eb812eccea0c60590533408e2f1a623a5fd

Messy Codes

Last but not least, there were some un-used or unnecessary variables. And there were values that were being used multiple times in the same block of code.
For unnecessary lines and variables, I removed to clean up, and for repeated values, I declared variable and re-used those.
In this process, some comments were revised and updated to clearly explain what is happening.
This process could be find in below links.
https://github.com/irenejoeunpark/ssgApplication/commit/470383f7b1430fbf360d23026663b8189a471078
https://github.com/irenejoeunpark/ssgApplication/commit/8f639d501c35c1a8e684eb611d4649fb2470f4d8

Conclusion

When multiple developers work on a same project, it is very important to do some code clean-up regularly because it is important to reduce memory for the program, and even also for the future works.
Even I had to re-set my environment, and download some dependencies from internet because it was little messed up by being worked on several developers, it was a great opportunity to learn how to make the code "better" and the importance of the refactorings.

by Irene Park at Mon Oct 18 2021 06:22:35 GMT+0000 (Coordinated Universal Time)

Saturday, October 16, 2021


David Humphrey

Yours to Discover

Today I wanted to give some credit to our government.  No, not the elected officials, about whom I have very little that's positive to say, especially during Covid.  Instead, I'm talking about the team who just shipped Ontario's Covid-19 Verification app.  I don't actually know who they are, but I respect what they did, how they did it, and I wanted to say so publicly.

Earlier in the fall, I was interested in media reports that hinted at how this app might get built (emphasis mine):

But during a press conference on Tuesday, Associate Minister of Digital Government Kaleed Rasheed stressed that both the enhanced vaccine  certificate featuring a QR code and the app that will be used by  businesses to read the codes are still “on track” to be released by Oct.  22. He said that the app will be open-sourced, allowing for it to be “continuously improved” once it is in use. "We have some of the most talented developers and designers in Ontario working on this app,” he said. “My team at the Ontario Digital Service is building the app in-house, taking advice from the private sector, and  other jurisdictions to help us get this right, to protect your data and  privacy from the start.”

Since then, I've been keeping any eye on https://github.com/ongov to see if they'd follow through.  Sure enough, yesterday my Twitter feed was full of people talking about the new Verify app. While the media was keen to go download it on their phones, I went to GitHub to read the source code.  It's now available at https://github.com/ongov/OpenVerify.

The app is Apache 2.0 licensed and written in React Native and TypeScript, using all the usual tools you'd expect (Jest, eslint, babel, etc).  It's great to be able to show this stack to my students, who are learning all these same tools and frameworks this semester. Plus reading the code and tests took me down some interesting rabbit holes, as I learned about https://spec.smarthealth.cards/ and how the QR Code validation flow works:

See https://github.com/ongov/OpenVerify/blob/main/src/services/QRCodeValidator/docs/QRCodeValidator-architecture.pdf

The whole thing is well done. I'm impressed! It's fantastic to see my own government creating digital services in the same way that I work.  I live on GitHub and seeing the potential to participate in the development and maintenance of the services I use is exciting.

There's still more I'm watching for in the coming weeks.  For one, the repo currently feels a bit like it was "thrown over the wall" vs. being an "open source project."  I don't fault the team for this, since the pressure to get it out on time must have been massive--shipped is more important than perfect & pending, and I know our family has been keen to see this thing become available in our community.  But as I write this, there's only a single commit by a GitHub account that's only ever made a single contribution.  There's no sense of who was involved, no real community here.  That's too bad.  It would be great to see some names and faces attached to this good work.

So, we have open source here, which is great; but I'd also love to see this "continuously improved" and ideally by people not in the government:

"We have some of the most talented developers and designers in Ontario working on this app,” he said

I believe it. But the number of talented developers and designers living and working in Ontario is much, much larger, and it would be great if there were obvious ways for us to get involved in projects like this. The next thing I'm watching for are how pull requests will be received.  There's already been a bit of activity from people filing Issues, which is great to see, especially since it naturally filters a bit by geography (I'm seeing devs from Ontario show up that I haven't met before, which is fun).

I'm excited by our increasingly online society and the potential it has for enabling more of our government services and data to find their way onto GitHub.  It's great that something as important as this Verification app can be trusted by the people who use it.  Over coffee today, my wife and I downloaded it in order to verify our own COVID Passport QR codes.  Seeing the green checkmark was reassuring, not least because I understood how it worked.

by David Humphrey at Sat Oct 16 2021 21:41:18 GMT+0000 (Coordinated Universal Time)


Trang Nguyen Thi Thuy

[OSD600] Contributing to Melisearch’s documentation

This week, I contributed to Melisearch — a search engine built in Rust. And I helped to add documentation on Search (issue128)

Preparation

Before writing the documentation, I read the issue’s description and start setting up the project.

Inspired on our PHP SDK’s search wiki, this document can specify features about search as the different methods exposed to the user (search() and rawSearch(), different constructors for this methods etc...
The repo’s README can have a link to this WIKI in the Custom Search section as in this PHP README example

Then I start reading the official documentation, PHP SDK’s search wiki, codes of search() and rawSearch()

Writing documentation

Basically, this documentation is the instruction of using search() and rawSearch(). I tried to follow PHP SDK’s search wiki’s approach and came up with this structure for the two methods

  • Parameters
  • Return Data type
  • Search Requests
  • Accessible methods from the SearchResult instance

Then I imported some data to test the search methods().

Then explored each attribute and method of Search Request. For example:

String results=index.rawSearch("movie_id","of");

Output:

[{
“movie_id”:3,
“title”:”Life of Pi”,
“genre”:[“Adventure”,”Drama”],
“_formatted”:{
“movie_id”:3,
“title”:”Life <em>of</em> Pi”,
“genre”:[“Adventure”,”Drama”]
},
“_matchesInfo”:{
“title”:[{
“start”:5,
“length”:2
}]
}
}]

Making pull request

My pull request has to pass 02 checks and get reviewed by a maintainer. I wasn’t sure if my documentation meet the owner’s expectations so I contacted Clementine — Integration & Core Manager of MeiliSearch. He said that the maintainer would review my pull request and it may take some time as she has a lot on her plate currently due to the Hacktoberfest.

Lucky for me, the maintainer replied to my pull request the next day and she said MeiliSearch would give me a small gift for my Hacktoberfest’s contribution. Haha, that’s cute!

by Trang Nguyen Thi Thuy at Sat Oct 16 2021 21:10:07 GMT+0000 (Coordinated Universal Time)


Tengzhen Zhao

Release0.2 week two

I have had experience about how to search Hacktoberfest issue, so I found the appropriate issue very soon. The Second Hacktoberest issue is about "String Metadata Extraction", and it is more difficult than the first one. The project named Nirjas. This project focus on extracting the comments and source code out of your file(s). The extracted comments can be processed in various ways to detect licenses, generate documentation, process info, etc.

The issue

The issue named "String Metadata Extraction". The problem is that in code files there are variables which are assigned with the strings. Extraction of it can be simply done using the same process of regex.

foo = "This is a string".
Nirjas is currently extracting several type of metadata including the SLOC, Comments. This can be a separate output metadata with only assigned string extractions.

How to do

First, I studied the code structure and understood the functions meaning. Then I authored a new function according to a similar function in this project.
Second, the point of the new function is about the regular expression. I had some regular expression experience in recent weeks. However, it is too complicated, so I need a tool to test it. I found an extension named "Regex Previewer", and it help me to find a right regular expression.

Third, Interact with the project owner and revise the code repeatedly according to their opinions.

Reflection

  1. Regular expression is very useful, but it is also complicated. We will continue to learn it in the coming weeks.
  2. Be patient! This project have sever owners and they have different style. They will put forward different requirements to improve a function, and sometimes their opinions are not clear. I need to keep good communication to clarify what needs to be modified. I have learned a lot in this process.
  3. I want to introduce my method which search the project. I used the advanced search, and choose "With this many forks <50 "in Repositories options part. It is very helpful for me to search for issues at my level.

by Tengzhen Zhao at Sat Oct 16 2021 20:04:18 GMT+0000 (Coordinated Universal Time)

Lab 5 - Improving my code through refactoring

Before refactoring, I learned the code structure of other students. I want to improve four features, but I only finished 3 of them before the due time. I have to upload them and the rest I will continue to do it.

  1. split the main file. Before that, all my code was stored in one file. I split it to two files, one store the main function named ssg_main.py. Another is assist file, and it stores all helper functions.
  2. merge get file function. There were two similar functions named get_md_files and get_txt_files. They read two different type files. I merged them into one function, and about 10 lines of statements were saved.
  3. merge output result function. There were two similar functions named output_md_result and output_txt_result. I merged them into one function, and about 5 lines of statements were saved.
  4. Try to use pathlib instead of working with path names as strings. It's not a good idea to work with paths as regular strings because I have to be careful with lots of cross-platform issues, and all of this has been solved with pathlib — Object-oriented filesystem paths. I learned the pathlib, but I didn't modify it successfully before due day. I will continue to do it.
  5. How to rebase. Use $git rebase main -i command, edit 94613fd, 3e7ecc2, 9593d95 from pick to squash. Then use $git commit --amend to combine four commits to one. The last step is merged refactoring to main and push to origin main.
  6. Reflection. At the beginning, I don't fully understand rebase command. I use $ git rebase refactoring -i command, and the terminal can't display all the commit. I should use the main branch to rebase.

by Tengzhen Zhao at Sat Oct 16 2021 03:16:44 GMT+0000 (Coordinated Universal Time)


Emily Phan

Refactoring Code

This week, I was working on refactoring my project - Shinny-SSG and experimenting Git Rebase command.

Refactoring code

There were several duplicate logics when processing input in my project. For example, in both Program.cs and SubFolder.cs , I did check the File exist, File extension and calling the FileText method CreateFile and SaveFile.

#Duplicate code
if (File.Exists(inputname) && (inputname.EndsWith(".txt") || inputname.EndsWith(".md")))
 {
  FileText temp = new FileText();
  if (temp.CreateFile(inputname, destination))
  {
   if (temp.SaveFile())
    Console.WriteLine($"File {inputname} is converted sucessfull in {destination} folder");
  }
 }

My solution for this is creating a Generator class. This class is designed to mainly focus on generate File and Subfolder. It has 2 methods are GenerateFile and GenerateFolder. I also deleted the Subfolder class and put all the logic of CreateFolder function to GenerateFolder funtion.
I also fixed issue#10 to using Path class to work with File/Folder paths instead of using string.
Another development I made for my project is removing the Global variables and rename variables.
However , I am still not satisfied with the code design. I still feel it needs more improvement to be cleaner. I will continue to work on it soon.

by Emily Phan at Sat Oct 16 2021 19:09:52 GMT+0000 (Coordinated Universal Time)


Ahmad Rokay

Second Hacktoberfest Contribution

The Issue

The issue author wanted someone to simplify anonymous types into lambda throughout the project.

Working on the issue

It had been a while since I'd written in Java or even used lambda, so I had to brush up on this first. I looked at old labs and notes from a JAC444 (Java) class I took last semester and quickly got the hang of it again.

After forking, cloning, and making an issue branch to work on, I followed the project's setup guide. The guide wanted contributors to use IntelliJ, which I had never used before. So I installed it and got the project running. Then I went searching for anonymous types.

I was actually able to chop down a lot of decently sized pieces of code. Like this nested anonymous type in ScheduleSaver.java:

new Thread() {
    public void run() {
        boolean success = false;
        if (schedule.getFile() != null) {
            success = schedule.writeToFile();
            if (!success) {
                Platform.runLater(new Runnable() {

                    @Override
                    public void run() {
                        Dialog.showError(LabelGrabber.INSTANCE.getLabel("cant.save.schedule.title"), LabelGrabber.INSTANCE.getLabel("cant.save.schedule.text"));
                    }
                });
            }
            if (callback != null) {
                callback.saved(success);
            }
            statusPanel.done();
        }
    }.start();

    if (callback != null) {
        callback.saved(success);
    }
    statusPanel.done();
}).start();
After
new Thread(() -> {
    boolean success = false;
    if (schedule.getFile() != null) {
        success = schedule.writeToFile();
        if (!success) {
            Platform.runLater(() -> Dialog.showError(LabelGrabber.INSTANCE.getLabel("cant.save.schedule.title"), LabelGrabber.INSTANCE.getLabel("cant.save.schedule.text")));
        }
    }
    if (callback != null) {
        callback.saved(success);
    }
    statusPanel.done();
}).start();

With every change, I tested and confirmed that everything was working as normal.

After replacing as much as I could find, I realized that some of the files I altered now had unused imports, because I had removed the need for them through lambda. So I had to go back and make sure I hadn't left any others hanging.

Merging

After finishing and double checking my work, I made a pull request. My pull request was approved and merged without issue!

by Ahmad Rokay at Sat Oct 16 2021 13:04:57 GMT+0000 (Coordinated Universal Time)


Mizuho Okimoto

Hacktoberfest! My first contribution

Hello October! Hacktoberfest is here!
I would like to share with you my first memorable contribution to an open source project.

Up until now, I've been doing school assignments and getting scores/grades according to the instructions given by the professors. However, the open source development course(OSD600) by David Humphrey at Seneca gave me a great opportunity to actually contribute in the real world. My first contribution was a very small start, but I would like to work up to something bigger for my 4th contribution!

First, some background on this open source project, the issue and the pull request.

Project

Artificial Brix created a artix-component-library (repository URL) which provides UI Components like Buttons, Cards, Inputs, etc. to build web applications.

Issue

"Make a better getting started readme file and also a contribution readme file" (Issue #63 URL)
This issue was about modifying the README.md file and adding a CONTRIBUTION.md file. I posted a comment before I worked on it, and one of the repo's owners got back to me and assigned it to me very quickly.

Pull Request

"Added details to README.md and created CONTRIBUING.md file" (Pull Request URL)

Second, I would like to mention what I learned from this pull request.

yarn...?💭

When I tried to run the project, I encountered a problem where I couldn't install yarn. I have never used yarn on my project, and I always use npm instead. I asked David and he gave me a detailed explanation.

What is yarn?

It was created by the Facebook developers. There was a time when developers using the NPM Registry took a very long time to update and fix bugs in the npm tool as the code size of billions of lines of JavaScript and the number of engineers increased. Facebook was dissatisfied with the pace of things and wanted to fix it for the internal team and created Yarn, which is compatible with npm but much faster.

How did I install yarn?

I had to do $npm install yarn -g on the command line to install.
When I installed node, I got npm by default. On the other hand, yarn tool has to be installed separately.

Was it okay to install it globally?

Yes, since it’s not really a dependency, in the same way that git isn’t a dependency: they are tools to build/develop the project.

Why should we avoid to install dependency globally?

It's better to avoid installing dependency globally because many projects specify the version and we don’t want to have the wrong version installed for a given project.
If you only work on one project, installing globally might be OK. But if you work on lots of projects, you might have dozens of different versions of the same dependency being used by each project. It’s always better to install to a local node_modules/ folder rather than installing globally.

I installed yarn, but yarn and yarn start didn't work! 😱

I had another problem: I opened power shell in administrator mode and entered Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted to change the PowerShell execution policies.

I finally worked!

However, it took extra time... I thought this issue: modifying README.md file and adding CONTRIBUTION.md was easy one. Since I didn't create this project, it was hard to make description for it and how much I could modify. I have decided to add a step to install yarn, License, and Contributing sections. Luckily, my professor explained about CONTRIBUTING.md in his lecture, and I created the file with references to it.

Time to push and make a Pull Request!

Although I was worried how much to improve, I finally pushed and made a Pull Request.

Merged! Accepted 🎉

Another repo's owner got back to me and requested to add more detail to the CONTRIBUTION.md file. After I modified and pushed it, the person accepted my pull request! Moreover, the person gave me kind words and comments.

I was impressed that the open source community is great place to contribute and gain experience, and many supportive people!

Conclusion

I was very happy that I could contribute to a project which was outside of school! I still don't have confidence to contribute to a big project, but I would like to take more time to find one and look more deeply into it. My contribution was small, but I acquired a better understanding from this first pull request.

In addition, I learned some useful features on GitHub. On a repository:

  • Ctrl + Shift + .: Opens a repository or pull request in the web-based editor
  • Ctrl + Shift + T: Activates the file finder

Lastly, I really appreciate the support from my professor and the contributors at Artificial Brix 💓 Happy Hacktober 🎃

by Mizuho Okimoto at Sat Oct 16 2021 06:04:28 GMT+0000 (Coordinated Universal Time)

Open Source: Rewriting git history(amend/rebase)

It's Friday which means... it's Blog Time! So many due dates!🙉
This week, I would like to introduce how to refactor my Static Site Generator(SSG) project, and also what I did for practice by using git amend and rebase.

Refactoring my SSG

Refactoring means not changing code, but making existing code easier to read, maintain, and more modular.
In fact, my SSG project had a lot of duplication, and there were a number of conditional templates, which was very inconvenient when adding new features and maintenance.
Link: my SSG project repo

What I did

  1. Added a yargsConfig.js file to keep yargs separates from the main js file.
  2. Added a tempGenerator.js file and created a function to avoid redundancy in the main js file.
  3. Replaced the code to call the function created in step2 in the pajama-ssg.js (main) file.

My redundancy code

var language = argv.l?argv.l:"en-CA";
  if (argv.s == undefined) {
    var template = `
    <!doctype html>
    <html lang="${language}">
     <head>
     <meta charset="utf-8">
     <link rel="stylesheet" type="text/css" href="please_add_your_css_path" />
     <title>${title}</title>
     <meta name="viewport" content="width=device-width, initial-scale=1">
     </head>
     <body>
     ${titleName}
     ${text}
     </body>
    </html>`;
   } else {
      var template = `
      <!doctype html>
      <html lang="${language}">
       <head>
       <meta charset="utf-8">
       <link rel="stylesheet" type="text/css" href="${argv.s}" />
       <title>${title}</title>
       <meta name="viewport" content="width=device-width, initial-scale=1">
       </head>
       <body>
       ${titleName}
       ${text}
       </body>
      </html>`;
  }

I had this code for each condition (This is when a user enter '-l' as an argument, so I had 3 more...)

My new function

module.exports = tempGenerate = (argv_s, argv_l, title, titleName="", text) => {
let style = argv_s ? `<link rel="stylesheet" type="text/css" href="${argv_s}" />` : `<link rel="stylesheet" type="text/css" href="please_add_your_css_path" />`;
let lang = argv_l ? `<html lang="${argv_l}">`: `<html lang="en-CA">`;
let titleLine = title ? `<title>${title}</title>` : "";

var template = `
   <!doctype html>
   ${lang}
   <head>
   <meta charset="utf-8">
   ${style}
   ${titleLine}
   <meta name="viewport" content="width=device-width, initial-scale=1">
   </head>
   <body>
   ${titleName}
   ${text}
   </body>
   </html>`;
    return template;
}

With this one function, I was able to remove the duplicate template in the main ssg and replace it with a single line of code to call the function.

Creating a branch for refactoring and committing

Before working on refactoring

Before I started, I made sure if I had everything from GitHub and it was up-to-date.
$git checkout main
$git pull origin main
I created a branch for refactoring.
$ git checkout -b refactoring

Testing and Committing

When I successfully added files and the function, I made a commit every time.
Added files:
$ git add
Made 4 commits:
$ git commit -m "Add yargsConfig file"

After committing, before pushing

Time to rebase!
$ git rebase -i
I used squash and melded into previous commit. Below is what I did and the display on the terminal:
I changed from 'pick' to 's' and 'squash' to squashing!

pick 563d8dd Add yargsConfig file
s 0922645 Add a function and make tempGenerator
squash 48b0fd0 replace code to call function
# Rebase 04a71d5..48b0fd0 onto 04a71d5 (3 commands)
# Commands:
# p, pick  = use commit
# r, reword  = use commit, but edit the commit message
# e, edit  = use commit, but stop for amending
# s, squash  = use commit, but meld into previous commit
# f, fixup  = like "squash", but discard this commit's log message
# x, exec  = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop  = remove commit
# l, label 
# t, reset 
# m, merge [-C  | -c ] 
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c  to reword the commit message.
# These lines can be re-ordered; they are executed from top to bottom.
# If you remove a line here THAT COMMIT WILL BE LOST.

When I saved, I used Ctrl+o and exit with Ctrl+x.
It successfully rebased and git created a new commit!

pick 9a1ea54 Add yargsConfig file
Rebase 04a71d5..9a1ea54 onto 04a71d5 (1 command)

Practicing amend

I could change my commit message by using $ git commit --amend.
Also, I learned $git --amend --no-edit command from my professor. This is where I want to update the previous commit to add/change something, but don't want to change the commit message (--no-edit means leave the commit message as it is).

Ready to merge!

I went back to my main branch, and I merged and pushed this refactoring!

Conclusion

I focused on getting rid of the 4 templates in my main js file to improve my project. I had many conditions based on the user input (if a user use -i or -s or -l or none). However, implementing a function made it easier to read since I added a condition in the separate file.
Rebasing and amending are very powerful and useful, and every time I learn about Git, I find it's very interesting. One of my goals through this course is becoming a Git master, so I hope I'm getting close to it!🧙🌟

(Photo by Hello I'm Nik on Unsplash)

by Mizuho Okimoto at Sat Oct 16 2021 02:48:34 GMT+0000 (Coordinated Universal Time)


Andrei Batomunkuev

Refactoring & Working with Git Rebase

Hi everyone! I have finished my 5th lab from OSD600 (Open Source Development) course. The tasks for this lab were to refactor the project and explore Git Rebase.

Refactoring

Code refactoring — the process of modifying and simplifying the source code without affecting functional behavior. It improves the structure and maintainability of the source code.

The complexity of the source code grows with geometric progression as we evolve the code and keep adding new features.

Having all the functionality of the program in one file makes it difficult to debug or test some functionality. We want to have a clean and structured source code, where we can easily add a new feature or test its functionality.

Lab

The task was to refactor the project (Static Site Generator tool). Here’s what I have done:

  • Created new branch “Refactoring”
  • Extracted class and functions into separate files. Previously I had all the functions and a class in one file. At this stage, I broke my application multiple times (forgot to import the functions and class that I have extracted). Those issues were easy, so I quickly solved them.
Extracting class and functions into separate files
  • Removed code duplication and renamed some variable names.
  • Created commits for each refactoring step.

Git Rebase

https://docs.github.com/en/get-started/using-git/about-git-rebase

The git rebase command allows you to easily change a series of commits, modifying the history of your repository. You can reorder, edit, or squash commits together.
Typically, you would use git rebase to:
- Edit previous commit messages
- Combine multiple commits into one
- Delete or revert commits that are no longer necessary

I have made commits for each refactoring step in refactoring branch.

I have used git rebase to combine my multiple commits into one commit by typing this command.

$ git rebase master -i

The interactive menu popped up in the terminal, and there I selected commits that I am going to “squash” — use commit, but meld into the previous commit.

I have selected the last 2 commits to squash to a single commit “pick” — use commit, then described the commit message.

Git log after rebase

Git Commit — amend

Before merging with the master branch, I changed the message of the last commit using git commit --amend . I have added a new line between the title of the commit message and bullet points.

Finally, I have merged master branch with refactoring branch.

Commit with rebase — https://github.com/abatomunkuev/static_site_generator/commit/31969477bd6640935ea8f80eb8989f8ccc98d139

Conclusion

I have explored Git Rebase and the way to change the last commit using git commit --amend . It was a good experience working with Git Rebase and refactoring the code.

by Andrei Batomunkuev at Sat Oct 16 2021 04:19:57 GMT+0000 (Coordinated Universal Time)


Eugene Chung

Deadlines and the Backup plan in Hacktoberfest

Deadlines for Week 2 Hacktoberfest

In week 2 of Hacktoberfest, my original pull request is delayed due to slower than normal communication, not because there are little people or issues to work with but rather the project has too many issues and pull request and there is a backlog.  Doing things in parallel with multiple issues saved me.

The Backup

 This pull request is originally planned for next week, because I will be busy with midterms and such.  However I got the chance to finish the code and I have tested it in the repo prompts-ai.  This repository has caught my interest because I knew the individual from a OpenAI Hackathon back in April.  As you know I am a machine learning enthusiast and the latest GPT-3 model has been on my hobby bucket list for some time.

The Changes

I noticed this code has 100+ stars in less than a year, but it actually doesn't build nor run properly due to outdated packages.  It is made in Typescript, in which is a programming language I have not touched this term, but would like to add to my growing list of programming languages used this term including Q#, C#, Javascript, python, etc.

I made a lot of changes to package.json shown in the picture below.

 

I touched over ten files some of which are minor changes but most noteworthy fix is the spread operator fix

As well as improvements to include the new Codex model.

Running Example

Here it can give the cords to the lyrics of the given song.

Running localhost:3000

Here is a fully humanized Chatbot in which i gave only 2 lines of input.


Conclusion

Even though this project might not be merged in time or be counted as Hacktoberfest, it signficantly helps me develop the next big GPT-3 template to further the process of singularity.  This was a worthwhile project in which I made my own opportunity. (issue#9)  The code is very well written and it is very structured.



by Eugene Chung at Sat Oct 16 2021 04:02:00 GMT+0000 (Coordinated Universal Time)


Tue Nguyen

Refactoring code

SOOO! For the last few weeks, with the help of other students in the course, my static site generator program has become very functional, but it has also grown in size and I was definitely in "technical debt". It was high time to refactor the code base.

Sit tight, because I have a lot to cover

Code refactoring

Below are the steps I took to repay my "technical debt"

Changing file paths handling to 'path' module

Most of my operations related to any file path were done using regEx or string functions, for example:

else if(stat.isFile() && filePath.split('.').pop() == "txt") {
    createHtmlFiles(filePath, "txt");
//... 
const fullFilePath = `${outputPath}/${filePath.match(/([^\/]+$)/g)[0].split('.')[0]}.html`; 

They don't look very readable, especially all the regular expressions. After working on others' code, I found that they used 'path' module which I also had used before, I just questioned myself why did I not do that. Below are some of the changes, they turned out to be easier to figure out what are they trying to achieve

else if (stat.isFile() && path.extname(filePath) == ".txt") {
    this.createHTMLFile(filePath, ".txt");
}
//...
const fullOutputPath = path.join(this.outputPath, `${path.basename(filePath, fileType)}.html`)

Change variable names

Not all function and variable names made sense. My function createHTMLFiles() only create one file at the time => createHTMLFile(), my variable fullFilePath left me a question which is "hhhm, what fullFilePath, did I mean the full output path. of a file" => fullOutputPath.

More changes were made

  • fileToHtml => fileToHtmlCreator because this variable is a HtmlCreator object
  • paragraphObj => bodyObj because the name was outdated, it was a 'paragraph object' for .txt files but now it's more like a 'html body object'

Extracting a function

I noticed that this piece of code was used twice in a similar way to write html files to the output folder, line 80, line 168

fs.writeFile(fullFilePath, fileToHtml.renderHTML().replace(//, `${option.lang ? option.lang : defaultLang}">`), (err) => {
      if(err) 
        return console.error(`Unable to create file ${fullFilePath}`);
      console.log(`${fullFilePath} is created`);
    });

I then wrote a separate function that does the same job to reduce duplicate code

writeHTMLFile = (fullOutputPath, fileToHtmlCreator) => {
        fs.writeFile(
            fullOutputPath,
            fileToHtmlCreator
                .renderHTML()
                .replace(//, `${this.lang}">`),
            (err) => {
                if (err)
                    return errorToConsole(`Unable to create file ${fullOutputPath}`);
                else console.log("\x1b[36m", `${fullOutputPath} is created`, "\x1b[0m");
            }
        );
    };

Refactoring the way of catching --config option

I was also not satisfied with the way the program handled --config option, so I rewrote most of the code. My approach was to catch the --config option, parse the .json first before other 'options', override the option object and return with error if --input is not specified

if(option.config){
  try {
    let configData = fs.readFileSync(option.config);
    let configOptions = JSON.parse(configData); 
    for(const [key, value] of Object.entries(configOptions)) {
      value || value.length > 0 ? option[`${key}`] = `${value}` : option[`${key}`] = undefined;
    }
    if(!option.input) {
      console.error('\x1B[31m', `error: input  is not specified in config file ${option.config}`, '\x1B[0m');
      process.exit(-1);
    }
  } catch(error) {
  console.error('\x1B[31m', `Can't read or parse config file ${option.config}\n ${error}`, '\x1B[0m');
  process.exit(-1);
  }
}

With this change, the number of lines drastically reduced.

Extracting a class

After refactoring the index.js file, I wanted to get rid of global variables so I came to a decision to create a class/module in a new file ssg.js that does all the file processing while index.js takes care of the command line. Therefore, I moved all global variables to be data members of SSG class and all functions into SSG class, I also tweaked them a bit to fit class syntaxes.

It definitely looks clearer now which also makes future debugging easier.

if(option.input) {
  var ssg = new SSG(option.input, option.output, option.lang);
  ssg.processInput(option.input);
}

Squashing all the commits into one

Each step refactoring the code base was one or more commit, since we usually care about the end result not really about the process, it's better to squash all the commits into one commit with a clear message consists of bullet points of the changes. The steps are:

git rebase main -i

Choosing which commit to be squashed and moving on to changing all commit messages into one

git commit --amend

In the end, I pushed the changes to GitHub, it was quite some work!

Checkout THE COMMIT

by Tue Nguyen at Sat Oct 16 2021 03:56:31 GMT+0000 (Coordinated Universal Time)


Antonio Bennett

Refactoring Code

Hey Everyone! If you've been keeping up then you know of Rssg my noob level static site generator for my class OSD600 :) The previous post can be found here

Task

This week we are supposed to find 3 ways to refractor our code such as renaming variables, separating logic and etc. The goal in doing so is not only to improve our code but also to practice rebasing a git branch. For rssg I decided on refractoring by

  • returning process exit 0 for main program if there was an error
  • renaming read_text function to be more specfic on what it does
  • separated the logic in the process function so it was more readable

Steps

As always if you just want to view the commit is is here

#1

My very first step was refractoring this bad boy

pub fn run() {
    //Takes appropriate action based on arguments passed ex. rssg --input
    read_arguments().unwrap();
}

read_arguments() has code that matches the cli argument and returns an Err if needed however I was calling program::exit(0) in there such as

if env::args().count() == 2 {
    println!("Please enter input. Type rssg --help or -h for more information.");
    process::exit(0);
}

when I could just return the Err like needed

return Err("Please enter input. Type rssg --help or -h for more information.".into());

and then call read_arguments like this

pub fn run() {
    //Takes appropriate action based on arguments passed ex. rssg --input
    if read_arguments().is_err() {
        process::exit(0);
    }
}

#2

This one was very simple but it made a lot of sense

I have a function named read_text that goes through each argument and calls the process function if the argument is a valid file.

pub fn read_text(args: &[String]) -> Result<(), Box<dyn Error>> {
    //Iterate through each input and process
    args.iter().for_each(|arg| {
        if let Ok(mut file) = fs::read_to_string(arg.to_owned()) {
            //Reaches this if the argument was just a filename
            process(&mut file, arg);
        } else if Path::new(arg).is_dir() {
            //Argument is a directory so we have to recursively search the dir
            let path = Path::new(arg);
            visit_dirs(path, &process).expect("Couldn't convert dir");
        }
    });

    Ok(())
}

It is much more appropriately named as process_arguments

#3

Previously my process function which turns the input file into an html file was suuuuuuper convoluted because it basically had an if check with logic in both the if and else for files with and without titles. I separated this logic into 2 separate functions and call them inside the if check instead. This makes the code more readable and easy to follow.

    if vec_lines[1].is_empty() && vec_lines[2].is_empty() && !vec_lines[0].is_empty() {
        process_file_with_title(
            vec_lines,
            &mut html,
            &mut firstline,
            &mut is_header,
            &mut line,
            prev_tag,
            ext,
        );
    } else {
        process_file_with_no_title(
            &name,
            default_content,
            vec_lines,
            &mut html,
            &mut firstline,
            &mut is_header,
            &mut line,
            prev_tag,
            ext,
        )
    }

Rebasing

This was a pretty cool process. You can rebase to pretty much combine multiple commits into one by doing git rebase main/master -i while on the checked out branch. It is a very cool git command to know but I'm not sure on how often I'd honestly use it. It is great though to have it as a tool that I could possibly use in the future :)

by Antonio Bennett at Sat Oct 16 2021 03:28:02 GMT+0000 (Coordinated Universal Time)

Hacktoberfest Week 2

Hey everyone! My previous week for Hacktoberfest can be read here:

Project

Let me start off by saying this week was awesome! This week I worked on a discord bot named parrot which is something I've never done before. It is written in rust and is in the early stages of development.

Issue

The issue I was assigned this week was to implement the !playtop command. This command when used will place the requested song or playlist at the top of the queue.

PR

Now let me tell you I racked my brain for a while to think of an elegant solution to this problem. Lets look on how to modify a queue. The modify_queue() function is defined on the type trackQueue and takes a closure as an argument which exposes the queue, which is essentially a vector of songs.

Now imagine we have the queue

let queue = vec![0,1,2,3,4];

The song at index 0 is always the current playing song. So when manipulating the queue it should remain untouched. To do this we can use the split off function to get the rest of the songs.

let mut non_playing = queue.split_off(1);
queue: 0
non_playing: 1,2,3,4

To the place the newly inserted song (called 5 in this case) we can just rotate the non_playing vec to the right by one which preserves the order.

non_playing.rotate_right(1)
non_playing: 5,1,2,3,4

For playlists I calculated the num of songs in the playlist and subtracted it from the length of non_playing so that the first song of the playlist is at the top. Writing this now, in hindsight I could just call rotate_right passing the num of songs in the playlist but meh.

let rotate_num = non_playing.len() - num_of_songs;
non_playing.rotate_left(rotate_num);

Lastly we append non_playing back to the original queue by doing queue.append(non_playing)

The final important bit of code is below. Check out the PR for all the details

fn reorder_queue(handler: &MutexGuard, is_playlist: bool, num_of_songs: usize) {
    //Check if we need to move new item to top
    if handler.queue().len() > 2 {
        handler.queue().modify_queue(|queue| {
            let mut non_playing = queue.split_off(1);
            if !is_playlist {
                //rotate the vec to place last added song to the front and maintain order of songs
                non_playing.rotate_right(1);
            } else {
                //We subtract num of songs from temp length so that the first song of playlist is first
                let rotate_num = non_playing.len() - num_of_songs;
                non_playing.rotate_left(rotate_num);
            }
            //Append the new order to current queue which is just the current playing song
            queue.append(&mut non_playing);
        });
    }
}

Overall Thoughts

This week was awesome! I loved working on something new and the task was just right in having me explore new ways of solving a problem. I had a ton of fun and I am excited for the rest of Hacktoberfest. Drop any Rust repo suggestions for me in the comments :)

by Antonio Bennett at Sat Oct 16 2021 02:01:29 GMT+0000 (Coordinated Universal Time)


Amasia Nalbandian

Five birds one stone

We're all very familiar with the phrase "to kill two birds with one stone." This week I learned I could kill more than two birds with one stone by using git rebase.

Background

I've used this command previously and it resulted in a huge mess where I pulled in a bunch of commits that I did not make in a branch, and then all those commits got added to my PR.

This week I learned exactly why that happened by actually understanding what git rebase does.

Lab 05

For Lab 5 I was more than happy to see we could use the time to refactor our code for the static site generator(SSG). I discussed my struggles setting up the SSG in release 0.1 and with that came a lot of bugs and what I will refer to as "working" code(to say that it could be better is an understatement).

After my experience from release0.1, I was lucky and grateful to have David and Reza log in some issues on top of the ones I discovered. I decided to use these to refactor the code.

Commits

Below are the issues I decided to use for commits to then squash.

Adding protection to invalid arguments in the cli
Fixing the mismatch license
Fixing incorrect variable types
Improve error handling

Outcome

After creating commits for each of the issues, I then ran an interactive git rebase by using the following command:

git rebase main -i

To my surprise there was a lot of interaction in the CLI through Vi, and it threw me off as I tried to understand what I was supposed to do. This is the image of the message in the editor:

After a few seconds I realized what I had to do was change the text from pick to squash to squash all five commits into one.

Once this was done I received the following:

I then went ahead and I checked out back to main, and merged my changes from the refactoring branch. I learned another thing here: My local commits from the refactoring branch were able to be merged into the main branch which was in GitHub. I had never tried this before without putting both branches up on GitHub, which explains why I was probably a bit shocked.

Lastly, I wanted to attach this image below which would demonstrate how a rebase works.

And another image here, which explains the difference between a rebase and a merge (as I know most people use these methods to grab latest commits from main branches in their feature branch.... cough cough me).

by Amasia Nalbandian at Sat Oct 16 2021 02:50:25 GMT+0000 (Coordinated Universal Time)


Hung Nguyen

Contribution to "Time It"

Overview

The project I contributed to is an ElectronJS app named "Time It". The owner of the project had a problem related to the sidebar. She wanted the sidebar to be toggled (on/off) instead of being static. I found this issue was interesting to me then I asked the owner to take a shot and she assigned it to me.
Firstly, I came up with an idea to create a burger menu icon to toggle the sidebar.
Before clicking the menu icon:

After clicking the menu icon:

I did some research about CSS animation and onClick function on React to make the change. Then I created a new branch named burgerMenu and started working on the issue.
Code explanation:
I created a burger menu component to create a burger menu icon


Then inside the Sidebar.js, I modified the class name of the Sidebar, so when the menu icon is clicked, the class name will add active. Sidebar only shows up when active is in its class name.

After some tests. I decided to send a Pull Request to the owner to merge my burgerMenu to her main.

Interaction with project owner
For the first time, I faced some problems related to install the project. She helped me a lot in figuring the problem out. I was event added to her private discord group of this project. This made me feel happy since I felt like I was a part of the team. My project was still not merged because of some conflicts and corrections needed, but we still working on it.

Links:

Issue: https://github.com/time-it-app/time-it-app/issues/3
Pull request: https://github.com/time-it-app/time-it-app/pull/7

by Hung Nguyen at Sat Oct 16 2021 02:37:32 GMT+0000 (Coordinated Universal Time)

Refactoring, and Rebase

Refactoring codes

This week is a good time for me to take a look back at my project to make some improvements. My program is working as expected but my codes are not clean and optimized. There are still a lot of redundant codes of testing stage, repeating codes and some ambiguous variable names.
Firstly, I created a new branch name refactoring then wrapped all duplicated codes up into a function. Then call that function in appropriate places. Variable naming is important in professional programming. It makes your codes more easily to understand when other people try to read them or when you want to look at your codes to make some changes. If you name your variable a which stands for array, other people might misunderstand it and they might think a is argument. This also the same with naming functions. In the end, all the names of variables and functions are now more clear and understandable. Lastly, I deleted all the console.log that I created while testing to make my code neat and look more professional.

Git Rebase

Each time I finished an improvement, I committed that step. After testing my tool many times to make sure it still works, I git rebase main -i to move my recent commits to the top of the sequence of commits. With option -i, my command will do an interactive rebase to allow me to choose what to do with my commits. I picked pick for the latest commit and the others are squash so that they will attach to one commit only. Finally, I did git commit --amend to modify my latest commit last time and merge the refactoring to main then push.
Git rebase is beneficial for maintaining a clean history of your project. With git rebase, your branching workflow is easily visualized, since you can rebase your old branches to the top so that you can start fixing and debugging your codes with ease.

by Hung Nguyen at Sat Oct 16 2021 01:34:58 GMT+0000 (Coordinated Universal Time)


Le Minh Pham

[DPS909] Continuing My Hacktoberfest Journey

This week, I continue my Hacktoberfest journey with two more contributions!

Issue #1: Adding data to a JSON file

After some time browsing through GitHub with the “good first issue” tag, I came across this issue. It belongs to osm/name-suggestion-index repo, which is a library used in OpenStreetMap, one of the largest open-source maps applications.

The goal of this project is to maintain a canonical list of commonly used features for suggesting consistent spelling and tagging in OpenStreetMap.

The program produces suggestions using data from the JSON files in their /data/ folder. My task was to add the data for a music school that the maintainers believed was big enough to be in their database. They also provided the JSON string to be added, as well as where the appropriate JSON file was located. I then simply looked for the file and put the JSON string inside. Here is a link to the pull request.

Issue #2: Remove unnecessary else/elif blocks

I wasn’t satisfied with the first issue for this week, as I felt like it was a bit too simple, so I looked for another project to contribute to. And I found NearBeach, which is a beta-staged project management system build with Vue.js and Django, both of which are pretty new to me. The issue I got was to remove the ‘unnecessary’ else/elif blocks in the code. They also provided a link to demonstrate what they meant by ‘unnecessary’. Assuming you have an if/else block, and there is already a return statement inside the if block and there is no more code after them in a function, like this:

def classify_number(x):
    if x % 2 == 0:
        return 'Even'
    else:
        return 'Odd'

If you remove the else statement and shift whatever is inside it outside the if/else block, like this:

def classify_number(x):
    if x % 2 == 0:
        return 'Even'
    return 'Odd'

It will still do the same thing. Therefore, the else is unnecessary and the first approach is considered a bad practice (which I learned thanks to this project!). The second approach improves readability and makes it easier to maintain.

The maintainers also showed me where the above bad else blocks occurred in the code, which I then easily fixed. However, while working on this, I accidentally deleted a blank line after one of the functions. And when I submit my pull request, one of the format checker bots gave an error, saying there must be 2 blank lines in between each function or class definition in the python files. Another good practice I learned from this project! I quickly fixed the error and pushed another commit. My code then passed all the automatic checks and got approved and merged by the maintainers not long after. Link to my pull request.

Conclusion

Two more Hacktoberfest contributions down! Only one more to go. I also picked up some new knowledge along the way, especially some good coding practices. Looking forward to more hacking!

Links

The first issue:

The second issue:

by Le Minh Pham at Sat Oct 16 2021 02:35:36 GMT+0000 (Coordinated Universal Time)


Jun Song

Refactoring?!

My Github project repo: Repo
Commit: Commit

Overview

In this time's lab, 5 purpose is for students to do refactoring themselves opensource project. When I saw this lab 5, actually I was being happy because honestly after 3 times working with my collaborators the API's code is getting un-efficient and long. It doesn't mean my classmate's work is useless it was enough helpful, but just need to remodeling :)

What is changed..?

So, after reading this I quickly started to work for it. I separated 3part of to-do things for refactoring each refactoring are..

added start function to handle promise error

I realized that the try and catch function has a promise error, so I changed it like this

async function start() {
    try {
        const { argv } = getParams();
        const {
            input: fileOrDirectory,
            output: outputDir,
            stylesheet: cssUrl,
            config: config,
            lang
        } = argv;
        if(!fileOrDirectory && !config) {
            throw new Error("Please include an input filename or folder");
          }

        await convertFilesToHTML(fileOrDirectory, cssUrl, lang, outputDir, config);
    } catch (err) {
        console.error(err);
        console.log(chalk.red(err.message));
        process.exit(-1);
    }   
}

start();

organized files

I separated some functions into another file.

reduced duplicated part

const convertToHTML part was duplicated, so I divided them as await getParamsData and await getFileData

exports.convertFilesToHTML = async (filename, cssUrl, lang = "en", outputDir = "dist", config) => {
    const paramsData = await getParamsData(filename, cssUrl, lang = "en", outputDir, config);

    const fileInfos = await getFileData(paramsData.input);

    //function part for generating an index file to go to sample pages.
    await createIndex(paramsData, fileInfos);    
};

Combine all commit to one..

After finishing all refactoring part(currently) I merged all of the commits to one commit from lab 5's instruction(used squash)

commit 10b5254e98ca6dbbfd4982dc671ec14487164821 (HEAD -&gt; master, refactoring)
Author: jsong89 &lt;jsong89@myseneca.ca&gt;
Date:   Thu Oct 14 20:14:47 2021 -0400

    Refactoring ssg to improve code maintainability:
      * added start function to handle promise error
      * organized files
      * reduced duplicated part

Conclusion

After this lab, I realized how much important that before we are going to commit something should not commit every each of the small things. It will make other developers confuse what is the point of the commit and distracting them because too many lists are there. So, I will not commit every moment will carefully committing the essential part.

by Jun Song at Sat Oct 16 2021 02:03:26 GMT+0000 (Coordinated Universal Time)


Jiyun Jung

Improving Code through Refactoring

For code improvements, I focused on the following points.

1. Separate files according to functional criteria.

I divided the code related to HTML generation and the code related to the command line, split it into two files, and put it in a util folder. There was one error in this part, but it was removed by adding the following codes.

command.js

module.exports = {
    getArgs
}

html.js

module.exports = {
    isKeyInObject,
    HTMLgenerator
}

index.js

const { getArgs } = require('./util/command');
const { isKeyInObject, HTMLgenerator } = require('./util/html');

2. In each divided file, unnecessary code is removed and structurally modified to make it easier to read.

In my judgment, there were many unnecessary if statements, so I removed them. I removed them because I think it would be better if it showed the error message. Through the first and second processes, I increased the readability of my project.

The part I removed in index.js

if(flags['inputFlag'] == false){
                  argv['input'] = "test/The Naval Treaty.txt"
                  argv['i'] = "test/The Naval Treaty.txt"
                  }
                  if(flags['langFlag'] == false){
                      argv['lang'] = "english"
                      argv['l'] = "english"
                      }
                  if(flags['outputFlag'] == false){
                          argv['output'] = "dist"
                          argv['o'] = "dist"
                          }

3. Add the necessary parts due to the nature of the code function.

I have not previously added a -o, i.e. result value option. Since the output option was in the -config option, I decided that it was also necessary for the command line option and made it work by modifying the code. In addition, I also updated the README.md file according to the updates.

 const output = argv.output ?? 'dist';
        if (!fs.existsSync(output)) {
            fs.mkdirSync(output);
        }
        await fs.promises.writeFile(`${output}/${filename}.html`, getHTML(filename, html, lang));

I committed to each of the above processes. And when I pushed it, there was a git error. Because among the codes I committed, there were overlapping code lines. So I made a manual correction after using fetch, pull git commands.

by Jiyun Jung at Sat Oct 16 2021 01:59:54 GMT+0000 (Coordinated Universal Time)


Oliver Pham

How I Refactored my Code

This week, I noticed that some functions in my static site generator (SSG) were hardcoded with complex logic and "magic values", so I decided to focus on refactoring them. Without cleaning them up, maintaining them would be a tragedy. For instance, there was a function spanning 36 lines of code with 8 if/elif statements. Some of the statements even have nested if/elif statements themselves. You can find the function referenced in this issue.

Code Refactoring

To resolve the above issue, I thought the best approach was to avoid reinventing the wheel and save myself hours of debugging: use a third-party library. After implementing a Python implementation of John Gruber’s Markdown, 36 lines of code were cut down to a single function call. I've not benchmarked my SSG after the change, but in terms of code readability, it's certainly worth the overhead caused by the library.

Another part that needed to be refactored was the function for extracting a file name without its (multiple) extensions from a file path. For some reason, there was confusing and irrelevant validation of the file extension inside the function.

# Inside the function
if pathlib.Path(file_path.split('.')[0]).stem == ".md" or pathlib.Path(file_path.split('.')[0]).stem == ".txt":
  return pathlib.Path(file_path.split('.')[0]).stem 
elif pathlib.Path(file_path.split('.')[1]).stem == ".md" or pathlib.Path(file_path.split('.')[1]).stem == ".md": 
  return pathlib.Path(file_path.split('.')[0]).stem 
elif pathlib.Path(file_path.split('.')[1]).stem == ".json" or pathlib.Path(file_path.split('.')[1]).stem == ".ini": 
  return pathlib.Path(file_path.split('.')[0]).stem 
else: 
  return pathlib.Path(file_path.split('.')[0]).stem

Since that's already checked at the beginning of the program, I simply removed the redundant checks.

The last piece of refactoring was probably the most problematic one. There was a block of code for setting the value of the options read from a JSON configuration file for generating an HTML document.

 def silkie(input_path, stylesheet, lang, config): 
     """Static site generator with the smoothness of silk""" 
     try: 
         # Set options for generating HTML document from config file
         if config is not None: 
             with open(config, "r", encoding="utf-8") as f: 
                 config_item = json.load(f) 
                 if "input" in config_item: 
                     input_path = config_item["input"] 
                 else: 
                     input_path = None 
                 if "stylesheet" in config_item: 
                     stylesheet = config_item["stylesheet"] 
                 if "lang" in config_item: 
                     lang = config_item["lang"] 

         kwargs = dict(input_path=input_path, 
                       stylesheet_url=stylesheet, lang=lang) 
         options = GeneratorOptions( 
             **{k: v for k, v in kwargs.items() if v is not None}) 
         # Clean build 
         shutil.rmtree(DIST_DIRECTORY_PATH, ignore_errors=True) 
         makedirs(DIST_DIRECTORY_PATH, exist_ok=True) 
         # Generate static file(s) 
         if path.isfile(input_path) and is_filetype_supported(input_path): 
             generate_static_file(options) 
         if path.isdir(input_path): 
             for extension in SUPORTED_FILE_EXTENSIONS: 
                 for filepath in glob.glob(path.join(input_path, "*" + extension)): 
                     options.input_path = filepath 
                     generate_static_file(options) 
     except OSError as e: 
         click.echo( 
             f"{TextColor.FAIL}\u2715 Error: Build directory can't be created!{TextColor.ENDC}") 
     except FileNotFoundError: 
         print(f'Error: There is no Json File "{config}" !') 
     except json.JSONDecodeError: 
         print(f'Error:Invalid JSON syntax!" ') 

I found this too irrelevant to be included in the main method, so I extracted to a method inside the GeneratorOptions class.

During the process of refactoring, I noticed a logic flaw with the above code. If the input_path was not included in the configuration file, it could crash the program (due to input_path being set to None). Thankfully, it was fixed before my code was committed. With that done, it was time for rebasing and squashing!

Git Interactive Rebase

It is indeed unnecessary to keep all the commits of each iteration of refactoring, so squashing them sounds like a good idea. After entering git rebase main -i into my command line, I edited my commit message one last time to make sure it's detailed and clear enough. After squashing all my commits into a single commit, I could finally merge my refactoring branch, where I'd been refactoring my code, into the main branch.

Conclusion

Luckily, throughout the code refactoring process, I didn't encounter any other major issues or crashes. It was not only a good chance to clean up my project but also a wonderful opportunity for me to learn more about Git Interactive Rebase and amending a commit.

by Oliver Pham at Sat Oct 16 2021 01:41:05 GMT+0000 (Coordinated Universal Time)


Suhhee Kim

Refactoring the codes

This week's lab was refactoring my code. I mainly worked on 4 parts which reduce code duplication by creating functions, make the code more readable by putting correct indentation and separate code into functions, categorize functions and put it into different javascript files and improving variable names

First, to reduce the code duplication, I created functions instead of copy and paste the same code for several places. For example, to create a HTML file, After put the name of the input files into the array, the input from the user is whether file or folder, it is using the same logic. Hence, I just copied and paste the same code to the two places. But in this lab, I create a function called "writeHTML" and just call the function if it needs.

Second, I try to make the code more readable. First, I fixed indentation and spacing. And I create more functions such as create HTMLForm, readFile, writeFile, createHTML, and so on. I tried to create functions that only have one feature in one function. I read from the book called "How to write clean code". It is always better to keep one feature in a function. This is because it is easier to do debugging and it helps to maintain the application.

Third, I created two different js files, categorize the created functions, and put them in the write file. one is consol.js which has functions about how to process cli input from the user and the other one is htmlCreator.js which has functions to process the input file to the HTML file.

Last, I improved variable names, I used a doubly-linked list to save the name of the text and markdown files. So, when I need to get a full name with extension then I need to access like TextArr[filenum][0].concat("."+TextArr[filenum][1]). But it seems too complicated, so, when I tried to refactor the code and create the function. Hence, instead of write whole name, I just pass "TextArr[filenum]" so in the file, it can just access by Text[0].concat("."+Text[1])which seems much more simpler. And for the simple edited variable names, I fixed "url" to "CssUrl" to make the variable name easier to understand.

After I refactored my code, I push it to the refactoring branch and merge it to the master branch. Everything works very smoothly :)

While I am doing this lab, I found an error that I couldn't found an error from the last partner who added the config feature to my file. Because she just fixed the config file, when I merge her code, I just tested the config feature. But while I was testing the version, help, and input before I separate the functions to make sure it works, all the commands were not working. Hence, it took me some time to fix it first before I refactoring the code. I learned that before I merge other's code or before I push my code to other's repository, I need to do an explementary test even though I just edited one feature to not break the program.

To sum up, Before I do this lab, if I want to change the structure or try to edit a large part of the code, I make a copy and save it somewhere in my local storage and erase the old one if the fixed one works well. Hence, while I am doing this lab I was so happy that from now I don't need to do the silly thing.

by Suhhee Kim at Sat Oct 16 2021 01:29:14 GMT+0000 (Coordinated Universal Time)


Leyang Yu

Hacktoberfest Week 2

Intro

We're already halfway through October! This week, I focused on finishing up my second issue that I had started working on last week in the Wordpress Openverse Catalog repository.

Using the New Issue Forms Feature

The issue
The pull request

The purpose of this issue was to update two of the issue templates that the repository was using from markdown (.md) to YAML (.yml) by using the new issue forms feature. The new issue forms provide a more user-friendly interface (for those who may not be familiar with markdown syntax) and also allow for form validation. Although the project did not require much setup, it was my first time writing a file in YAML so I first went over the GitHub docs to learn the proper syntax.

Although the issue did not seem too complicated when I first began working on it, I soon encountered a few roadblocks. Thankfully, the code reviewers were all very kind and responded to my commits and questions right away with helpful suggestions and answers.

Roadblock #1

Form fields in issue forms can accept label and description attributes, such as:

 - type: input
    id: source
    attributes:
      label: Source Site
      description: Please provide a link to the Source site that you'd like considered for inclusion on Openverse
    validations:
      required: true

The label (title) and description are styled like the following in issue forms:

However, for the issue I was working on, some "form fields" were more for providing information and did not require user input (they are not really fields, but in the original template, they are styled similar to fields). The only way I could create these fields was by using "type: markdown", which could not accept label or description attributes. Therefore, the code for such a field would look something like:

- type: markdown
    attributes:
      value: |
        ## General Recommendations for implementation
        Modify this section if necessary

        - The script should be in the `openverse_catalog/dags/provider_api_scripts/` directory.

And the output would look like:

As you can see, there is an underline beneath the label and the description also looks different compared to the first example.

Roadblock #2

Another issue I had was that I wanted to combine a form field that wasn't "type: markdown" with markdown text. For example:

In the above, the form field I used was "type: checkboxes". I wanted to style the text that is highlighted using markdown, but I could not find a way to do so unless I used "type: markdown". However, if I did so, then there would be no form validation for the checkboxes, which is a major reason for using the new issue forms feature.

After looking more into the documentation for issue forms and trying different solutions, I asked the code reviewers about this problem. They said that this wasn't a big issue and my code was successfully accepted. In the end, I created two new issue forms, one for Image Provider API Integration Requests and one for New Source Suggestions for Openverse and my work was merged here.

You can see an example of the before and after for the New Source Suggestions form below:

Conclusion

A big takeaway I got from working on this issue was that there are still a lot of limitations in the new issue forms feature. Although markdown issue templates have been around for a while, YAML issue forms are relatively new and still in beta. Personally, I think there could still be some improvements to allow for an easier transition from issue templates to forms and also better support for custom form fields and styling.

In addition, I realized the importance of communicating frequently with the code maintainers. For example, I spent a lot of time researching how to fix the issues I mentioned previously, but it turns out that this was not a big concern for the maintainers.

Overall, I learned a lot from this experience and can't wait to get started on my next pull request.

by Leyang Yu at Sat Oct 16 2021 01:25:31 GMT+0000 (Coordinated Universal Time)

Friday, October 15, 2021


Gustavo Tavares

Time It App Lets Go!

Hey,

It’s good to see you again!

This time I want to talk about my Second time collaborating on someone’s project. This time I was able to collaborate in the Time It App.

Time It app goal is to allow its users to record time and calculate the amount they should charge for it. It keeps the record of all the timed events you have and allow you to copy it to your clipboard.

The Issue

Issue #2 was the issue I decided to work on. Basically, my goal was to add a button loader for the Settings page buttons.
The project use React to build its components so, besides my React being rusted, it was really good to work with it again.

The Solution

First, I had to make a loader using CSS. I used this as reference and ended up using this:


.loader {
    border: 10px solid #f3f3f3;
    border-radius: 50%;
    border-top: 10px solid #364f6b;
    width: 15px;
    height: 15px;
    -webkit-animation: spin 2s linear infinite; /* Safari */
    animation: spin 1.5s linear infinite;
    margin: auto;
  }

  /* Safari */
  @-webkit-keyframes spin {
    0% { -webkit-transform: rotate(0deg); }
    100% { -webkit-transform: rotate(360deg); }
  }

  @keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }

To make the Loaders work, I added a state for each, L8 and L9.

const [isLoadingDelete, setIsLoadingDelete] = useState(false);
const [isLoadingCopy, setIsLoadingCopy] = useState(false);

Because I had to make a loader appear for a process that is almost instantly, I thought it was a better idea to make a symbolic loader instead of one that would last until the process were being processed.

So I decided to use setTimeout() to make the loader appear for just a couple of seconds.

 function clearLocalStorageData() {
        localStorage.clear();
        setIsLocalStorageEmpty(true);
        if(!isLocalStorageEmpty){ // This one!
         setTimeout(function(){ setIsLoadingDelete(false); }, 1500); // This one!
         setIsLoadingDelete(true); // This one!
        }
    }

and

function localStorageTextToClipboard(text) {
        if (text != null) {
            let newText = text.toString();
            // formatting copied output
            newText = replaceAll(text, '[{', '');
            newText = replaceAll(newText, '}]', '');
            newText = replaceAll(newText, '{', '\n');
            newText = replaceAll(newText, '}', '');
            newText = replaceAll(newText, ',', '\n');
            const temp = document.createElement('textarea');
            document.body.appendChild(temp);
            temp.value = newText;
            temp.select();
            document.execCommand('copy');
            document.body.removeChild(temp);
            setTimeout(function(){ setIsLoadingCopy(false); }, 1500); // This one!
            setIsLoadingCopy(true); // This one!
        } 
    }

Then I just had to adjust the JSX to make it work:

 {isLoadingDelete 
    ? 
"loader" /> : }

and

 {isLoadingCopy 
   ? <div className="loader" /> 
   : <button
    className="PinkButtonYellowText"
     onClick={ () => 
     localStorageTextToClipboard(localStorage.getItem('tasks'))}
     >
      copy task data
   </button>}

I also happened to find a bug that made the onClick function to fire nonstop if a task could be copied to the clipboard, which I fixed while was solving the loader question.

 //Before 
onClick={localStorageTextToClipboard(localStorage.getItem('tasks'))}

//Fixed
onClick={ () =>
  localStorageTextToClipboard(localStorage.getItem('tasks'))}

The Result

Before:

After:

Finally

This was a great project to contribute to, the people that I have interacted were polite and very welcoming which made me feel very comfortable.
Feels really good to be useful and capable to help other people.

I hope you have enjoyed reading this!
Thank you so much and see you again!

by Gustavo Tavares at Fri Oct 15 2021 23:32:16 GMT+0000 (Coordinated Universal Time)

Time to Refactor!

Hey,

This Lab goal is to refactor our code and to make our first rebase!

To be completely honest, I had refactored my code long time ago, when David made Issue #7 and Issue #6.
So for this lab I had to make only a few changes to make it good to go.

How I Did It?

I tried to remove all redundant and duplicated code I had, I made everything into functions and put every function in its own module, this way my main file has only a few lines of code.
Now, the code is way easier to understand and more efficient too.

Which modules I have created?

My SSG now is composed of the following modules:
-GMOT-SSG.js
-htmlAssembler.js
-htmlMaker.js
-writeFile.js
-yargsConfig.js

Time to Rebase!

This was my first time rebasing anything, it was not complicated to be honest, with the “-i” flag it allowed me to choose which option I wanted for each commit I had so I made my 3 commit became only one with the fixup option.
It is pretty useful, specially for me because I use to make a lot of commits.

Thank you for reading!

by Gustavo Tavares at Fri Oct 15 2021 19:41:03 GMT+0000 (Coordinated Universal Time)


Roman Rezinkin

DPS909 - Lab 5

This weeks lab included us refactoring our code. The point was not to introduce new functionality or features, but rather instead clean up our code. I chose to do three improvements to my static site generator, which included reducing code duplication through the use of functions, improving variable names, and separating the main logic from the conversion functions.

Functions - Reducing Code Duplication

This was the hardest part of the lab. I essentially had to rewrite my code, all whilst testing every code change. I was able to reduce my code duplication by a large amount. This was achieved by creating a few functions that accepted parameters from the main logic, and allowed me to create html files in a simpler way. By doing these mandatory steps, my code is a lot more readable, which means that if someone wanted to contribute to my open source project, they would have an easier time doing so.

Improving Variable Names

Some of the variable names within my code were very confusing, so much so that I had other developers ask for clarification on the meaning behind them. I took the initiative during this lab to make them more understanding.

Separating the Main Logic

In my last refactoring step, I took the chance to split my main logic code from the bulk of the other code. This means that now there are two files, one being a utility file, which contains all the functions needed to operate my static site generator, and the second being the main , which holds the argument parsing, etc.

Overall, the git rebase and squashing was pretty straight forward. Here is a link to the commit...

by Roman Rezinkin at Fri Oct 15 2021 22:47:15 GMT+0000 (Coordinated Universal Time)


Leyang Yu

Refactor and Rebase

Intro

I have been working on my static site generator, Jellybean, over the past few weeks and others have also added new features to my code. The code has gotten a bit messy and difficult work with and this week was a good point to refactor the code so that I can continue building on it in the future. In this post, I want to discuss the changes I made and how I utilized Git during this process.

Commits I Made

1

First of all, I decided to move all my source code into a src directory to improve the organization of my repository.

2

All of my JS code was in a single file, index.js. I decided that it would be better to split the file up into three files: index.js, processInput.js, and createHtml.js. Index.js contains the main function, as the entry point into the program. ProcessInput.js contains functions for validating user input and and createHtml.js contains functions for converting the input file(s) into HTML files.

While refactoring the files, I did a lot of testing and noticed some bugs that I hadn't noticed before. For example, the program should be able to accept either a --config or --input flag with a valid argument. However, my program printed an error message if no config argument was specified, regardless of whether or not there was an input argument. Therefore, I found this refactoring process to be very useful in also debugging my program.

3

I renamed all the JS files so that they followed kebab case rather than camel case. For example, processInput.js and createHtml.js became process-input.js and create-html.js.

4

I had a function in process-input.js called readFile which read a single file and created the corresponding HTML file in the output directory. It also created a style.css file in the output directory every time an HTML file was created, which shouldn't be happening. I didn't like that this function for creating HTML was in the process-input.js file. I decided to remove readFile and move all the functionalities related to generating output to two new functions in create-html.js called setupOutput for setting up the output directory and calling other functions to generate all required files (such as index.html, style.css, etc.) and createHtmlFile for creating HTML files.

5

I decided to do some general cleanup, including renaming variables and functions and reducing the number of parameters for some functions. For example, a function that checks if the user input is valid or not was named getUserInput so I renamed it to checkUserInput. Another example would be the getUpdatedHtmlLayout function. Originally, this function accepted five parameters. It became hard to maintain as new features were added and I had to continuously increase the number of parameters and change all function calls. Instead, I decided to pass an object containing everything needed by the function so now the function only needs to accept one parameter.

6

I forgot to commit a few files I had deleted previously, which is what this commit was for.

7

At the very end, I did some testing and realized I had made a mistake in one line and used a variable that hadn't been initialized yet, which broke the program. I created a commit to correct this mistake.

Rebasing

I've been a bit weary of using git rebase after I messed up a rebase during my first week at a CO-OP and gave my supervisor a hard time in correcting my mistake. At the time, I hadn't used Git before and had no idea what a rebase was, and I never used rebases since, but thankfully, rebasing my commits went much better this time around.

It was my first time learning about interactive rebases and I found this process to be so useful as it gives you so much freedom in customizing your commits. I used the interactive rebase command (git rebase main -i) to squash all my commits into a single commit. In addition, I used the git commit --amend command to modify my commit message and add more details. After this exercise, I feel so much more confident in using rebases to modify my commits and project history.

Overall, I think my repository looks much cleaner now and will be easier to work with going forward.

by Leyang Yu at Fri Oct 15 2021 21:47:01 GMT+0000 (Coordinated Universal Time)


Kevan Yang

Lab 5 - Refectory code and git rebase

Intro

For my fifth lab, we have to implement refactor our Static site generator CLI repo.

Refactor

Move handler file to handler folder

I moved my ssgHandler.js to src/utils/handler instead of being in the root folder. This helps to have everything in a respective folder.

Remove unused package

Removed some unused package import. They were some import declaration in the code that was never used. Removing it can make a cleaner code.

Remove duplicate code

In the code, they were some redundant code that wasn't necessary or can be simple to make it less redundant.

Add error handling for await

Add error handling for await, I wrapped most of the await call into a try/catch to handle the error. This makes code traceability easier.

Use promisified versions of fs

Removed promise wrapper for some node fs function. Instead changed to fs.promise.

Isolate function not related to ssgHandler to its own files

ssgHandler.js file was getting bigger and there is a lot of function that wasn't related such as reading files, data processing. I moved every unrelated function to its own file. So it is making it easier to maintain in the future.

Refactor names

In my code, there is some naming issue like inputPaths the name is in plural but the input path should only be a single path. To avoid some confusion I renamed it to inputPath

Rebase

After making all the commits for the above change. I wanted to squash into 1 commit. I first run the command git rebase -i master and pick the commit that I needed to combine together to squash and leave one commit to be pick. After saving the files I wasn't happy with the name of the commit, I run the command git commit --amend and changed the name. (b092da9)

Conclusion

Cleaning the code is something useful, it will help in the future as the project grows to have better maintainability.
Git rebase is super powerful too, It is like merge but can combine everything into 1 commit.

by Kevan Yang at Fri Oct 15 2021 21:43:13 GMT+0000 (Coordinated Universal Time)

First contribution on a react native repo

Intro

For release 0.2, we are participating in the Hacktoberfest. I started to search for some issue with the label "good first issue" and I end up with one issue in the heylinda repo.
The issue was Upgrade Expo to the latest version. It was a simple task.

First I fork the repo, then clone it and install all packages needed to run in my local. To run the application I had to do yarn run start. Since it is in react native I need an emulator on my desktop or an IOS or Android phone. I choose to use the expo application in Android to run the application on my phone. After playing around in the application it was time to upgrade expo to the latest version. I run yarn upgrade expo to upgrade expo to the latest version. After upgrading it. I had to re-run the application locally and test the application that it didn't break anything.
When the testing was done I created a pull requested PR#85.

It felt great contributing to someone else repo. Even though the issue was not something complex

by Kevan Yang at Fri Oct 15 2021 21:04:09 GMT+0000 (Coordinated Universal Time)


Roxanne Lee

Refactoring and Git Rebase

Lab 5 of OSD600

For this week’s lab we got to clean up our own code through refactoring, then learn to rebase and squash the commits into a single commit.

The result of my lab can be seen in this one single commit.

Refactoring

I think the idea behind refactoring is that as our code grows, and as we learn more coding techniques, its important to continue to clean up our code so that it has better structure, and make it easier to maintain.

I had previously seen some refactoring issues when I was on the hunt for public issues to work with, but I had skipped them not knowing what refactoring meant. This lab had helped clarify the technique for me, and I had found the link (in the lab) to common refactoring patterns really helpful, and I’m sure it’ll be really handy to reference in the future as well.

Some of the changes I made to clean up the code included

  • Rename variables

This was just simply renaming variables for better readability.

  • Extract File Class

One thing I noticed about my code was that many of the functions asked for file paths, but sometimes these paths were single file paths, and sometimes it was the input path from the input option. My functions were also all over the place, some dealing with single Files, some dealing with the whole data, etc. So I decided to extract a File class to make things more structured.

Previously, I had wanted to put the createFile function inside of the File Class, but I had a problem when using the transform stream, as it wouldn’t recognize the toHtml method inside of the File Class. I had to leave the createFile outside of the class, and have it call file.toHtml() in the transform stream instead.

  • Extract Data Class, extract processOptions function.

My initial idea was to get rid of some of my global variables that I had, most notably “stylesheetUrl”, “outputPath” and “extensions”. So, I began with extracting a Data Class, then found out it doesn’t completely take off these global variables, so I extracted a processOptions function to put those variables inside the function block. Throughout this process I had crashed the program many times, mostly from changing function parameters within the Data Class, and from changing from global variables to using the variables within the class.

  • Extracted getHtmlContent function

Afterwards I realized I had some duplicate code, mostly the html block for creating individual .html files from the input path, and creating the index.html file for input path with directories. So a function was extracted to get rid of code duplicity.

  • Split index.js and data.js

Finally I split off the data we get from the input option into its separate unit.

I know my code is still far from perfect. Looking through my code again as I write this I noticed a few things I could clean up on. We’ve been told we’ll be starting to write tests for our static site generators soon, so I’d like to clean up more of my code before that.

Git Rebase

As the professor has mentioned in the lab, for cases like refactoring, we only want the end result, and it doesn’t really matter how many commits it got to that point. So we learned the git command

git rebase main -i

where the option -i for interactive, and the command gives us an interactive menu in where we can change the commands for our commits.

# Commands:
# p, pick &lt;commit&gt; = use commit
# r, reword &lt;commit&gt; = use commit, but edit the commit message
# e, edit &lt;commit&gt; = use commit, but stop for amending
# s, squash &lt;commit&gt; = use commit, but meld into previous commit
# f, fixup &lt;commit&gt; = like "squash", but discard this commit's log message
# x, exec  = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop &lt;commit&gt; = remove commit
# l, label &lt;label&gt; = label current HEAD with a name
# t, reset &lt;label&gt; = reset HEAD to a label
# m, merge [-C &lt;commit&gt; | -c &lt;commit&gt;] &lt;label&gt; [# &lt;oneline&gt;]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c  to reword the commit message.

To get all our refactoring commits into a single commit we used the squash command, so that it can meld into the commit before it.

I also used git commit --amend to fix the commit message.

Reflection

I didn’t have any problems with the rebase interface, and now that I know about rebase and refactoring, I can clean up my code without having to worry about flooding my repository with minor commits. Furthermore, now that I finally know what refactoring means, I can probably contribute to refactoring related issues on GitHub.

Overall, it as a really useful lab, and I had a lot of fun with it.

by Roxanne Lee at Fri Oct 15 2021 21:19:01 GMT+0000 (Coordinated Universal Time)


Jia Hua Zou

Git Refactor and rebase

For this week’s lab I was introduce to rebase and squash. In order to rebase my program, I will making improving my code.

Refactor

My refactoring goal for my program was to fix bugs, remove redundant codes, and move codes into functions and different files.

Fix bugs

There was a bug where if the user uses the --input it prints out an error. It happens because it was not checking if the data was valid.

Remove redundant codes

I had a section where I was reading the files twice. First one was if the input is only 1 file and the second one was for when it is reading through the list of files in a folder. What I did was I move the block of code into a function call readFile() .

Moving codes

The program was getting too big, so I decided that I want to move all of the functions that has to be with writing data to the HTML files to another file called fs-html.js . This had made the codes a lot of readable.

Rebase

Afterward I commit for each of the changes that I did to my program and start the rebasing.

Problem

I ran into a problem when I try to squash my commits. It was telling me that I have merge conflict. I try to fix the merge conflict I see that it is trying to merge all of the older commits. So I end up aborting the rebase and try again. I later found out the problem. When I tell Git which commit to squash and pick , I move the latest commit to the top of the line. This cause the merge conflict problem because it thinks that the old commit is at the top.

Conclusion

After fixing that mess, I got my rebase working and squash all of the old commits into one. The rebase feels like a merge but it shows the history of all the commits into 1 commit.

by Jia Hua Zou at Fri Oct 15 2021 20:33:38 GMT+0000 (Coordinated Universal Time)


Francesco Menghi

Refactoring and Git Rebase

The deep dive into the git universe continues. One really cool concept I have learned this week is git rebase: it is like moving a series of commits to a new base commit.

Series of commits

To practice, I worked on refactoring my dodo-SSG project in a new branch that I called refactoring. I started by fixing the code format from previous contributions using prettier. I then changed the code to get rid of global variables. To do that, I had to split up some code into separate smaller functions. At each of these steps, I created a new commit to make sure I could easily go back to the previous version if anything broke (And things broke a lot while doing this!).

Putting it all together

Once satisfied with what I had, I used the command git rebase main -i to rebase into the main branch. The -i stands for interactive mode and it opened my editor to allow me to customize my commit.

All the commits made in the refactoring branch are now displayed in chronological order. Each line shows a command word (pick by default), a commit id and the commit message. Like this:

pick 28cd74de fix code format with prettier

These are the available commands to use:

# Commands:
# p, pick &lt;commit&gt; = use commit
# r, reword &lt;commit&gt; = use commit, but edit the commit message
# e, edit &lt;commit&gt; = use commit, but stop for amending
# s, squash &lt;commit&gt; = use commit, but meld into previous commit
# f, fixup &lt;commit&gt; = like "squash", but discard this commit's log message
# x, exec  = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop &lt;commit&gt; = remove commit
# l, label &lt;label&gt; = label current HEAD with a name
# t, reset &lt;label&gt; = reset HEAD to a label
# m, merge [-C &lt;commit&gt; | -c &lt;commit&gt;] &lt;label&gt; [# &lt;oneline&gt;]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c  to reword the commit message.

I used squash for all the other commits in the list to merge them all into the first commit. To change the final commit message I used:
git commit --amend. Now the commit message includes everything. I could have also used changed pick to reword to edit the commit message during the interactive git rebase.

Outcome

I believe the code is now easier to read and easier to maintain going forward. The code looks very different now and there is definitely more that could be improved. I love the git rebase workflow and it is for sure something I will continue to use going forward.

by Francesco Menghi at Fri Oct 15 2021 20:15:48 GMT+0000 (Coordinated Universal Time)


Eugene Chung

OSD600 - Lab 5 Refactoring CMD-SSG

 Introduction

This week we are refactoring our beloved open source SSG program  We learned to use the git commands git rebase as well as git commit --amend to rewrite history on a branch and to add/change our git message as well as the command git merge in the end.  Refactoring is a technique for improving the structure and maintainability of your code without altering its behaviour. I made several refactoring changes.

Refactoring

 1. created a new helper.js file to add all functionality of generating .html from .txt and .md files

 2. exported the functions checkInput, convertToHtml, displayError as new or existing functions to make the code cleaner.  "checkInput" does input checking of what the user enters, "displayError" is a function specific to displaying error codes and convertToHtml is an existing function to generate the final html files.  

 3. refactor some variables names that are not up to standard like test1 and test2 such as the following image.


Additions

4. I added support for output folder command with -o or --output as well for better use.

5. added a config.json test file and made changes to README.md

Time for Some Squashing

git rebase main -i

and...

git commit --amend

then... the commit message 6a0e543

 

* extracted helper functions to new file to make code more modular

* Extract error codes into single use function

* Renamed test and test2 variables

* refactor/fix code for output

Ta Da... git push origin main

Conclusion

This week has been a truly busy week for me, but I did not overlook the fact that what I learned here this week will change the way I view, code or experience Git and Github.  I no longer feel like a novice at Git or have began to shed my fear of it.  I still make mistakes, but I know how to fix things now.

Thanks for Reading guys.

by Eugene Chung at Fri Oct 15 2021 19:07:00 GMT+0000 (Coordinated Universal Time)


Andrew Tassone

First Pull Requests - SnapIT HacktoberFest

I began working on pull requests for Octoberfest this week. I haven't really done much work on big repos, other than my classmates or my own. I found a great project by SnapITSolutions that is an open source project that directs users to their in-person and virtual hackathons.

I enjoy working with react and websites so I thought this would be fun to work on. I solved two open issues that were created by another developer. The first was adding support for other languages to the homepage. The other included adding support for other languages to the registration page.

In order to fix these issues, I first had to add the translations required into a json file for both es-us and en-us. I then had to ensure the react-intl module was imported to provide the service for each page. Lastly, I added FormattedMessage to all buttons and textfields as a wrapper, in order to translate all of the values.

After I was done creating my pull request, I realized I missed a step in the contribution guidelines that require all pull requests to be linted and tested with ESLint. Tests failed the first time but I was able to correct it by simply importing the react-intl module in one of the pages.

The code was eventually merged by the developer. I created one pull request instead of two which meant less credit for Hacktoberfest, so the developers were nice enough to allow me to create another one.

It felt great contributing to the community and communicating with someone who's all the way in Texas. I hope to continue to work on this project and make it even better!

by Andrew Tassone at Fri Oct 15 2021 18:51:13 GMT+0000 (Coordinated Universal Time)

Refactoring The Great Site Generator

This week, I focused on refactoring this project using git rebase to rewrite history on a branch for my first time. I also learned how to use git commit --amend to change the information in my commit.

I wanted to reduce redundancy in my code so I created a function called readFolder() for reading folders. I also combined readMarkdownFile() into readFile(). This supports both file types of either .txt or .md.

Lastly, I separated these functions into a new class called Reading. I then placed the class into its own reading.h file. I broke it a few times during this process, usually just forgetting a brace somewhere.

Using the interactive vim to edit commits was new to me. Ive used command line editors before but not very much. At first, I made a few mistakes by accidentally adding too many spaces between the commit ID and action. I received a few errors but figured it out eventually!

Changing git history was interesting and a useful thing to learn when cleaning up code and changing commits. It was confusing to do at first but I will keep practicing. I hope to use it again in the future!

by Andrew Tassone at Fri Oct 15 2021 16:40:42 GMT+0000 (Coordinated Universal Time)


Luigi Zaccagnini

Refactoring Code in Octo!

Update

Hello Everyone! Welcome to my weekly blog post about my journey in Open Source. This week I will be focusing on my experience with refactoring my code for Octo and working with the rebasing feature with Git. I also wanted to share that while writing these blog posts, I will also be posting about Hacktoberfest every week until the end of October so be sure to read those blog posts as well.

Refactoring Code

When I first started reviewing my code I was looking for common problems that could be modified to make the code more readable or less redundant. I found enough of those problems to start making a list and track what I wanted to change about my code. Here are the problems I wanted to refactor!

Function names aren’t clear enough.

While reviewing the code I found that some functions names don’t clearly explain what the functions do. An example of this is the getPathInfo function. When I first named the function I was naming it based on one of the parts of the function. Now seeing how this function acts more like a main function rather than just handling one part, I found a more fitting name for it. Now seeing this problem I renamed the function from getPathInfo to main.

Redundant code that can be turned into a function

When I was looking at the textToHTML and textToHTMLWithMarkdown functions I found some redundant code for processing each line from the file. I saw this and wanted to write a function so we can get rid of the redundant code. It was difficult at first on how to transform the code into a separate function because of variables tied to the functionality. Once I was able to figure out how I wanted the function to work with the code, I was able to replace the redundant code with the lineChecker function.

// New lineChecker function
const lineChecker = (line, isFirstLine) => {

let document = ``;

if (line !== "" && isFirstLine) {

document += `

${line}

`
; } else if (line !== "" && !isFirstLine) { document += `

${line}

`
; } else if (line === "") { document += "
"
; } return document; };

Redundant variable declarations & variable names need better names

Some of the code that was written had variables that would be defined at the start of a function and then declared later in the function. For this situation, that was not needed as the variables can be defined and declared at the start of the code. Not a lot of variables were changed as most of them were named best to explain their purpose. The main one I did change was doc to document. I changed this variable name because I find that it is important to use full words so everyone understands what the variable is. I know this is a bit extreme but it is always good to be very clear with your variable names.

Removed unused code

Removing unused code was the easiest fix as visual studio code shows you want isn’t being called or used. It was also easy because this is a very small project and there was not as much unused code as a major project might have. This part I just removed my original textToHTML function and replaced it with the textToHTMLFixed function.

Rebasing and changing Git history

Rebasing my code was a lot easier than I thought it would be. I used the

git rebase -i main

and went into interactive mode to squash everything into a single commit. After I was finished I used

git commit —amend

to edit my commit message to something more clear.

Conclusion

In Conclusion, no code is perfect code and refactoring code can teach you a lot (even if it is your own code). During the refactoring process I went very slow with each change to make sure nothing would break and made sure there were no bugs while I was running the code. Don’t forget to go find a Open Source project and contribute! This week I found a Open Source discord being created called Fosscord and thought it would be very interesting to share. I am still finding a style with how I want to do blog posts so if you have any feedback or recommendations please write them in the comments! Thank you for reading!

by Luigi Zaccagnini at Fri Oct 15 2021 16:45:44 GMT+0000 (Coordinated Universal Time)


Andre Willomitzer

Code Custodian: A lesson in refactoring.

The Story So Far...

When the OSD600 course began, we were asked to create a Static Site Generator tool to create HTML documents from txt files. Then, we were asked to add extra options to allow for customizing the HTML files such as stylesheet. As the weeks progress we added more and more features to the project. I noticed my code was following the same pattern for each of the operations, with minor tweaks in the HTML template based on the options passed in.

Improvements

The focus of my refactoring for this lab was making a module for my Yargs configuration options, and refactoring my repeated code into functions that can be called instead of retyping all the HTML template strings like so:

Previously, instead of calling generatePara(), I would have had the split/map/join and regexp repeated inside each of the txt "if" statements checking file type. Furthermore, you may notice

let styles = argv.s ? `\n"stylesheet" href="${argv.s}">` : "";

which previously was a statement checking

if(argv.s){render the whole html template + link tag}

By doing it this improved way, I can simply add "styles" variable to my HTML template, and if it doesn't exist a blank string is added which produces nothing in the HTML. This allowed me to eliminate 2-3 repeated if statements and make the code much more readable.

I did the same thing in the Markdown sections and made a separate function to handle h1, h2, and p tags. I removed the repeated template code, added a function, and changed the styles tag as I did with txt.

yargsConfig.js

In terms of the Yargs code, I made a module and required it in my main file in order to get access to "argv" value. This helped me make my main textToHTML.js file much cleaner because the setup code for Yargs was put into it's own file and textToHTML.js just handles the file logic.

Squash... and not the vegetable.

At the end I had a total of 4 commits and used git rebase -i main to squash the changes into 1 commit. Overall the command was very intuitive and allowed me to pick my 1st commit and squash the others into it. I then went to rename the commit message so that they would all be under a single name of "Refactored textToHTML.js for modularity". A link to the final commit can be found here.

Thanks for reading!

by Andre Willomitzer at Fri Oct 15 2021 16:20:21 GMT+0000 (Coordinated Universal Time)

Testing the testers (Jasmine contribution)

This week for my open source contribution I decided to tackle a bigger project and a slightly more complex issue. Last week, I removed commented code, this week I added some code. For my repository, I chose to fork Jasmine, and the issue involved adding some extra descriptions to an error message regarding "expectations" and asynchronous tasks in the Jasmine framework.

The issue was that the error message was pointing to one cause, but not anything else that was possibly causing the error. I had a look at the previous comments about what they were doing when the error occurred, and some suggestions from a contributor about done() function and how it executes.

In order to find the file to change in this massive project I took advantage of a Github feature. It allows you to click on a function (similar to Visual Studio) and find the definition. I clicked the error generator function to see where it was defined and change the error.

He mentioned that done() should only be called when you're sure the test is finished and that there won't be any async tasks started after done(). Originally the issue was reported when someone did in fact call done() and then start an expectation.

To fix this, I amended the error message in 2 different files (env.js and EnvSpec.js) to include 3 potential causes:

  • 1. Did you forget to return or await the result of expectAsync?
  • 2. Was done() invoked before an async operation completed?
  • 3. Did an expectation follow a call to done()?

In this way the person running the test can check more causes than just awaiting the result (such as terminating the test before the task can finish).

Each time I made a change, I ran "npm test" which runs their full test suite to make sure that all the errors and test cases pass.

For example, the test caught me when I didn't change the error in env.js but I did change it in EnvSpec.js and it gave me a message saying these 2 errors don't match each other even though they're from the same cause.

Before I could submit my Pull Request however, I had to fix some styling issues such as running Prettier. Furthermore, the maintainer of the project asked that I make my lines of code no more than 80 columns. To fix this, I split the string into separate lines using concatenation and newlines. Finally, in order to merge I ran "git rebase main -i" and squashed my 4 commits into 1. After those steps my pull request was accepted!!!

This was my first time working on such a large project and repository and it was a unique experience. One thing I would do different is add even more description to my pull request about how I tested the feature and what I changed.

by Andre Willomitzer at Fri Oct 15 2021 14:15:51 GMT+0000 (Coordinated Universal Time)


Japneet Kalra

Refactoring the SSG Convertor

Introduction

Hello everyone, this week we are introduced to a new topic to refactor the entire code to make it effective, shorter and understandable. Update all changes to one single commit on git.

Improvements

To Begin, I started with improving indentation and some comments to make my code understandable. I have been receiving a lot of issues with the code being tough and not understandable. I certainly wanted to make the code shorter now I got the chance.

Bugs found

While refactoring the code, a lot of bugs were found. Initially, I had one function developed that looked like a mess. I tried to improve the indentation first & foremost to make it look comfy. The second step was to remove global variables. Third and mainly, Refracting of functions which took me a lot of time to cover. The extraction of function development was not necessary to run the program. But, they were prominent to improve the readability of code. In the end, I did rename some variables to make them easier to read, easier to maintain, and more modular.

Broke the program

My program did broke certain times while working on the refactoring branch. I tested code a lot of times working on extracting functions. I tried to make it common code and reduce the duplicity of code. However, it didn't go very well. I ended up breaking my code due to a lack of knowledge of working with functions in swift. I learnt that in functions with parameters those values are unchanged. The parameters are let constants that are non-convertible.

Working with git

  • creating branches to work on evolving your code
  • using git rebase to rewrite history on a branch
  • using git commit --amend to add things to a previous commit and update a commit message
  • Final Commit

Conclusion

Learnt how to use git rebase and git commit --amend those are very powerful commands in git to make commit modifiable and shorter.

by Japneet Kalra at Fri Oct 15 2021 08:36:41 GMT+0000 (Coordinated Universal Time)


Le Minh Pham

[DPS909] Refactoring My SSG Code

This week’s lab gave me time to work on refactoring my SSG program (at last!).

Table of Contents

Introduction

This week’s lab asked us to refactor our SSG program, which was exactly what I had been wanting to do for a while, especially since my two main python files kept getting bigger and bigger, but I hadn’t managed to found the time (or the motivation) to do so. I decided to seize this opportunity and make some meaningful changes to my awesome cool_ssg_generator.

Re-structuring The Whole Project!

After many days of browsing through GitHub looking for things to do for #Hacktoberfest, I came across a lot of Python projects. And while spending time with them, I noticed that the project’s source codes were often put inside a subfolder, rather than having everything at the root level, which was how my cool_ssg_generator structured at the time:

My project folder before refactoring, with everything at root folder

Since then, I came up with the idea to put all my python scripts under one folder. At first, my main concern was that I thought this approach would make running the program a little bit more inconvenient, as the command would have been quite long (i.e. python cool_ssg/main.py -i … instead of python main.py -i …). However, this concern went away as soon as I learned that there was a way for Python to treat my program as a “package”, which meant that if all my source codes are under the cool_ssg package, I can simply call:

python cool_ssg -i example.txt

to run my program. This command looked a lot cleaner to me, which was why I decided to have a go at this approach. To make this happen, I needed to make sure the Python interpreter understand that my /cool_ssg/ folder is a valid Python package. First, I had to create an empty __init__.py file in that folder. I then moved my main.py file into /cool_ssg/, and renamed it to __main__.py, which basically told the interpreter that this file contains the entry point for my program. And voila! First commit down, and my project looks much cleaner, the command is also shorter, and is now using the program name cool_ssg as the argument, instead of the boring main.py.

My project is now cleaner! No more source code in top level yay 🤟

Separating The Modules

Next step, I wanted to divide my codes into different modules, since my two source code files were getting a bit crowded. I separated the argument parsing as well as the config handling codes into their respective python files named config_util.py and arguments_util.py. I also wanted to give my helper.py file a better name, so I renamed it to html_generator_util.py to match the naming scheme of the other files. I then put all these utility files under a /utils/ folder. However, Python did not let me import them into my __main__.py yet, and after some more googling, I added another __init__.py inside /utils/ so that Python knows this is a valid Python module before allowing me to use the codes inside. Here is my source structure so far:

Separating the codes left me drowning in errors (unsurprisingly). After hours and hours of screaming in agony and trying to make sure that everything still works perfectly and no function is missing, I finally got it to work. I made several commits in the process.

Replacing os library with pathlib

While working on separating the modules, I realized I might have overused regex patterns for getting files’ paths, names, and extensions. Regex seems very hard to read, and I felt like I would completely forget what those patterns even mean after a while. Therefore, I decided to look for a cleaner solution. And the library pathlib solved it for me. It makes dealing with files and folder paths much easier. However, I also used some functions from the os library in my code already, and since they pretty much do the same things, I wanted to get rid of one and replace it with the other. pathlib methods seemed a bit more cleaner to me, so I decided to went with it. It has an equivalent function for each one os has (minus a couple), which made replacing them especially easy. The only problem I encountered was that there is no equivalence of os.walk(), which returns every subfolder and file inside a directory tree. Instead, pathlib has a Path.rglob(pattern) function, which returns all files in a folder that match the pattern. The behaviors of these two functions are somewhat different, which meant I had to change my code up a bit. I was finally able to replace all the os functions with pathlib correspondence and safely remove the import os statement, with a ton more debugging in the process, of course.

Conclusion

By refactoring my code, I learned a lot more about Python, especially in terms of project structure and modules. It also makes my project less horrendous and a tiny bit easier to run. I also learned how to squash multiple commits into one using git rebase --interactive. I’m glad that this assignment exists, as it gave me time to make the changes I have been wanting to make to my code for a while, but did not have enough time. Check out my cool_ssg_generator here and my refactoring commit here.

Also, guess I can also use this meme with confidence now

by Le Minh Pham at Fri Oct 15 2021 07:51:17 GMT+0000 (Coordinated Universal Time)


Vivian Vu

OSD600 - Refactoring My SSG

1. Lab5 requirement

As my-ssg was updated with a lot of new features over the past few weeks and these features were written by different contributors, my-ssg's source code will unavoidably contain duplicated logic, inconsistent naming conventions, etc...

This lab requires us to refactor the existing code so its structure and maintainability will be improved. Additionally, this is a good practice for using git rebase we have learned this week.

Here are some modifications I had applied to my-ssg:

2. Refactoring process

First of all, I started looking at the index.js file where option declarations and input path validation are placed. This file seemed a bit lengthy back to the time so I decided to extract checkInput() and trackDistFolder() into a newly module.

Secondly, I realized that using global variables is not necessary and some variable names and file names are not really good. As a result, I changed global variables to scoped variables and renamed some variables/file names to get more meaningful names.

During the refactor process, I encountered some errors and these errors made my program exit inappropriately. Therefore, whenever there is an error, I will display a log message and use return statement with a non-zero exit code to solve this situation.

 try {
    await fsPromise.mkdir("./dist");
    console.log(chalk.bold.green("--- dist folder is created successfully! ---"));
  } catch (err) {
    console.log(chalk.bold.red("***Cannot create dist folder!***"));
    return process.exit(-1);
  }

Next, as I stated above, it is inevitable for the source code to not contain any logic repetition. Not surprisingly, I could find some here:

  • Repeated logic and not clear variable names:
const sortedFile = files.filter((file) => path.extname(`${inputPath}/${file}`) === ".txt");

sortedFile.forEach((file) => { 
const fileName = fileModule.readFile(`${inputPath}/${file}`, cssLink, language, outputContainer);
const url = `./${encodeURI(fileName)}.html`;
body += `${url}\">${fileName}\n`;
});

const sortedMDFile = files.filter((file) => path.extname(`${inputPath}/${file}`) === ".md");

sortedMDFile.forEach((file) => {
const fileName = fileModule.readFile(`${inputPath}/${file}`, cssLink, language, outputContainer);
const url = `./${encodeURI(fileName)}.html`;
body += `${url}\">${fileName}\n`;
});

---> Solution:
----> Create getBodyHTML():

function getBodyHTML(path, stylesheet, language, outputContainer, fileExtension){
  let fileName = fileExtension == ".txt" 
                 ? readFile(path, stylesheet, language, outputContainer) 
                 : readMDFile(path, stylesheet, language, outputContainer) ;
  let url = `./${encodeURI(fileName)}.html`;
  return `${url}\">${fileName}
\n`; }

----> Rename variables:

const textFile = files.filter((file) => path.extname(`${pathToFile}/${file}`) === ".txt");
textFile.forEach((file) => {
      body += getBodyHTML(`${pathToFile}/${file}`, stylesheet, language, outputContainer, ".txt");
    });

 const mdFile = files.filter((file) => path.extname(`${pathToFile}/${file}`) === ".md");
    mdFile.forEach((file) => {
     body += getBodyHTML(`${pathToFile}/${file}`, stylesheet, language, outputContainer, ".md");
    });

  • Since I just created the checkInput module, now I can use it after finishing reading a .json file instead of copying the same checking logic in index.js as before:
const fs = require("fs");
const check = require("./checkInput");

module.exports.readJson = (pathToFile) => {
  fs.readFile(pathToFile, "utf8", (err, json) => {
    if (err) {
      console.log(chalk.bold.red("***Cannot read the file!***"));
      return process.exit(-1);
    }
    const data = JSON.parse(json);

    const stylesheet = data.stylesheet || "https://cdn.jsdelivr.net/npm/water.css@2/out/water.css";
    const language = data.lang || "en-CA";

    check.checkInput(data.input, stylesheet, language, true);
  });
};

After all, my final commit is 92e007

3. Rebasing

Overall, git rebase -i is a very helpful command. It helped me to squash multiple commits into a single one. Meanwhile, git commit --amend allowed me to adding or modifying the commit message so it will be more meaningful and understandable.

by Vivian Vu at Fri Oct 15 2021 06:46:46 GMT+0000 (Coordinated Universal Time)


James Mai

Week 6: Refactoring and git rebase

This week I will is about refactoring my code and you guys can check out my change at this commit 6f20f71

**Summary of what I did

I change my README.md,package.json, LICENSE to close 2 issues #3 and #4

I did move the parsing comman line argument into src/argv.ts and parsing html into src/html-maker.ts and instead of a global variable let inputPath; I decide to wrap all of them in another function for best practice

And thanks to the advises on Slack from my prof, I decide to change using camel case which is my favourite to kebab-case.js
**Git rebase

I think this week we leanr another best practice using git where we can avoid octopus node using $ git rebase . I remmeber when I first start Git, people keep talking about Git as a time machine and now I know why. Rebase will move your HEAD one commite above and when you merge it back to the main branch, you will have a nice and clean commit log.

$ git commit --amend also super usefull. I did not remeber how many times I have to create dummy commit because I forgot to change one or 2 small things in my working tree and have to start another new commit. Amend the commit really come out and help my git log way cleaner

by James Mai at Fri Oct 15 2021 06:13:15 GMT+0000 (Coordinated Universal Time)


Reza Poursafa

[OSD600] Rebase, Squash and Git Ammend

This week I was introduced to some very useful git concepts such as git rebase, squashing our commits, and using git amend.

Refactoring My Code

One of the tasks in this week’s lab was to refactor and clean up our code from the static site generator application.

Since I was waiting for this opportunity to clean up my code,I made a lot of changes to the code.

I created a function for output folder creation and success messages.
I also separated reading files and appending the data to HTML into multiple smaller functions and used them in all of the functionalities( read data from file, folder and markdown file).

I also renamed some of my variables to be more understandable.

The other fixes to my code were regarding fixing some of the error handlings and receiving options in config.json.

Git Rebase

I found this feature very interesting. I played with rebase a bit and got lots of errors while doing it which helped me understand it more.

I rebased my files and squashed all the commits into one. Then I used git commit --amend to remove the spaces between the commit messages and put a dot before them.

Finally I merged the branch into my main branch and pushed it on github.

My Comit

My commit can be found here

by Reza Poursafa at Fri Oct 15 2021 03:35:42 GMT+0000 (Coordinated Universal Time)


Joshua Li

Refactoring LENNAH SSG

This week we learned about refactoring and combining commits using Git. As I have mentioned in my first blog about LENNAH, I wanted to make my SSG in C++ because I wanted to practice my C++. Our projects were meant to be pretty rough around the edges and messy to begin with so we would have a lot to improve on. So I figured using C++ would be perfect for that. And indeed it has given me a lot of code to refactor.

When I originally started off with this project I didn't have many separate files, everything was done under a single cpp file. So I had a lot of code I would need to split, because it was becoming extremely crowded in my single cpp file. It also had a lot of features added from my classmate Andrew, who added to my repo with config file support last week. If you want to see what he did here's a link to his blog post.

First thing I need to do was update and add some of my function descriptions in the code comments. There were a few descriptions missing from some of the features both Gus and Andrew previously added that I touched upon. I also had to update the naming for my readTxt() function because it now also can read .md files so I changed it to readFile(). Then I extracted a function to delete and create an output folder because I noticed that this was done twice in the code. Additionally, I had to update some console outputs for the config file support feature Andrew added.

Once the code clean up and adding of comments was done, it was time for me to split my code and create header files for my classes and functions. This was the hardest step for my refactoring because I had to completely restructure my code. However, once it was done my code became a lot easier to read and also by doing this I was able to simplify some code that was actually repeated by removing the repeated instance completely.

After I tested everything I was able to do an interactive rebase in Git to merge all my commits together. This was a really neat feature that allowed me to keep my actions/changes organized and it was super easy to do! If you want to take a look at my rebased commit you can find it here. While it looks like a lot was changed it was a lot more manageable because in reality it was a bunch of separate changes. This feature is great to make the commit history look a lot cleaner because I know I am someone who always tends to miss a few things here and there so the tiny commits tend to pile up. Now I don't have to feel as bad when I notice a small thing that needs changing, I can just rebase the commits!

Well anyways thanks for reading, and as always, take care!

by Joshua Li at Fri Oct 15 2021 03:08:01 GMT+0000 (Coordinated Universal Time)


Xiongye Jiang

Refactoring with Git

This is the 6th Week that I've been being in OSD 600. And this week we have a new work to do -- Lab 5. Different from the previous labs we had, this week we are going to modify our code of SSG program and make it looks better. It's about refactoring our code.

Due to we added new features to our program, the complexity of the code grows with it. We added new features and we forced to create new code paths, functions, variables. which will cause we are start losing control of the code.
Refactoring is a technique for improving the structure and maintainability of our code without altering its behavior.

Procedure

#1. Get the repository to my PC

After reading the instruction of the Lab 5. I cloned my repository to my local machine and then used the command git checkout -b refactor in git to created a new branch named 'refactor'.
And then I use the command code . to run the code in Visual Studio Code.

#2. Go through the code

When my SSG code available in my local machine. I read through my code again. And I found out that there are a bunch of code are similar.
Therefore, I decided to make some new functions to reduce the amount of duplication.

#3. Create Functions

Firstly, I created a function called "mdFileHtmlConversion" to store the code that adding a new feature to my SSG so that all --- in a Markdown file would get converted to an


tag.
Secondly, I found that the way I try to convert a txt file to a html file is very similar the way I covert a md file to a html file.
Therefore, I put then into a new function named "htmlGenerator".
Lastly, I have duplicated logic and code for my program to convert a folder and a single file. In order to make my program with less duplication. I created a new function named "htmlConversion" to store the converting logic and code.

#4. Improve variable naming

Since I updated my code with some new functions, it became more tidy. And my next step was to rename those variables that with a non-sense name. For example, I have a variable named 'fname'. I mean, there are many possibilities for a variable named 'fname', it could be 'first name' or 'file name' or 'french name', etc. So, I changed it to a more specific name 'fileName'. It's way more clear than with the name 'fname'.Also, I changed the variable 'stats' to 'filePath' so that it became easier to understand.

#5. Get rid of global variables

Finally, I removed all the global variables I had in my code. Instead of having global variables, I put those variables to each specific function that I will use them.

#6. Combine my commits

After updating my code, I use this command git rebase master -i to start an interactive rebase, and opening the editor. And then I overwrite the 'pick' keyword to 'squash' so that I can combine all the commits I had into 1 commit. Then I use the command git commit --amend to rename some of my commit descriptions. Last but not least, I merged my 'refactor' branch to my 'master' branch.

My Feelings

I gotta say "Refactoring is interesting!" This is a good way to improve my coding structure. It saved me 53 lines of code after refactoring,which is almost 1/5 line of code in my SSG program.
Also, my code became easier to work with, easier to understand, and easier to extend! I think I will make more refactor move in the future!

Link to my repo: [Refactoring]

by Xiongye Jiang at Fri Oct 15 2021 03:07:55 GMT+0000 (Coordinated Universal Time)


Kunwarvir Dhillon

Refactoring existing code and rebasing

Background

I was looking at my static site generation tool, cli-ssg and being an open source repository, it had received a couple of commits from contributors. Now while the tool definitely worked as expected, I thought that this was a good moment to refactor the codebase to improve the structure and maintainability of the project.

Refactoring cli-ssg

I started off by creating a refactoring branch from main. I then spent some time looking in the project to find areas where I could improve the code quality.

When I had initiated this project, I decided to go with a module based approach even though at that time it only really supported .txt input. This drastically reduced the refactoring effort as a major portion of the code involving .html generation was already in a separate module called generateHtml.js.

That being said, index.js was looking a bit messy after the pull request for the --config option was merged into main (#18).

The way the options for the input path, output directory, language and stylesheet were being parsed and validated could definitely use some improvement and I decided to refactor the following code:

  .check((argv) => {

    //Input
    if(argv.i){

      if(!fs.existsSync(argv.i)){
        throw new Error("Input path must be a file or directory");
      }
    }

    //Output
    else if(argv.o != outputDir){
      if(fs.existsSync(argv.o)){
        if(!fs.lstatSync(argv.o).isDirectory()){
          throw new Error("Output path points to a file. Output directory must be valid")
        }
      }
      else throw new Error("Output directory must be valid");
    }

    //Config
    else if(argv.c){

      if(isJSON(process.argv[3])){

        if(!fs.existsSync(argv.c)){
          throw new Error("JSON file path does not exist");
        }
        var data = JSON.parse(fs.readFileSync(argv.c));

        if(data.input)      argv.i = data.input
        if(data.output)     argv.o = data.output
        if(data.stylesheet) argv.s = data.stylesheet
        if(data.lang)       argv.l = data.lang

      }else{
        throw new Error("The passed file should be of JSON format")
      }
    }
    else {
      throw new Error("A config file(.JSON) or an input file is required");
    }

    return true;
  })
  .argv;

Before I started refactoring, I noticed some problems with the code which were missed during code review:

  • No error handling when reading/parsing the JSON file
  • No validation for input, output options when they were parsed from JSON
  • An unhandled error would be thrown if an output directory path, which did not exist, was passed to the tool.

To fix these problems, I decided to refactor the option parsing and validation process into a new module. The class Options could then be used to store and process options for the tool such as:

input: Input file/folder to be processed
output: Output directory
lang: Language attribute for the html element
stylesheet: CSS stylesheet for the website

To store and process these, I wrote a class called Options and stored it in configOptions.js.

class Options{
  constructor(input, output, stylesheet, lang){
    this.input = input;
    this.output = output;
    this.stylesheet = stylesheet;
    this.lang = lang;
  }
  static get DEFAULT_OUTPUT(){ return './dist'; }
  static get DEFAULT_LANG(){ return 'en-CA'; }
}
module.exports.Options = Options;

Refactoring the config parsing functionality into this new module:

class Options{
   /**
   * Parses options using a file path
   * @param {string} filePath 
   * @return {Boolean} true if the options were parsed
   */
  parseConfig(filePath){
    if(fs.existsSync(filePath)){
      if(path.extname(filePath).toLocaleLowerCase() == '.json'){
        let fileContents = fs.readFileSync(filePath);
        let configData;

        try{
          configData = JSON.parse(fileContents);
        }
        catch(err){
          console.log('Error while parsing JSON: ', err);
          process.exit(-1);
        }

        this.input = configData.input;
        this.output = configData.output ? configData.output : Options.DEFAULT_OUTPUT;
        this.lang = configData.lang ? configData.lang : Options.DEFAULT_LANG;
        this.stylesheet = configData.s;

      }
      else {
        console.log("Config file must be JSON!", path.extname(filePath));
        process.exit(-1);
      }
    }
    else {
      console.log(`${filePath} not found! A JSON config file must be supplied`);
      process.exit(-1);
    }

    console.log(chalk.green(`Options successfully retrieved from ${filePath}`));
    return true;
  }
}

Adding methods to validate the options:

class Options{
  //Returns true if the input path is validated, otherwise throws an error
  validateInput(){
    if(!fs.existsSync(this.input)){
      throw new Error(`${this.input} does not exist. Input path must be a file or directory`);
    }
    return true;
  }

  //Returns true if the output path is validated, otherwise throws an error
  validateOutput(){
    if(this.output != Options.DEFAULT_OUTPUT){
      if(fs.existsSync((this.output))){
        if(!fs.lstatSync((this.output)).isDirectory()){
          throw new Error("Output path points to a file. Output directory must be valid")
        }
      }
      else throw new Error(`${this.output} does not exist. Output directory must be valid`);
    }
    return true;
  }
}

After I had written the Options module, it was now time to use it in index.js to parse and process the options supplied to the program. Starting off by importing the module:

const { Options } = require("./configOptions");

With the help of the Options module, I was able to simplify the messy index.js by reducing the options processing from 46 lines to just 12 lines:

.check((argv) => {
    options = new Options(argv.i, argv.o, argv.s, argv.l);

    if(argv.c){
      //Parse and use options from the config file
      options.parseConfig(argv.c);
    }

    //Validate the options
    return options.validateInput() && options.validateOutput();
  })
  .argv;

Since I was now using a variable called options to store the tool options, all I had to do was to change the arguments for .html generation:

generateHtml(options.input, options.output, options.stylesheet, options.lang);

And Voila! index.js was looking clean again and everything still worked just like before. The final change I made was to move generateHtml.js and configOptions.js to bin/modules

Organizing changes and rebasing

The refactoring work I mentioned above was done in the form of multiple separate commits. I had a total of 5 commits by the time I had finished:

Fixing the error handling bug introduced by the config feature

Refactor options validation and parsing into a new Options class

Move the HTML generation and tool options module to bin

Refactor paths for options and generate html modules

Improve linting and indentation

Before I merged these changes into main, I squashed them into a single commit using

git rebase main -i

I also ended up modifying its commit message to highlight the work done using git commit --amend.
At this point, I just performed a merge on the main branch to integrate the changes from my refactoring branch and pushed these changes to GitHub.

Final commit on main for refactoring work: b406d2f

by Kunwarvir Dhillon at Fri Oct 15 2021 02:28:51 GMT+0000 (Coordinated Universal Time)


Tuan Thanh

Rewriting history in Git

Introduction

Hello everyone, my name is Dustin. Today, I wanted to talk about the experience of refactoring my entire code written in Nodejs and rewriting history in Git.

Process

To be honest, I didn't think that it would be that difficult until I broke the whole thing. I literally had to rewrite everything from scratch. I mean not everything but everything. So first off, I had to create a readPath class which mainly will get the path from main to check if it is a folder or other files: .txt, .md, or .json so that I can use different method for different file types. After that, I need a produceFile class, which is going to help me in creating html file and a produceFolder class, which just helps me create a folder in the root directory where the user is sitting at.

Comparison

Before using classes
I will have around 6 files in my helpers folder here

After using classes
I just have 3 classes here

And the code is well organized and easy to read even if for beginners who are used to object-oriented programming.

Achievement

Thanks to the assignment, I got a chance to learn more about rebasing, amending as well as using classes in Javascript.

Commit in git

3fcb0c88

by Tuan Thanh at Fri Oct 15 2021 01:42:58 GMT+0000 (Coordinated Universal Time)


Minh Quan Nguyen

Refactoring & Rebasing

Overview

This week, my main focus is to clean up and refactor my static site generator. With so many people working on the project for the past few weeks, it isn't strange to see duplicated logic and unnecessary variables. And as the project grows, improving the quality of the code will not only make it more readable but also allow for better error handling and maintainability.

Refactoring

Here is my list of what to change in the existing codebase:

  • Moving all the source files into a /src directory
  • Changing the file name to use kebab-case and updating the imports in the entry file
  • Reversing the logic for checking file extensions
  • Splitting the tasks in generateHTMLFile() to smaller functions

1. Moving all the source files into a /src directory

Currently, my file structure looks like this:

root-dir
|- mini-ssg.js
|- utils
   |- generateHTML.js
   |- processInput.js
   |- processJSON.js 
|- package.json
|- README.md

With this file structure, it will become harder to navigate as the project gets larger. Therefore, one of the things you can do to make your coding experience easier is separate the sources files into a different directory and reserve the root directory for metadata (e.g., package.json, linting, config files, README.md, etc.)

The result should look something like this:

root-dir
|-src
  |- mini-ssg.js
  |- utils
     |- generateHTML.js
     |- processInput.js
     |- processJSON.js 
|- package.json
|- README.md

2. Changing the file name to use kebab-case and updating the imports in the entry file

Before, I was using camel-case for file names. However, I learned that not all file systems were case-sensitive. As such, fileName1 and filename1 might or might not be the same file. Changing the naming into kebab-case (e.g, file-name) resolves that issue.

3. Reversing the logic for checking file extensions

I was having a bit of trouble looking for what to refactor. As such, asking for help on Slack gave me a lot of insight into what can be improved. One of the recommendations I saw was to revert the logic to check for the file extensions.

To be specific, here is the old one:

if (path.extname(inputPath) === ".json") {
    // main logic
}

console.log("File extension must be '.json'.");
return process.exit(1);

While it is okay to keep the existing code, reversing the checking logic would help save me from indenting an if statement to run the main logic. As such, I modified the function into:

if (path.extname(inputPath) !== ".json") {
    console.log("File extension must be '.json'.");
    return process.exit(1);

}

// main logic

4. Splitting the tasks in generateHTMLFile() to smaller functions

When refactoring, it is usually best to break functions into smaller chunks. Not only does it allow the function to be easier to read and understand, but you also have more control over what each of them does, which makes finding errors simpler.

I realized that my generateHTMLFile() function is getting a bit too big, and is doing too many things at once:

async function generateHTMLFile(...parameters) {
  // a big group of code to generate the HTML body

  // logic to create file and write HTML content   
}

The logic to generate the HTML body can be extracted into its own function and generateHTMLFile() will use the function to get the result:

async function generateHTMLFile() {
  const htmlBody = generateHTMLBody()

  // logic to create file and write HTML content   
}

function generateHTMLBody() {
  // a big group of code to generate the HTML body
}

With this approach, in addition to reducing the number of tasks that generateHTMLFile() does, I also surprisingly avoid using the global variable storing the HTML body that I had before.

Rebasing

git rebase and git commit —amend came in handy during the refactoring because they allowed me to patch up and re-organize my commit. The option to combine many commits into a single commit and change the message of the most recent commit has cleaned up my git history, making the top-level message of each git commit more relevant.

Additional links

My project 💻: mini-ssg
Rebase commit 📝: f42e5b6

by Minh Quan Nguyen at Fri Oct 15 2021 01:31:33 GMT+0000 (Coordinated Universal Time)