<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Luke Nguyen</title>
    <description>The latest articles on DEV Community by Luke Nguyen (@mqnguyen).</description>
    <link>https://dev.to/mqnguyen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F700993%2Ff0734d4f-7bc1-4870-9a23-74610bfb9812.jpeg</url>
      <title>DEV Community: Luke Nguyen</title>
      <link>https://dev.to/mqnguyen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mqnguyen"/>
    <language>en</language>
    <item>
      <title>Release 0.4 - Part 3</title>
      <dc:creator>Luke Nguyen</dc:creator>
      <pubDate>Fri, 10 Dec 2021 20:54:56 +0000</pubDate>
      <link>https://dev.to/mqnguyen/release-04-part-3-29po</link>
      <guid>https://dev.to/mqnguyen/release-04-part-3-29po</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;With both pull requests submitted and one of them being merged recently, we are approaching the final chapters of this journey. This blog, the last one of the release 0.4 trilogy, will be about the process of participating in code reviews for the pull requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  The issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;a href="https://github.com/Seneca-CDOT/telescope/issues/2416"&gt;#issue-2416&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;While the &lt;a href="https://github.com/Seneca-CDOT/telescope/pull/2582"&gt;initial release&lt;/a&gt; looks good, some places need improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Addressing the problem where the build status get refreshed every 5 seconds&lt;/li&gt;
&lt;li&gt;Rebasing and moving the code for the build header to a new location to accommodate for the newly added Handlebars feature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the first problem, the culprit was the 2 &lt;code&gt;toggleAttribute&lt;/code&gt; calls inside &lt;code&gt;renderBuildInfo()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;resMsg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toggleAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;buildHeaderInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toggleAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As such, I had to find a workaround to replicate the behaviour, and using "innerHTML" seems to be the best option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;buildHeaderTitle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the second problem, I reached out to the classmate who added the templating engine and was able to get him to explain the changes he made. With all of the questions clarified, I referred to the Handlebars documentation and slowly migrated the code to its new location. Once done, I also performed a small test to ensure that the two functions that fetch and render the data were called. &lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;a href="https://github.com/Seneca-ICTOER/IPC144/issues/107"&gt;#issue-107&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;As for this &lt;a href="https://github.com/Seneca-ICTOER/IPC144/pull/144"&gt;pull request&lt;/a&gt;, the code review went much more smoothly, with me having to only make minor changes to ensure that it would not cause any errors when built.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And with that, I'm almost done with the release! By the time this blog is up, I still have a little bit more work to do, mostly refining and optimizing #issue-2416 to get it ready for PR. The journey until now was not easy, and I was a bit disappointed that I couldn't contribute as much as I wanted to. Compared to my performance in previous releases, I would give myself only a 6/10, as I felt like I could do more than just taking only two issues. But with that said, I'm still proud of what I have done. &lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Release 0.4 - Part 2</title>
      <dc:creator>Luke Nguyen</dc:creator>
      <pubDate>Fri, 10 Dec 2021 12:33:37 +0000</pubDate>
      <link>https://dev.to/mqnguyen/release-04-part-2-mp6</link>
      <guid>https://dev.to/mqnguyen/release-04-part-2-mp6</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Continuing with my release 0.4, I started putting my plan for the two selected issues into action. After talking with the project maintainers and noting down almost everything I needed to know, I was confident that I could get both pull requests up for review within the week. Sadly, things did not go as planned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working on the issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;a href="https://github.com/Seneca-CDOT/telescope/issues/2416"&gt;#issue-2416&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;At first, I intended to reuse the existing table layout and only made tiny modifications. However, I soon realized that this approach only made everything more difficult. By duplicating the code, not only did I make the already bulky HTML even harder to read, but it also made naming classes, IDs, and performing DOM manipulation to render the data more challenging. After several days of just writing and deleting the same code, I decided to go back to the drawing board.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Initial design&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fewAi0Wq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/59778930/144354666-505bd5d4-b2d1-4728-9da3-d7fe129c6d7e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fewAi0Wq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/59778930/144354666-505bd5d4-b2d1-4728-9da3-d7fe129c6d7e.png" alt="image" width="880" height="135"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make the final product matches the provided example, I had to choose between flexbox and grids. Both of them will get the job done, but to my experience, I find that grid is much simpler to use. After hours of sketching out the design in my notebook, it was time to write the actual code. I started working my way slowly through each section of the layout, adding minor adjustments and constantly going back and forth between the Bootstrap documentation to ensure the result looked good on the web.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;My ugly sketch of the new layout&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_5SasTnG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hxz4y8k1a7wst2u7u4nb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_5SasTnG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hxz4y8k1a7wst2u7u4nb.jpg" alt="image" width="880" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Final result&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZMmfiDQK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/59778930/145264347-b7c2770d-b8a2-4ec0-8487-a01fb38717e9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZMmfiDQK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/59778930/145264347-b7c2770d-b8a2-4ec0-8487-a01fb38717e9.png" alt="image" width="880" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another roadblock I had while working on this issue was figuring out how to fetch the data and render them to the UI. I initially thought I had to make an API call and process the data, but one of the maintainers mentioned that doing so was unnecessary. Thus, I had to play around with the return values inside the function responsible for fetching the data. After hours of logging different variables, objects, messages, and a couple of calls with one of the maintainers, I managed to get everything worked and combine it with the design I made earlier.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;a href="https://github.com/Seneca-ICTOER/IPC144/issues/107"&gt;#issue-107&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Surprisingly, I hadn't had as much trouble working on this as the previous one. As a lot of the work was similar to one of my labs about continuous integration, I was able to use it as a reference and quickly get my pull request up for review. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;It has been a rough week, but I managed to get both the issues up and ready for review. By the time this blog is up, #issue-107 has been merged successfully, while #issue-2416 was on its final stage of reviewing. I'll be waiting for feedback and making any modifications where necessary.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Release 0.4 - Part 1</title>
      <dc:creator>Luke Nguyen</dc:creator>
      <pubDate>Tue, 30 Nov 2021 03:09:28 +0000</pubDate>
      <link>https://dev.to/mqnguyen/release-04-part-1-43d5</link>
      <guid>https://dev.to/mqnguyen/release-04-part-1-43d5</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Finally, we managed to reach the end of my first open-source course. And, what better way to end it than challenging myself to work on something even bigger and more impactful compared to my previous releases?&lt;/p&gt;

&lt;p&gt;This blog will be the first of my 3-part journey tackling the final release: from planning the approach to the assigned issues and working on the code to finally submitting the PR(s) and making adjustments based on others' feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  The search 🔎
&lt;/h2&gt;

&lt;p&gt;First things first, we need to get ourselves some issues.&lt;/p&gt;

&lt;p&gt;I decided to look inside Telescope and the IPC144 curriculum repo and after a while, managed to find myself 2 issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Seneca-CDOT/telescope/issues/2416"&gt;https://github.com/Seneca-CDOT/telescope/issues/2416&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Seneca-ICTOER/IPC144/issues/107"&gt;https://github.com/Seneca-ICTOER/IPC144/issues/107&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Planning 📝
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;a href="https://github.com/Seneca-CDOT/telescope/issues/2416"&gt;#issue-2416&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;After talking with the project maintainers, I managed to write down a few things about my approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetching the builds' (previous, current, next) detail from the Telescope API&lt;/li&gt;
&lt;li&gt;Extracting the following info from the fetched result:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  * The git SHA that is/was built
  * Who pushed the code (i.e., pusher)
  * Who wrote the code (i.e., sender/author)
  * A link to the compare branch to see what changed
  * When the build started (startedDate)
  * When the build stopped (stoppedDate)
  * What the result code of the build was
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Rendering the data to a UI element to display it in both the dashboard and the build log&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the place that hosts the logic to fetch and extract data from the API, I was suggested to create a new file in &lt;a href="https://github.com/Seneca-CDOT/telescope/tree/master/src/api/status/public/js/build-log"&gt;https://github.com/Seneca-CDOT/telescope/tree/master/src/api/status/public/js/build-log&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the UI element, I planned on basing my design on GitHub's per one of the maintainers suggestion:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sE70Fpr1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rijn6q8q23kvd9h8zv6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sE70Fpr1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rijn6q8q23kvd9h8zv6g.png" alt="GitHub build detail" width="880" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the project uses &lt;a href="https://getbootstrap.com/"&gt;Bootstrap&lt;/a&gt;, I could refer to their documentation to create a card component and customize it to match the example as closely as I can.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;a href="https://github.com/Seneca-ICTOER/IPC144/issues/107"&gt;#issue-107&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Since the task is to add more scripts to improve the current CI workflow, I could refer to a &lt;a href="https://dev.to/mqnguyen/adding-continuous-integration-with-github-actions-33hm"&gt;blog&lt;/a&gt; I made about GitHub Actions and start from there.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Publishing a project to npm</title>
      <dc:creator>Luke Nguyen</dc:creator>
      <pubDate>Sat, 27 Nov 2021 07:45:07 +0000</pubDate>
      <link>https://dev.to/mqnguyen/publishing-a-project-to-npm-2b9k</link>
      <guid>https://dev.to/mqnguyen/publishing-a-project-to-npm-2b9k</guid>
      <description>&lt;h2&gt;
  
  
  Introduction 📖
&lt;/h2&gt;

&lt;p&gt;For the past three months, I have been working on my static site generator, adding features and fixing bugs as the project grows. With the recent implementation of &lt;a href="https://dev.to/mqnguyen/static-analysis-tooling-n55"&gt;static analysis tooling&lt;/a&gt;, &lt;a href="https://dev.to/mqnguyen/automated-testing-with-jest-4745"&gt;test suites&lt;/a&gt;, and &lt;a href="https://dev.to/mqnguyen/adding-continuous-integration-with-github-actions-33hm"&gt;continuous integration&lt;/a&gt;, I thought the project was finally ready for public use. &lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing for release 🛠
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Making the project callable by its name
&lt;/h3&gt;

&lt;p&gt;To call the project directly, we have to map the entry file to its executable name, which we can do by adding the &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;bin&lt;/code&gt; value to &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mini-cli-ssg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/index.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside &lt;code&gt;index.js&lt;/code&gt;, we specifiy the environment of the executable by adding the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cp"&gt;#!/usr/bin/env node
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we can register the binary (the &lt;code&gt;bin&lt;/code&gt; value) globally by using &lt;code&gt;npm link&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Testing the project locally
&lt;/h3&gt;

&lt;p&gt;With &lt;code&gt;npm link&lt;/code&gt;, we can now test our project locally on our machine before actually publishing it. Start by creating a temporary directory for testing anywhere on your machine (I recommend putting it on Desktop as it is easier to see). Then, inside the newly created directory, install the project using the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;link &lt;/span&gt;mini-cli-ssg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we can play around with the CLI by calling it by its name, passing in different arguments to ensure that all features are working.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Adding information to &lt;code&gt;package.json&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;With the code tested and ready for publishing, it is time to prepare the &lt;code&gt;package.json&lt;/code&gt;. So far, we already have the basic information covered, like the project name, description, author, etc. However, it is nice to include in more detail such as the project homepage or GitHub repository. We can do so by adding the following values to &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"homepage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;your GitHub repo/site here&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"repository"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git+&amp;lt;your GitHub repo here&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, we also need to ensure that the version number follows the semantic versioning rules. You can check out the full description of it &lt;a href="https://semver.org/"&gt;here&lt;/a&gt;, or read the shortened version in the &lt;a href="https://docs.npmjs.com/about-semantic-versioning"&gt;npm docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Releasing to &lt;code&gt;npm&lt;/code&gt; 💾
&lt;/h2&gt;

&lt;p&gt;Here are the steps needed to publish the package:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an account on &lt;a href="https://www.npmjs.com/"&gt;npmjs.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Run the &lt;code&gt;npm login&lt;/code&gt; command and input your information&lt;/li&gt;
&lt;li&gt;Run the &lt;code&gt;npm publish&lt;/code&gt; command which will automatically publish it&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Receiving users' feedback
&lt;/h2&gt;

&lt;p&gt;With the package published, I reached out to some of my friends via Discord, asking them to test my code using the installation and usage instructions included in the docs. To my surprise, there were actually some issues that managed to slip through while I was testing it locally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mqnguyen5/mini-ssg/issues/23"&gt;#issue-23&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mqnguyen5/mini-ssg/issues/24"&gt;#issue-24&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After calling my friend and watching him run my package, I realized that I did not handle the file path properly. My classmate Duke also had a &lt;a href="https://dev.to/dukemanh/publish-a-cli-project-to-npm-10mc"&gt;blog post&lt;/a&gt; about a problem similar to this, so I will leave the explanation to him. But in short, I had to change the path names leading to each of the &lt;code&gt;dist&lt;/code&gt; and &lt;code&gt;assets&lt;/code&gt; into absolute paths using &lt;code&gt;path.resolve()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I can't believe I finally published my first ever package to npm. The experience was terrifying at first, but having someone to view and test your code gives you so many opportunities to learn from it. Additionally, it was satisfying seeing others were able to run your project successfully on their machines. &lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Adding Continuous Integration with GitHub Actions 🛠</title>
      <dc:creator>Luke Nguyen</dc:creator>
      <pubDate>Sat, 20 Nov 2021 07:23:33 +0000</pubDate>
      <link>https://dev.to/mqnguyen/adding-continuous-integration-with-github-actions-33hm</link>
      <guid>https://dev.to/mqnguyen/adding-continuous-integration-with-github-actions-33hm</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;With &lt;a href="https://dev.to/mqnguyen/static-analysis-tooling-n55"&gt;static analysis tooling&lt;/a&gt; and &lt;a href="https://dev.to/mqnguyen/automated-testing-with-jest-4745"&gt;unit tests&lt;/a&gt; added to the project, it is time to increase the complexity of my project. At the moment, I have written several tests to check on the different functionalities of my program. However, they had to be manually run by executing "npm run test" in the terminal, which will be very tedious if there are a lot of files to test. Additionally, we also need to consider human errors, as there is no way to guarantee that all contributors remember to run the test before committing their code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing a CI
&lt;/h2&gt;

&lt;p&gt;With this in mind, it is to introduce continuous integration (or CI, for short). It allows us to set up a workflow that listens to every time someone introduces new changes, builds the code, and automatically runs tests against it.&lt;/p&gt;

&lt;p&gt;While we have many CI services, such as Azure DevOps, Evergreen, or Jenkins, I'll choose GitHub Actions for this task. &lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the CI
&lt;/h2&gt;

&lt;p&gt;There are different options to set up GitHub Actions. You can either choose to do it manually or choose from numerous templates. My project, &lt;a href="https://github.com/mqnguyen5/mini-ssg"&gt;MINI&lt;/a&gt;, works just fine with the Node.js template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Title of the workflow&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Node.js CI&lt;/span&gt;

&lt;span class="c1"&gt;# Trigger this workflow on push and new PR&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# jobs to run inside this workflows&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# choose a platform to run on&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="c1"&gt;# options&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;14.x&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;16.x&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# use a preset step to checkout the code &lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="c1"&gt;# use a preset step to setup Node environment&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use Node.js ${{ matrix.node-version }}&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v2&lt;/span&gt;
        &lt;span class="c1"&gt;# preset options&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.node-version }}&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;npm'&lt;/span&gt;
      &lt;span class="c1"&gt;# command to run&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm test&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After setting up GitHub Actions, I made two pull requests to check if it worked as intended: &lt;a href="https://github.com/mqnguyen5/mini-ssg/actions/runs/1474720001"&gt;One&lt;/a&gt; containing an intentional error and the &lt;a href="https://github.com/mqnguyen5/mini-ssg/actions/runs/1474725084"&gt;other&lt;/a&gt; with the same error fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing test for others
&lt;/h2&gt;

&lt;p&gt;After ensuring that the CI was working, I decided to file an issue to Tue's &lt;a href="https://github.com/TueNguyen2911/tue-1st-ssg"&gt;repo&lt;/a&gt; and asked if I could help him test his text to HTML conversion. We worked with each other through Slack and GitHub, with myself taking notes of what he wanted to check and what the expected results should be. After struggling with managing and rebase commits when changing the code based on Tue's review, I was able to merge my &lt;a href="https://github.com/TueNguyen2911/tue-1st-ssg/pull/30#event-5647003435"&gt;pull request&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I intend to use continuous integration in additional projects in the future, and it was helpful to understand how it works and how to set it up. It makes collaboration considerably easier because it prevents unintended problems and code-breaking changes.&lt;/p&gt;

&lt;p&gt;Happy coding! 💻&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
    </item>
    <item>
      <title>Performing code reviews </title>
      <dc:creator>Luke Nguyen</dc:creator>
      <pubDate>Fri, 19 Nov 2021 03:54:21 +0000</pubDate>
      <link>https://dev.to/mqnguyen/performing-code-reviews-h5b</link>
      <guid>https://dev.to/mqnguyen/performing-code-reviews-h5b</guid>
      <description>&lt;p&gt;Contributing to open-source doesn't stop at adding features and fixing bugs. Sometimes, you can do more than you might think just by performing code reviews.  In this week of my open-source journey, I'll share some of my experiences when performing code reviews.&lt;/p&gt;

&lt;p&gt;The project where I'll be doing this was my school IPC144 curriculum renewal. With many students working on the repository, it is essential to review and test incoming PRs regularly. Surprisingly, I didn't have any trouble looking for issues this time.&lt;/p&gt;

&lt;p&gt;Here are the issues that I decided to perform the code reviewing on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Seneca-ICTOER/IPC144/pull/81"&gt;Audit &amp;amp; fix &lt;code&gt;Information.md&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Seneca-ICTOER/IPC144/pull/73#event-5639653957"&gt;Audit &amp;amp; fix &lt;code&gt;Compilers.md&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the first issue, I wanted to check if the person escaped the special characters with "\," as some of them didn't get converted properly when formatting with Prettier. An example of this was on line 115-128, when the asterisks were replaced with underscores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Original
* Giga or G (=1024M): 1 Gigabyte = 1024 * 1024 * 1024 bytes ~ 10&amp;lt;sup&amp;gt;9&amp;lt;/sup&amp;gt; bytes

// Expected
* Giga or G (=1024M): 1 Gigabyte = 1024 \* 1024 \* 1024 bytes ~ 10&amp;lt;sup&amp;gt;9&amp;lt;/sup&amp;gt; bytes

// Actual
* Giga or G (=1024M): 1 Gigabyte = 1024 _ 1024 _ 1024 bytes ~ 10&amp;lt;sup&amp;gt;9&amp;lt;/sup&amp;gt; bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the second issue, I mainly focused on addressing what the contributor was missing in the list of requirements, specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using backticks and all code for memory addresses and such in tables that use things like void, int, function names, memory addresses.&lt;/li&gt;
&lt;li&gt;Removing unnecessary changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code review is an excellent thing to do. By assisting others by leaving reviews and comments on the PR, not only will you improve the code quality of the PR, but you will also be able to learn some new stuff too.&lt;/p&gt;

&lt;p&gt;To find out more about the problem in the first issue, you can check &lt;a href="https://github.com/Seneca-ICTOER/IPC144/issues/56"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy coding! 💻&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Contributing to Telescope 🔭</title>
      <dc:creator>Luke Nguyen</dc:creator>
      <pubDate>Thu, 18 Nov 2021 21:39:24 +0000</pubDate>
      <link>https://dev.to/mqnguyen/contributing-to-telescope-k1</link>
      <guid>https://dev.to/mqnguyen/contributing-to-telescope-k1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;While waiting for reviews in my recent &lt;a href="https://dev.to/mqnguyen/contribution-to-course-curriculum-2eb9"&gt;pull request&lt;/a&gt;, I decided to find a different project. After hours of searching for issues on GitHub, I suddenly remembered the first repository where I made my first pull request, Telescope. Since then, the project has undergone many changes with different features and bug fixes, so I think it is time to make another contribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  The issue
&lt;/h2&gt;

&lt;p&gt;A quick overview about &lt;a href="https://github.com/Seneca-CDOT/telescope"&gt;Telescope&lt;/a&gt;: it is a web server and application developed by professors and students at Seneca College to track students/faculties' blogs about anything open-source. &lt;/p&gt;

&lt;p&gt;For my &lt;a href="https://github.com/Seneca-CDOT/telescope/issues/2461"&gt;task&lt;/a&gt;, I had to customize Telescope's build log page to match the design and layout of the main dashboard, specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add header and side navigation bar&lt;/li&gt;
&lt;li&gt;Change side navigation default logo into Telescope logo&lt;/li&gt;
&lt;li&gt;Update link in side navigation logo to redirect to &lt;code&gt;./&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Working on the issue
&lt;/h2&gt;

&lt;p&gt;After setting up the development environment using Telescope's documentation, I began looking at the UI to figure out what I should do. Lucky for me, there was also a different &lt;a href="https://github.com/Seneca-CDOT/telescope/issues/2433"&gt;issue&lt;/a&gt; that addressed the dashboard page UI, so I decided to use that as a reference.&lt;/p&gt;

&lt;p&gt;I began by adding each UI component one by one, re-rendering the page every time I added in new code to make sure I didn't break anything. Once I was satisfied with my changes, I opened up a &lt;a href="https://github.com/Seneca-CDOT/telescope/pull/2480"&gt;pull request&lt;/a&gt; on Telescope, explaining what I did and providing screenshots of the result. &lt;/p&gt;

&lt;p&gt;Since I was referencing another issue, I had to keep track of the updated changes in the other PR and update mine accordingly. The other PR also had many requested changes, so I tried my best to read through all the reviews, adding comments when I needed help and clarification to ensure that I wouldn't break or miss anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Similar to the other PR, when this post is online, the PR is currently under review. I will constantly keep an eye on new notifications regarding this PR and add more commits if needed.&lt;/p&gt;

&lt;p&gt;Cheers! 🍻&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Contribution to course curriculum</title>
      <dc:creator>Luke Nguyen</dc:creator>
      <pubDate>Thu, 18 Nov 2021 18:07:28 +0000</pubDate>
      <link>https://dev.to/mqnguyen/contribution-to-course-curriculum-2eb9</link>
      <guid>https://dev.to/mqnguyen/contribution-to-course-curriculum-2eb9</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Finally, I made it through Hacktoberfest! And, I also got myself a fancy new T-shirt! Celebration aside, I still have a lot of work to do. Working in open-source means you always have to be ready to look for new issues, find ways to contribute to the community of developers, and always set yourself up for new challenges. And this week, I had a chance to contribute to my school's course curriculum.&lt;/p&gt;

&lt;h2&gt;
  
  
  The project
&lt;/h2&gt;

&lt;p&gt;The IPC144 course curriculum renewal is a project that aims to update the original course note to a brand new one using Docusaurus. As mentioned before in &lt;a href="https://dev.to/mqnguyen/prototype-markdown-and-static-assets-support-for-ssg-547e"&gt;one&lt;/a&gt; of my blogs, Docusaurus is a static-site generator for building, deploying, and maintaining documentation websites. Most of the notes have already been changed to use Docusaurus, but the project needs contributions to review each converted section, add new features, or fix existing bugs. &lt;/p&gt;

&lt;h2&gt;
  
  
  The issue
&lt;/h2&gt;

&lt;p&gt;After looking at all the available issues, I decided to go with &lt;a href="https://github.com/Seneca-ICTOER/IPC144/issues/24"&gt;adding static analysis tooling&lt;/a&gt;, specifically, installing and configuring Prettier as the source code formatter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working on the issue
&lt;/h2&gt;

&lt;p&gt;Working on the issue was not too difficult, and I already have a different &lt;a href="https://dev.to/mqnguyen/static-analysis-tooling-n55"&gt;blog&lt;/a&gt; where I walk through how I setup Prettier, but here is an overview of what I did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installed Prettier using &lt;a href="https://www.npmjs.com/package/prettier"&gt;npm&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Added a &lt;code&gt;.prettierrc&lt;/code&gt; file to configure all the options and a &lt;code&gt;.prettierignore&lt;/code&gt; file to skip the ones that don't need formatting.&lt;/li&gt;
&lt;li&gt;Added the necessary scripts to run Prettier in &lt;code&gt;package.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Submitting the PR
&lt;/h2&gt;

&lt;p&gt;Once I was satisfied with my work, I created a &lt;a href="https://github.com/Seneca-ICTOER/IPC144/pull/50"&gt;pull request&lt;/a&gt; and explained what I had done. Getting in touch with the project's maintainers was quick, as I could reach them through Slack. However, during the reviewing process, my professor (one of the maintainers) noticed an issue when Prettier formatted the Markdown files. Per my professor's request, I decided to alert other students working on auditing and fixing the documentation about this problem by filing a new issue. I made sure to write down a detailed explanation of how and why it happened while providing Prettier configurations so that other contributors could test their changes or replicate the issue if needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;At the moment, the pull request was waiting to be merged. I will constantly keep track of any notifications and add changes if needed.&lt;/p&gt;

&lt;p&gt;Happy coding! 💻&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>Automated testing with Jest 🤖</title>
      <dc:creator>Luke Nguyen</dc:creator>
      <pubDate>Sat, 13 Nov 2021 02:09:12 +0000</pubDate>
      <link>https://dev.to/mqnguyen/automated-testing-with-jest-4745</link>
      <guid>https://dev.to/mqnguyen/automated-testing-with-jest-4745</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Managing code complexity can be difficult. I mean, you already added comments inside your codebase, wrote detailed documentation, and even set up static analysis tooling to keep your consistently formatted. But even so, somehow, your code still breaks. Human mistake? Bugs? It is hard to know. You can try adding safety nets to handle the errors, but can you even catch all of them? &lt;/p&gt;

&lt;p&gt;Luckily, we have tests. Testing allows developers to prevent their existing code from breaking, identifies bugs, and tracks easy to miss edge cases. The added extra layer of protection ensures that your project, small or large, will evolve in the right direction when new changes are introduced.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Jest?
&lt;/h2&gt;

&lt;p&gt;Since I wrote my project in JavaScript, I can choose between Mocha and Jest. In the end, I decided to go with the later option, as I have a bit of experience with it before. &lt;/p&gt;

&lt;p&gt;A quick overview: &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt; is a JavaScript testing framework that focuses on simplicity. It allows you to write tests and test suites in files ending with &lt;code&gt;.spec.js&lt;/code&gt; or &lt;code&gt;.test.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To begin, start by installing Jest using &lt;a href="https://www.npmjs.com/package/jest"&gt;npm&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; jest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, create a file with the ending as mentioned above to begin testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing tests
&lt;/h2&gt;

&lt;p&gt;Because my project is a static site generator, I'll be testing the parsing logic that converts text to HTML.&lt;/p&gt;

&lt;p&gt;First, I started by exporting and importing the necessary functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;generate-html.js&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;generateHtmlBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;generate-html.test.js&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;generateHtmlBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./generate-html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With everything up and ready to go, I began thinking of how I should test the logic. Here are some example scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Checking if the paragraphs are wrapped in &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; tags. A paragraph is identified by having one or several consecutive lines of text, followed by a single blank line as a paragraph limit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Checking if the title is wrapped in &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; tags. A title is defined by being the first line followed by 2 blank lines.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thus, my test should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;generateHtmlBody tests&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;returned html paragraph should be wrapped in &amp;lt;p&amp;gt; tag&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;extName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.txt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;generateHtmlBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;extName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.+&lt;/span&gt;&lt;span class="se"&gt;?)&lt;/span&gt;&lt;span class="sr"&gt;&amp;lt;&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;p&amp;gt;/g&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;returned html title should be wrapped in &amp;lt;h1&amp;gt; tag&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;extName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.txt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;generateHtmlBody&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;extName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;.+&lt;/span&gt;&lt;span class="se"&gt;?)&lt;/span&gt;&lt;span class="sr"&gt;&amp;lt;&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;h1&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running the test
&lt;/h2&gt;

&lt;p&gt;Great! We now have a file that tests for specific functionality, but how do we run it?&lt;/p&gt;

&lt;p&gt;With Jest, setting up test scripts was not too difficult. Inside "package.json," add the following scripts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;scripts:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest --"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test:watch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest --watch --"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"coverage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jest --collectCoverage --"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;npm test [file]&lt;/code&gt; will run the test on the specified file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run test:watch [file]&lt;/code&gt; will also run the test but in &lt;strong&gt;watch&lt;/strong&gt; mode, which automatically re-runs when changes are made.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm run coverage [file]&lt;/code&gt; will generate a code coverage report.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The experience of writing tests has forced me to challenge my way of thinking. Specifically, I had to abandon the thought of writing good tests every time and accepting that there would always be room for improvement. After all, there is no "done" in programming, only "version 1, 2, 3, and many more."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Free yourself from the need to be perfect.  Embrace “better than it was” and continue living in that&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>opensource</category>
      <category>testing</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Static Analysis tooling 🛠</title>
      <dc:creator>Luke Nguyen</dc:creator>
      <pubDate>Sat, 06 Nov 2021 00:58:04 +0000</pubDate>
      <link>https://dev.to/mqnguyen/static-analysis-tooling-n55</link>
      <guid>https://dev.to/mqnguyen/static-analysis-tooling-n55</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;It's easy to forget that people have different ways to write their code, from indentation, writing conditional statements, to choosing what type of quotes to use for strings. While this is trivial when working on personal projects, it is another story for projects with different people simultaneously working on a single code base. Unable to agree on a coding style often leads to problems reviewing pull requests, with developers/project maintainers spending countless hours searching for formatting issues instead of focusing on the logic.&lt;/p&gt;

&lt;p&gt;With this in mind, open-source projects need to include static analysis tooling, as they help improve code maintainability by spotting suspicious coding constructs or alerting us to common errors. &lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing the right tool 🔍
&lt;/h2&gt;

&lt;p&gt;For my static site generator, which is written in JavaScript, I have selected &lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt; and &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt; as the formatting and styling guide tools. I chose them due to their popularity amongst other developers, with detailed documentation and high customizability. Also, I have been using Prettier for a while as a VS Code extension, so it would be nice to learn more about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Prettier 🎨
&lt;/h2&gt;

&lt;p&gt;To set up Prettier, start by installing the tool using &lt;a href="https://www.npmjs.com/package/prettier"&gt;npm&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; &lt;span class="nt"&gt;--save-exact&lt;/span&gt; prettier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, follow the instructions from the Prettier &lt;a href="https://prettier.io/docs/en/install.html"&gt;docs&lt;/a&gt; and create 2 files: &lt;code&gt;.prettierrc&lt;/code&gt; and &lt;code&gt;.prettierignore&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.prettierrc&lt;/code&gt; is where you will set all the configuration options for your Prettier formatting.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.prettierignore&lt;/code&gt; lets the Prettier CLI and editors know which files to &lt;strong&gt;not&lt;/strong&gt; format. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, add the necessary scripts to &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prettier&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prettier --write &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;./**/*.{md,jsx,json,html,css,js,yml}&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prettier-check&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prettier --check &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;./**/*.{md,jsx,json,html,css,js,yml}&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using ESLint 🧪
&lt;/h2&gt;

&lt;p&gt;To set up ESLint, start by installing the tool using &lt;a href="https://www.npmjs.com/package/eslint"&gt;npm&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;eslint &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After finishing the installation, follow by setting up a configuration file, which you can do with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx eslint &lt;span class="nt"&gt;--init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should ended up with something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;module.exports&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;env:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;commonjs:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;es&lt;/span&gt;&lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;node:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;extends:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'eslint:recommended'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'prettier'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;parserOptions:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;ecmaVersion:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;rules:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;semi:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'error'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'always'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;quotes:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'error'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'double'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The configuration file is where you can customize the validation rules based on the project. For more information about the rules, using plugins, or adding shared settings, refer to the ESLint configuration &lt;a href="https://eslint.org/docs/user-guide/configuring/"&gt;docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Finally, add the necessary scripts to &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eslint&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eslint --config .eslintrc.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eslint-fix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eslint --config .eslintrc.js --fix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lint&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;npm run eslint&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Editor Integration 💻
&lt;/h2&gt;

&lt;p&gt;Running static analysis tools at build time (i.e., using our scripts) is great since we can automate it. However, it would be nice to have a way to integrate them into our editor or IDE so that we can enjoy the benefits while writing code.&lt;/p&gt;

&lt;p&gt;My solution is to create a &lt;code&gt;.vscode/&lt;/code&gt; folder that contains &lt;code&gt;settings.json&lt;/code&gt;, which directly configures the VSCode editor settings, and &lt;code&gt;extensions.json&lt;/code&gt;, which stores ESLint and Prettier as the recommended extensions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding a pre-commit hook 🎣
&lt;/h2&gt;

&lt;p&gt;Lastly, how can we deal with forgetful developers? The answer: adding a Git pre-commit hook. The hook will run your source code formatter on any changes that are being committed, preventing formatting errors before the developer makes a pull request. &lt;/p&gt;

&lt;p&gt;For this task, I'll be using &lt;a href="https://typicode.github.io/husky/#/"&gt;husky&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/pretty-quick"&gt;pretty-quick&lt;/a&gt;. &lt;code&gt;husky&lt;/code&gt; is a package for defining and executing git hooks, while &lt;code&gt;pretty-quick&lt;/code&gt; is used to run Prettier formatting against your staged files.&lt;/p&gt;

&lt;p&gt;First, start by installing &lt;code&gt;husky&lt;/code&gt; and &lt;code&gt;pretty-quick&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx husky-init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; prettier pretty-quick
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will setup &lt;code&gt;husky&lt;/code&gt;, modify &lt;code&gt;package.json&lt;/code&gt; and create a sample &lt;code&gt;pre-commit&lt;/code&gt; hook that you can edit. &lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;package.json&lt;/code&gt;, modify the &lt;code&gt;pre-commit&lt;/code&gt; script to use &lt;code&gt;pretty-quick&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pre-commit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pretty-quick --staged&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, add the following code to &lt;code&gt;/.husky/pre-commit&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/_/husky.sh"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'🐶 Checking your commit...'&lt;/span&gt;
npm run pre-commit &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'❌ Build failed. Please fix the error(s) showed above.'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! Every time you make a commit, the pre-commit hook will make sure to format the code using the configurations from &lt;code&gt;.prettierrc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cheers! 🍻&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>git</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Happy Hacktoberfest! 🎃 - Part 4</title>
      <dc:creator>Luke Nguyen</dc:creator>
      <pubDate>Sun, 31 Oct 2021 05:08:00 +0000</pubDate>
      <link>https://dev.to/mqnguyen/happy-hacktoberfest-part-4-3543</link>
      <guid>https://dev.to/mqnguyen/happy-hacktoberfest-part-4-3543</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Well, this is it, the last chapter of my 2021 Hacktoberfest journey. As there wasn't much time left, I thought maybe I could get myself a project get it done quickly. Surprisingly, I was wrong.&lt;/p&gt;

&lt;p&gt;Looking for a repository to work on during the last week of Hacktoberfest was quite challenging. As such, I had to rely on my classmates' PRs for issues. Since many of them worked on JavaScript or React-based projects, it didn't take me too long to find one. In the end, I decided to give Greenstand's &lt;a href="https://github.com/Greenstand/treetracker-admin-client"&gt;Treetracker&lt;/a&gt; (an app for planting trees, surprisingly!) a shot.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first issue
&lt;/h2&gt;

&lt;p&gt;The first &lt;a href="https://github.com/Greenstand/treetracker-admin-client/issues/176"&gt;issue&lt;/a&gt; was to address a CSS behaviour that caused one of the pages not to scroll vertically. While cloning the project to my local machine, I discovered that I needed the admin credentials to log into Treetracker's website. After messaging one of the lead developers and asking for the credentials, I was added to a Slack server, which from there I could retrieve what I needed and begin my work.&lt;/p&gt;

&lt;p&gt;Fixing the issue was not too hard. The source behind the unwanted behaviour was the &lt;code&gt;overflow: hidden&lt;/code&gt; style in the &lt;code&gt;Captures&lt;/code&gt; view, which I had to change into &lt;code&gt;overflowY: scroll&lt;/code&gt; to make the page start scrolling again. After creating a &lt;a href="https://github.com/Greenstand/treetracker-admin-client/pull/182"&gt;PR&lt;/a&gt;, I got some feedback to make the navbar stick to the top even when scrolling. Googling for a solution, I realized that I had to move &lt;code&gt;overflowY&lt;/code&gt; from the &lt;code&gt;Captures&lt;/code&gt; view to the &lt;code&gt;CaptureTable&lt;/code&gt; component, as this was the place that contained the navbar. &lt;/p&gt;

&lt;h2&gt;
  
  
  Finding a new bug
&lt;/h2&gt;

&lt;p&gt;While working on the finishing touch for the CSS changes, I discovered another bug: the pagination kept loading the next page even when pressing the previous button. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sRs1K7Iu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cpz215c74kc2qqi8hkeo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sRs1K7Iu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cpz215c74kc2qqi8hkeo.png" alt="a website image" width="880" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The culprit lies on the &lt;code&gt;CaptureTable&lt;/code&gt; component, where the page state was not set correctly when &lt;code&gt;onPageChange&lt;/code&gt; happens. Realizing that it was an opportunity to test my knowledge of React, I decided to file an issue and asked if I could try and solve it myself. &lt;/p&gt;

&lt;p&gt;First, I began looking up Material UI's &lt;code&gt;TablePagination&lt;/code&gt; &lt;a href="https://mui.com/api/pagination/"&gt;API&lt;/a&gt; per the lead dev suggestion. Using the example from the example and some inspiration from StackOverflow, I began creating the solution. The plan was to use a local &lt;code&gt;page&lt;/code&gt; state, and when &lt;code&gt;onPageChange&lt;/code&gt; happened, updated the &lt;code&gt;page&lt;/code&gt; state to the value of the new page instead of &lt;code&gt;page + 1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPage&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;captureContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handlePageChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;loadCaptures&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this solution was decent, I was told by the lead dev that the local state was unnecessary. He suggested taking advantage of the &lt;code&gt;capturesContext&lt;/code&gt; context, which holds the logic to manage the page state. With his suggestion, I went back to the code and made some more adjustments, and in the end, managed to successfully merged my &lt;a href="https://github.com/Greenstand/treetracker-admin-client/pull/182"&gt;PR&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hacktoberfest was an exciting new experience. I was able to learn a lot working with different communities on different projects and challenged myself to work on something a bit more advanced from what I learned. I'm excited to see which open-source events will happen in the future, and can't wait to contribute to even more repositories than this one.&lt;/p&gt;

&lt;p&gt;Have a great Halloween everyone! 👻 &lt;/p&gt;

</description>
      <category>opensource</category>
      <category>hacktoberfest</category>
    </item>
    <item>
      <title>Prototype: Markdown and static assets support for SSG 🛠</title>
      <dc:creator>Luke Nguyen</dc:creator>
      <pubDate>Fri, 29 Oct 2021 20:20:49 +0000</pubDate>
      <link>https://dev.to/mqnguyen/prototype-markdown-and-static-assets-support-for-ssg-547e</link>
      <guid>https://dev.to/mqnguyen/prototype-markdown-and-static-assets-support-for-ssg-547e</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the past two weeks, I had the chance to play around with &lt;a href="https://docusaurus.io/"&gt;Docusaurus&lt;/a&gt;, a React-based static site generator built and maintained by Facebook. Inspired by the feature-rich and beginner-friendly nature of the project, I decided to steal some of their ideas and apply them to my own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docusaurus impression 🐱‍🐉
&lt;/h2&gt;

&lt;p&gt;Setting up Docusaurus was simple, and this is the command I used to create my Docusaurus website:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-docusaurus@latest my-site classic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I chose the &lt;code&gt;classic&lt;/code&gt; template as the starting point, since it already shipped with documentation, a blog, customs pages, and dark mode support using a CSS framework. &lt;/p&gt;

&lt;p&gt;To deploy the site to GitHub pages, I had to make some modifcation to the &lt;code&gt;docusaurus.config.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="nl"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://mqnguyen5.github.io&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Your website URL&lt;/span&gt;
  &lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/docusaurus-demo/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;docusarus-demo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Your project's repo&lt;/span&gt;
  &lt;span class="nx"&gt;organizationName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mqnguyen5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, I just need to run &lt;code&gt;GIT_USER=&amp;lt;GITHUB_USERNAME&amp;gt; yarn deploy&lt;/code&gt;, and there we go: A fully-fledged &lt;a href="https://mqnguyen5.github.io/docusaurus-demo/"&gt;documentation website&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Docusaurus also make it easy for developers to add extra customization to their website, thanks to the organized directory structure, route-based modules, and excellent documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding new features 💡
&lt;/h2&gt;

&lt;p&gt;Currently, the implementation for markdown support is entirely hand-coded and is only available for a limited number of markdown syntax. To add full markdown support with this approach is just reinventing the wheel, and the better solution is to use an &lt;code&gt;npm&lt;/code&gt; package to do the heavy lifting.&lt;/p&gt;

&lt;p&gt;With the features in mind, I began by creating &lt;a href="https://github.com/mqnguyen5/mini-ssg/issues/15"&gt;an issue&lt;/a&gt; on my repo, detailing what I needed to do, and providing suggestions or resources to help me accomplish it. Implementing the code was not too difficult, and I realized that I could add more features to improve my SSG. After being satisfied with how the markdown support works, I began editing the issue to include support for static assets. It is a nice feature to have in my project, as I think images and favicons are common in most web pages today. &lt;/p&gt;

&lt;p&gt;While working on the feature for static assets, I realized that I couldn't find a way to customize &lt;a href="https://github.com/markdown-it/markdown-it"&gt;markdown.it&lt;/a&gt; (the packages used for markdown support) to refer to the newly created &lt;code&gt;/assets&lt;/code&gt; folder. As such, I had to develop a workaround by using regex, and in the end, managed to make it work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While I managed to implement the features, I was still unsatisfied with the result. The static assets support could be buggy, and there is still room for improvement. Additionally, I planned on adding frontmatter support to make the web pages more optimized for search engines, but it was postponed as I needed to deal with the static assets issue. I managed to file some issues for those leftovers, which I will be working on soon when I have the time. For those who are interested, the issues are &lt;a href="https://github.com/mqnguyen5/mini-ssg/issues/16"&gt;#issue-16&lt;/a&gt; and &lt;a href="https://github.com/mqnguyen5/mini-ssg/issues/17"&gt;#issue-17&lt;/a&gt;, available in my GitHub &lt;a href="https://github.com/mqnguyen5/mini-ssg"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cheers! 🍻&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
  </channel>
</rss>
