<?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: Paul Kim</title>
    <description>The latest articles on DEV Community by Paul Kim (@paulkim26).</description>
    <link>https://dev.to/paulkim26</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%2F1155277%2F24ab6c80-9f08-466f-bd00-281084d6e929.jpeg</url>
      <title>DEV Community: Paul Kim</title>
      <link>https://dev.to/paulkim26</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/paulkim26"/>
    <language>en</language>
    <item>
      <title>Adding a Continuous Integration Workflow</title>
      <dc:creator>Paul Kim</dc:creator>
      <pubDate>Sat, 18 Nov 2023 04:37:03 +0000</pubDate>
      <link>https://dev.to/paulkim26/adding-a-continuous-integration-workflow-47bj</link>
      <guid>https://dev.to/paulkim26/adding-a-continuous-integration-workflow-47bj</guid>
      <description>&lt;p&gt;For this week in &lt;a href="https://github.com/Seneca-CDOT/topics-in-open-source-2023"&gt;Topics in Open Source Development&lt;/a&gt; we were tasked with adding continuous integration tests into an existing project. The project that I will be enhancing is &lt;a href="https://github.com/paulkim26/til-to-html"&gt;til-to-html&lt;/a&gt; - a markdown to static HTML site generator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bun CI Workflow
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/paulkim26/writing-tests-30a1"&gt;Last week&lt;/a&gt;, I added automated unit tests to my project. This time, I will add a CI workflow&lt;/p&gt;

&lt;p&gt;Up until now, whenever code was merged into the main branch, it was up to the maintainer (me) to manually run tests on incoming code. Now, a workflow will be triggered when anyone attempts to push to or create a pull request to be merged onto the main branch. As this is a &lt;a href="https://bun.sh/"&gt;Bun.sh&lt;/a&gt; application, I followed the &lt;a href="https://bun.sh/guides/runtime/cicd"&gt;official setup guide&lt;/a&gt; to run Bun in GitHub Actions.&lt;/p&gt;

&lt;p&gt;The workflow file I created does the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whenever someone:

&lt;ul&gt;
&lt;li&gt;pushes to the main branch, or&lt;/li&gt;
&lt;li&gt;creates a pull request for the main branch…&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;GitHub Actions will run a job that:

&lt;ul&gt;
&lt;li&gt;installs Bun using Bun's official &lt;a href="https://github.com/oven-sh/setup-bun"&gt;setup-bun&lt;/a&gt; routine&lt;/li&gt;
&lt;li&gt;uses the latest version of bun&lt;/li&gt;
&lt;li&gt;installs all package dependencies&lt;/li&gt;
&lt;li&gt;runs a build&lt;/li&gt;
&lt;li&gt;runs all unit tests&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of these steps fail, the push/pull request is rejected.&lt;/p&gt;

&lt;p&gt;Bun CI Workflow: &lt;a href="https://github.com/paulkim26/til-to-html/blob/main/.github/workflows/bun.yml"&gt;https://github.com/paulkim26/til-to-html/blob/main/.github/workflows/bun.yml&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding tests to a partner's project
&lt;/h2&gt;

&lt;p&gt;(coming soon)&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;This is the first time I incorporated an automatic CI testing workflow into a project. I enjoyed how straightforward and well documented the process was. Adding a CI workflow alleviates a lot of anxiety when it comes to integrating code not just from other developers, but from me as well. These are all checks and balances I would have had to worry and remember to execute myself - there's no reason &lt;strong&gt;not&lt;/strong&gt; to automate these trivial tasks.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Writing Tests</title>
      <dc:creator>Paul Kim</dc:creator>
      <pubDate>Mon, 13 Nov 2023 02:44:37 +0000</pubDate>
      <link>https://dev.to/paulkim26/writing-tests-30a1</link>
      <guid>https://dev.to/paulkim26/writing-tests-30a1</guid>
      <description>&lt;p&gt;For this week in &lt;a href="https://github.com/Seneca-CDOT/topics-in-open-source-2023"&gt;Topics in Open Source Development&lt;/a&gt;, we were tasked with adding tests to an existing project. Here is my experience doing so.&lt;/p&gt;

&lt;p&gt;Project Repository: &lt;a href="https://github.com/paulkim26/til-to-html"&gt;https://github.com/paulkim26/til-to-html&lt;/a&gt;&lt;br&gt;
Commit: &lt;a href="https://github.com/paulkim26/til-to-html/commit/2a00cf69b4fab11c65baedc9ca518fe3bf36e9d6"&gt;https://github.com/paulkim26/til-to-html/commit/2a00cf69b4fab11c65baedc9ca518fe3bf36e9d6&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Framework
&lt;/h2&gt;

&lt;p&gt;Since my project already uses Bun, I decided to use Bun's own &lt;a href="https://bun.sh/docs/cli/test"&gt;built-in test runner&lt;/a&gt;. It is based on &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt; which makes it easy to pick for developers familiar with that testing framework. As a result, there was no additional setup required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing Tests
&lt;/h2&gt;

&lt;p&gt;For this project, I added tests that test the markdown parsing modules I had previously written (&lt;a href="https://github.com/paulkim26/til-to-html/tree/main/src/parse-markdown"&gt;source&lt;/a&gt;). Since each markdown parsing module accepts multiple syntaxes e.g. markdown italics can be represented as either &lt;code&gt;_text_&lt;/code&gt; or &lt;code&gt;*text*&lt;/code&gt;, I made sure to test for each matching combination along with an aberrant test case (e.g. an empty string) (&lt;a href="https://github.com/paulkim26/til-to-html/blob/main/src/parse-markdown/parseItalics.test.ts"&gt;example&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;One nice thing I realized working with TypeScript is that I don't have to write additional tests that check for strange type combinations e.g. passing a &lt;code&gt;null&lt;/code&gt; to a function that accepts only strings, since TypeScript already blocks such cases. If I had written it in a weakly typed language i.e. JavaScript, I would have had to cover these cases as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;I have only had limited experience writing tests before; this was a good experience to write some more. I was surprised to learn how verbose and comprehensive the act of writing tests can be. It is in its verbosity, however that test writing is great since it is easily readable for a human. I see no reason for any project to not include its own suite of tests, especially open source ones. I will for sure continue to write tests in all of my projects going forward.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Adding Static Analysis Tooling</title>
      <dc:creator>Paul Kim</dc:creator>
      <pubDate>Sun, 05 Nov 2023 01:48:18 +0000</pubDate>
      <link>https://dev.to/paulkim26/adding-static-analysis-tooling-5mg</link>
      <guid>https://dev.to/paulkim26/adding-static-analysis-tooling-5mg</guid>
      <description>&lt;p&gt;For this week in &lt;a href="https://github.com/Seneca-CDOT/topics-in-open-source-2023"&gt;Topics in Open Source Development&lt;/a&gt;, I was tasked with adding Static Analysis Tooling to an existing project.&lt;/p&gt;

&lt;p&gt;Project: &lt;a href="https://github.com/paulkim26/til-to-html/commits/main"&gt;til-to-html&lt;/a&gt;&lt;br&gt;
Commit: &lt;a href="https://github.com/paulkim26/til-to-html/commit/c34a0b61c28847822f6a7467f68eeaf54e08ca03"&gt;https://github.com/paulkim26/til-to-html/commit/c34a0b61c28847822f6a7467f68eeaf54e08ca03&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Tools Used
&lt;/h2&gt;

&lt;p&gt;To automatically format and lint code in this project, I used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://prettier.io/"&gt;Prettier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I chose these as I am familiar with them and have enjoyed using them for previous projects. They are commonly used by many projects and integrate well with Visual Studio Code. Prettier is an opiniated automatic code formatter that formats all code in the same way. ESLint is a linting tool for JavaScript that is able to detect code smells and can automatically fix them too (if configured to do so).&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up Prettier
&lt;/h2&gt;

&lt;p&gt;Note: this project is using &lt;a href="https://bun.sh/"&gt;Bun&lt;/a&gt;.&lt;br&gt;
The following instructions are adapted from &lt;a href="https://prettier.io/docs/en/install.html"&gt;https://prettier.io/docs/en/install.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To setup Prettier, I ran the following to install Prettier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun &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
node &lt;span class="nt"&gt;--eval&lt;/span&gt; &lt;span class="s2"&gt;"fs.writeFileSync('.prettierrc','{}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;')"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I added a &lt;code&gt;.prettierignore&lt;/code&gt; file, using the same contents of my existing &lt;code&gt;.gitignore&lt;/code&gt; file. To format the project, I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun prettier &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--write&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command is then added to the &lt;a href="https://github.com/paulkim26/til-to-html/blob/c34a0b61c28847822f6a7467f68eeaf54e08ca03/package.json#L9"&gt;package.json&lt;/a&gt; file as a runnable script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up ESLint
&lt;/h2&gt;

&lt;p&gt;The following instructions are adapted from &lt;a href="https://eslint.org/docs/latest/use/getting-started"&gt;https://eslint.org/docs/latest/use/getting-started&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To setup ESLint, I installed the &lt;code&gt;eslint package&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;bun &lt;span class="nb"&gt;install &lt;/span&gt;eslint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I created a &lt;a href="https://github.com/paulkim26/til-to-html/blob/c34a0b61c28847822f6a7467f68eeaf54e08ca03/.eslintrc.json"&gt;.eslintrc.json&lt;/a&gt; file. It extends the following templates to be compatible with typescript and Prettier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;eslint:recommended&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;plugin:@typescript-eslint/eslint-recommended&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;plugin:@typescript-eslint/recommended&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prettier&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I customized the linting rules to fit the preset coding conventions I set in my project; I disabled the following rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;no-useless-catch&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@typescript-eslint/no-explicit-any&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I added a &lt;code&gt;.eslintignore&lt;/code&gt; file, using the same contents of my existing &lt;code&gt;.gitignore&lt;/code&gt; file. To format the project, I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun eslint &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command is then added to the &lt;a href="https://github.com/paulkim26/til-to-html/blob/c34a0b61c28847822f6a7467f68eeaf54e08ca03/package.json#L10C14-L10C14"&gt;package.json&lt;/a&gt; file as a runnable script.&lt;/p&gt;

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

&lt;p&gt;To integrate with Visual Studio Code, I setup a VS Code configuration file under &lt;a href="https://github.com/paulkim26/til-to-html/blob/c34a0b61c28847822f6a7467f68eeaf54e08ca03/.vscode/settings.json"&gt;.vscode/settings.json&lt;/a&gt;. This file ensures that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prettier is set as the default formatter for the project.&lt;/li&gt;
&lt;li&gt;On save:

&lt;ul&gt;
&lt;li&gt;Files are formatted.&lt;/li&gt;
&lt;li&gt;Files are linted with ESLint.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following VS Code plugins are required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode"&gt;Prettier - Code formatter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint"&gt;ESLint&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;After running Prettier and ESLint, I found many issues in my existing code, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declared arguments that were unused&lt;/li&gt;
&lt;li&gt;Extraneous whitespace&lt;/li&gt;
&lt;li&gt;Improperly indented blocks&lt;/li&gt;
&lt;li&gt;Missing commas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have been using Prettier and ESLint for a while now in my own projects, but its a good idea to set it up for each project rather than globally so that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All contributors use it&lt;/li&gt;
&lt;li&gt;A specific version and configuration is used&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instructing and encouraging all contributors to follow the same standards I do in a programmatic, consistent way will help out immensely with the maintainability of the project.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hacktoberfest Recap</title>
      <dc:creator>Paul Kim</dc:creator>
      <pubDate>Wed, 01 Nov 2023 07:35:58 +0000</pubDate>
      <link>https://dev.to/paulkim26/hacktoberfest-recap-1i9m</link>
      <guid>https://dev.to/paulkim26/hacktoberfest-recap-1i9m</guid>
      <description>&lt;p&gt;For this month in &lt;a href="https://github.com/Seneca-CDOT/topics-in-open-source-2023/wiki"&gt;Topics in Open Source Development&lt;/a&gt;, I was tasked with partaking in &lt;a href="https://hacktoberfest.com/"&gt;Hacktoberfest&lt;/a&gt; and submitting 4 pull requests this month.&lt;/p&gt;

&lt;p&gt;Pull Request 1 - &lt;a href="https://dev.to/paulkim26/hacktoberfest-week-1-33hh"&gt;https://dev.to/paulkim26/hacktoberfest-week-1-33hh&lt;/a&gt;&lt;br&gt;
Pull Request 2 - &lt;a href="https://dev.to/paulkim26/hacktoberfest-week-2-4648"&gt;https://dev.to/paulkim26/hacktoberfest-week-2-4648&lt;/a&gt;&lt;br&gt;
Pull Request 3 - &lt;a href="https://dev.to/paulkim26/hacktoberfest-week-3-49id"&gt;https://dev.to/paulkim26/hacktoberfest-week-3-49id&lt;/a&gt;&lt;br&gt;
Pull Request 4 - &lt;a href="https://dev.to/paulkim26/hacktoberfest-week-4-ad2"&gt;https://dev.to/paulkim26/hacktoberfest-week-4-ad2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are the big takeaways I learned…&lt;/p&gt;

&lt;h2&gt;
  
  
  It takes a long time to find issues to work on
&lt;/h2&gt;

&lt;p&gt;There was no shortage of interesting projects to work on, but finding one to work on can be a lot of work in and of itself. Before taking on an issue I had to make sure I could even properly set it up. Some projects had extensive requirements to follow through. Others had technical issues or were buggy in a way that prohibited further enhancement for the issue. Another dealbreaker were projects that asked to be refactored entirely or have the documentation written for in post - this indicated a general lack of quality to me that was not worth dealing with.&lt;/p&gt;

&lt;p&gt;Here are some of the repositories I passed up for one reason or another:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No response

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/trussworks/react-uswds"&gt;https://github.com/trussworks/react-uswds&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Problems during setup

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mattermost/mattermost"&gt;https://github.com/mattermost/mattermost&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Xkonti/file-api"&gt;https://github.com/Xkonti/file-api&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/JordanForeman/cf-find"&gt;https://github.com/JordanForeman/cf-find&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/digitalfabrik/integreat-app#project-setup"&gt;https://github.com/digitalfabrik/integreat-app#project-setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/yanna92yar/open-listings"&gt;https://github.com/yanna92yar/open-listings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/beda-software/fhir-emr"&gt;https://github.com/beda-software/fhir-emr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/AnshuPathak-88825/Live-code"&gt;https://github.com/AnshuPathak-88825/Live-code&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;App did not work properly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/harshmangalam/qwik-x/issues/64"&gt;&lt;/a&gt;&lt;a href="https://github.com/harshmangalam/qwik-x/issues/64"&gt;https://github.com/harshmangalam/qwik-x/issues/64&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;App had errors fetching from database.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Felt too much like a student project

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/ConnectPlus-Org/ConnectPlus-Frontend/issues/36"&gt;https://github.com/ConnectPlus-Org/ConnectPlus-Frontend/issues/36&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Had typos everywhere.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/mazipan/tanyaaja"&gt;&lt;/a&gt;&lt;a href="https://github.com/mazipan/tanyaaja"&gt;https://github.com/mazipan/tanyaaja&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/LainForge/Neura-Launch-Dashboard"&gt;&lt;/a&gt;&lt;a href="https://github.com/LainForge/Neura-Launch-Dashboard"&gt;https://github.com/LainForge/Neura-Launch-Dashboard&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/qianzhong516/interactive-comments"&gt;&lt;/a&gt;&lt;a href="https://github.com/qianzhong516/interactive-comments"&gt;https://github.com/qianzhong516/interactive-comments&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/0l1v3rr/trello-clone/issues/42"&gt;&lt;/a&gt;&lt;a href="https://github.com/0l1v3rr/trello-clone/issues/42"&gt;https://github.com/0l1v3rr/trello-clone/issues/42&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Were out of scope

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/prasenjeet-symon/intellectia/issues/174"&gt;https://github.com/prasenjeet-symon/intellectia/issues/174&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/stephane-r/holoplay-pwa/issues/32"&gt;https://github.com/stephane-r/holoplay-pwa/issues/32&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Involved testing an Android version.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/0xVikasRushi/OpenIssueMonitor/issues/1"&gt;&lt;/a&gt;&lt;a href="https://github.com/0xVikasRushi/OpenIssueMonitor/issues/1"&gt;https://github.com/0xVikasRushi/OpenIssueMonitor/issues/1&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Involved non-coding work only

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/YurisCodingClub/zero-minds/issues/21"&gt;https://github.com/YurisCodingClub/zero-minds/issues/21&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;accessibility check&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/OpiumPay/opium-frontend/issues/2"&gt;&lt;/a&gt;&lt;a href="https://github.com/OpiumPay/opium-frontend/issues/2"&gt;https://github.com/OpiumPay/opium-frontend/issues/2&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;readme creation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I had no idea what these projects did

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/GEWIS/sudosos-backend/issues/84"&gt;https://github.com/GEWIS/sudosos-backend/issues/84&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hasadna/open-bus-map-search/issues/106"&gt;https://github.com/hasadna/open-bus-map-search/issues/106&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/inclinedadarsh/open-spectrum"&gt;https://github.com/inclinedadarsh/open-spectrum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/getAlby/ZapPlanner/issues/60"&gt;https://github.com/getAlby/ZapPlanner/issues/60&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jokly/crowdfunding"&gt;https://github.com/jokly/crowdfunding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/thtauhid/terminal-portfolio/issues/81"&gt;https://github.com/thtauhid/terminal-portfolio/issues/81&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  You can submit a pull request right away
&lt;/h2&gt;

&lt;p&gt;One thing I learned early on from my peers on our course Slack - you don't have to wait for permission to submit pull requests to an issue. You can go ahead and post one anyway and use that as a starting point for communication. This is contextual of course - certain problems require extensive communication before starting out on.&lt;/p&gt;

&lt;h2&gt;
  
  
  It can be fun to jump into a new framework on the fly
&lt;/h2&gt;

&lt;p&gt;I experienced a lot of new tools, frameworks, libraries, architectures, and coding styles during Hacktober. The ones that stuck out to me in particular were &lt;a href="https://www.prisma.io/"&gt;Prisma&lt;/a&gt;, &lt;a href="https://svelte.dev/"&gt;Svelte&lt;/a&gt;, &lt;a href="https://chakra-ui.com/"&gt;Chakra UI&lt;/a&gt;, &lt;a href="https://www.postgresql.org/"&gt;Postgres&lt;/a&gt;, &lt;a href="https://hodgef.com/simple-keyboard/"&gt;simple-keyboard&lt;/a&gt;, &lt;a href="https://qwik.builder.io/"&gt;Qwik&lt;/a&gt;, &lt;a href="https://www.notion.so/"&gt;Notion&lt;/a&gt;, and &lt;a href="https://firebase.google.com/"&gt;Firebase&lt;/a&gt;. I didn't have to learn these tools comprehensively at the onset - I could play around and tinker with them and discover how they worked and discover how to best use them for my specific use case. I may or may not use these all in my software development career but the skill of picking up, well, new skills is something I can hone over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The open source community is really nice
&lt;/h2&gt;

&lt;p&gt;The project maintainers I have interacted with were pleasant and professional to work with. They would go over my code extensively, give meaningful feedback, take and accept my suggestions - just overall be very easy to work with. Looking at other people's discussions, there was never any vitriol or poor communication skills on display between any parties (at least none that I've personally witnessed). Everyone has the same goal on a project and it's great to see everyone working together towards that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small issues can be a surprising amount of work
&lt;/h2&gt;

&lt;p&gt;An issue may seem straightforward at first, but I discovered some of them can go quite deep. For example, on one of my issues I had to implement a "Forget Password" page. At first it sounds like its just one new view to add, but the more I thought about it the more the work revealed itself - I had to introduce tokens stored in the database, I had to refactor existing code that overlapped with my aims, I would come across bugs in the code or in the tools I was working with. Thankfully, project maintainers can offer great insight and suggestions.&lt;/p&gt;

&lt;p&gt;Hacktober was really fun! I highly suggest everyone who hasn't already to give it a try next time.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hacktoberfest Week 4</title>
      <dc:creator>Paul Kim</dc:creator>
      <pubDate>Wed, 01 Nov 2023 07:35:03 +0000</pubDate>
      <link>https://dev.to/paulkim26/hacktoberfest-week-4-ad2</link>
      <guid>https://dev.to/paulkim26/hacktoberfest-week-4-ad2</guid>
      <description>&lt;p&gt;For my fourth and final &lt;a href="https://hacktoberfest.com/"&gt;Hacktoberfest&lt;/a&gt; PR, I worked on a project called &lt;a href="https://github.com/Yureien/YABin"&gt;YABin&lt;/a&gt; by &lt;a href="https://github.com/Yureien"&gt;Yureien&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Project Repository: &lt;a href="https://github.com/Yureien/YABin"&gt;https://github.com/Yureien/YABin&lt;/a&gt;&lt;br&gt;
Issue: &lt;a href="https://github.com/Yureien/YABin/issues/19"&gt;https://github.com/Yureien/YABin/issues/19&lt;/a&gt;&lt;br&gt;
My Pull Request: &lt;a href="https://github.com/Yureien/YABin/pull/29"&gt;https://github.com/Yureien/YABin/pull/29&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  YABin
&lt;/h2&gt;

&lt;p&gt;YABin is "Yet Another Pastebin" that seeks to add features not found in other similar applications, such as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Modern and minimal UI (This site's design was inspired by bin).&lt;/li&gt;
&lt;li&gt;Optional end-to-end encryption (we're using AES-256-GCM) with optional password protection (using PBKDF2).&lt;/li&gt;
&lt;li&gt;Syntax highlighting (using Prism) that supports 297 languages.&lt;/li&gt;
&lt;li&gt;API support to create and get pastes from command line.&lt;/li&gt;
&lt;li&gt;View raw pastes. Normally, encrypted pastebins do not have this. With this site, you can either get the Base64-encoded encrypted paste, or decrypt it on the server side (even with the password) and get the raw paste.&lt;/li&gt;
&lt;li&gt;Keyboard shortcuts!&lt;/li&gt;
&lt;li&gt;And of course, being fully open-source and easily self-hostable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NEW&lt;/strong&gt; Ability to edit pastes after creation, and a dashboard for viewing all your pastes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Comes with a CLI tool to create and read pastes from the command line!&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It can even be run on edge servers and in serverless environments!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is a &lt;a href="https://svelte.dev/"&gt;Svelte&lt;/a&gt; web application, can leverage any type of database (supported by &lt;a href="https://www.prisma.io/"&gt;Prisma&lt;/a&gt;). Users can create "pastes" to share with other users, set their time of expiration, they can be encrypted, be destroyed after being read, and users can create accounts.&lt;/p&gt;

&lt;p&gt;You can check it out here: &lt;a href="https://bin.sohamsen.me/"&gt;https://bin.sohamsen.me/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Issue
&lt;/h2&gt;

&lt;p&gt;The issue asks to implement a page for the user to reset their account password. Breaking this down, the flow would look as such:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user clicks on a "Forgot password?" link in the login page.&lt;/li&gt;
&lt;li&gt;Present user with a form to enter their username or email.&lt;/li&gt;
&lt;li&gt;The user clicks submit.&lt;/li&gt;
&lt;li&gt;The server finds the email address associated to user in the database (if just the username was provided).&lt;/li&gt;
&lt;li&gt;Generate a password reset token, overwriting any existing ones.&lt;/li&gt;
&lt;li&gt;Send an email to the user with a link to reset their password i.e. "Click this link to reset your password".&lt;/li&gt;
&lt;li&gt;The link takes the user to a page to enter their new password.&lt;/li&gt;
&lt;li&gt;Check that the password reset token exists and has not yet expired.&lt;/li&gt;
&lt;li&gt;If the provided password is valid, update it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This entails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The addition of two new routes&lt;/li&gt;
&lt;li&gt;A password reset token database entity&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;The first step was to get the project running. Following the project's &lt;a href="https://github.com/Yureien/YABin"&gt;README&lt;/a&gt;, I had to set up some kind of database; Postgres was recommended. I have not worked with the Prisma ORM before but I quite enjoyed using it. After setting up a Postgres database and user, all I had to do was migrate the schema defined in Prisma into my database and it would set it up accordingly. Prisma is flexible enough to work with many different types of databases, so it didn't have to necessarily be Postgres. It was interesting to look through through the Prisma migrations files in the project, they were incremental SQL statements that collectively formed the instructions on how to completely rebuild the database from scratch (&lt;a href="https://github.com/Yureien/YABin/tree/62c4eb2f05c5d4207a2df019ac932ccba12e3723/src/lib/server/prisma/migrations"&gt;source&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Svelte
&lt;/h2&gt;

&lt;p&gt;Another new thing about this project for me was using Svelte. Svelte is a framework I have only heard recently as a "down to earth" experience that felt like one was coding in the good old days where there was less abstraction in web development. The first thing that struck out at me was the file naming convention - a view was named &lt;code&gt;+page.svelte&lt;/code&gt; and server code was placed in &lt;code&gt;+page.server.ts&lt;/code&gt; files. I hadn't seen any frameworks that use &lt;code&gt;+&lt;/code&gt; signs in their pathnames - I would've thought this would cause issues in certain environments. The front-end syntax resembled &lt;a href="https://handlebarsjs.com/"&gt;Handlebars.js&lt;/a&gt;, a similar HTML templating library I learned a while ago.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Forgot Password" Page
&lt;/h2&gt;

&lt;p&gt;Here's the "Forgot Password" page I wrote - &lt;a href="https://github.com/Yureien/YABin/pull/29/files#diff-dbf052776c6d297935386d01582ffc6bcc9b37bba0c196f39f83f642dd7b87ca"&gt;src/routes/(auth)/forgot-password/+page.svelte&lt;/a&gt; and it's accompanying server code - &lt;a href="https://github.com/Yureien/YABin/pull/29/files#diff-722faba086fa3d16f43326a73aa255182fd02fd0124b4287b2cb0664594e4be2"&gt;src/routes/(auth)/forgot-password/+page.server.ts&lt;/a&gt;. If the &lt;code&gt;MAIL_ENABLED&lt;/code&gt; environment variable is set to false, the page will simply redirect the user to the root route (since email is disabled), otherwise the page loads normally. I set up two Svelte functions a &lt;code&gt;load&lt;/code&gt; function which is called upon page load and &lt;code&gt;actions&lt;/code&gt; which defines i.e. a callback function when a form is submitted. The page asks for a username or email of the account to reset the password for. It then checks if that user exists, then sends an email to the one registered for the user. It pulls the user data with Prisma's &lt;code&gt;findFirst&lt;/code&gt; method which was very straightforward to use. It was nice not having to worry about database-specific methods and just use a generic one that'll work for all of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nodemailer
&lt;/h2&gt;

&lt;p&gt;I set up a &lt;code&gt;sendRequestEmail&lt;/code&gt; function (&lt;a href="https://github.com/Yureien/YABin/pull/29/files#diff-a1a8d0f49906ee84c4eff1a704a6a6fc51631ec770a9a4830bea4a757cda5386"&gt;source&lt;/a&gt;) that calls a &lt;code&gt;generatePasswordResetToken&lt;/code&gt; function (&lt;a href="https://github.com/Yureien/YABin/pull/29/files#diff-fd038faf661d88f37997bf178de521166badf173fb2e735b2b538ee151f77f9d"&gt;source&lt;/a&gt;) that upserts a password reset token into this database for this user. It then constructs a URL and sends an email using the &lt;a href="https://nodemailer.com/"&gt;nodemailer&lt;/a&gt; library which I've used before. The SMTP service I had used before had gone defunct unfortunately and the free SMTP server options had features I could not overcome (i.e. requiring a legitimate business identity and address). I ended up using a spare Gmail address configured with an app password. I used &lt;a href="https://10minutemail.com/"&gt;10minutemail&lt;/a&gt; to generate some email addresses and everything worked great. The tokenized URL was sent to users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Processing a password change
&lt;/h2&gt;

&lt;p&gt;This URL would point to a new &lt;code&gt;reset-password&lt;/code&gt; route (&lt;a href="https://github.com/Yureien/YABin/pull/29/files#diff-12a66d73f1ebea6502e6dd7270666806057c619b4a5eb2af932eae19e5e46d96"&gt;source&lt;/a&gt;). Upon page load, it will check to see if the URL contains query parameters for the user ID and the reset token that was passed via the email. If one is missing or invalid, the user is blocked from the route. If both are present and verified, the page loads. The user will see two fields - a field to enter their new password and another to confirm. Upon page submission, the server will validate the password (i.e. are of a sufficient length), generate a password hash, delete the reset token, and then redirect the user to the login page (&lt;a href="https://github.com/Yureien/YABin/pull/29/files#diff-12a66d73f1ebea6502e6dd7270666806057c619b4a5eb2af932eae19e5e46d96"&gt;source&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I originally intended for the user to stay on the page with a confirmation message i.e. "Your password has been successfully updated." However, when I delete the reset token from the database, it noticed that it forces a page reload, which is problematic since the token will no longer exist and the route will be invalid. I attempted to suppress this page reload but was unable to find a way to do so. I am still not sure how to overcome this behaviour.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;This project was fun to work on. The new technologies (Svelte, Prisma) were fun and straightforward to work with and the project was organized well. I had to refactor some existing code to make it work (&lt;a href="https://github.com/Yureien/YABin/pull/29/files#r1378370358"&gt;source&lt;/a&gt;) - I tried to make smart, surgical changes that impacted the existing code as little as possible. I learned that it can be pretty easy to learn and work with new technologies on the fly - they all tend to follow similar features and workflows that can be worked out even without prior knowledge.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hacktoberfest Week 3</title>
      <dc:creator>Paul Kim</dc:creator>
      <pubDate>Wed, 01 Nov 2023 07:34:36 +0000</pubDate>
      <link>https://dev.to/paulkim26/hacktoberfest-week-3-49id</link>
      <guid>https://dev.to/paulkim26/hacktoberfest-week-3-49id</guid>
      <description>&lt;p&gt;For my third &lt;a href="https://hacktoberfest.com/"&gt;Hacktoberfest&lt;/a&gt; PR out of a required four, I continued worked on a project called &lt;a href="https://github.com/avikantz/ikea-word-games"&gt;Ordspel&lt;/a&gt; by &lt;a href="https://github.com/avikantz"&gt;avikantz&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Project Repository: &lt;a href="https://github.com/avikantz/ikea-word-games"&gt;https://github.com/avikantz/ikea-word-games&lt;/a&gt;&lt;br&gt;
Issue: &lt;a href="https://github.com/avikantz/ikea-word-games/issues/41"&gt;https://github.com/avikantz/ikea-word-games/issues/41&lt;/a&gt;&lt;br&gt;
My Pull Request: &lt;a href="https://github.com/avikantz/ikea-word-games/pull/42"&gt;https://github.com/avikantz/ikea-word-games/pull/42&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Issue
&lt;/h2&gt;

&lt;p&gt;A quick recap - Ordspel is a collection of linguistics games based on furniture names from the Ikea store. You can play it here - &lt;a href="https://ikeawordgames.com"&gt;https://ikeawordgames.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What was interesting was that not only was this a project I had previously worked on before (&lt;a href="https://github.com/avikantz/ikea-word-games/pull/40"&gt;my previous PR&lt;/a&gt;), but this was an issue I posted myself. While working on disabling the non-solution characters in the Jumble keyboard (&lt;a href="https://github.com/avikantz/ikea-word-games/issues/37"&gt;issue&lt;/a&gt;), I noticed that the keyboard would act funny. If there were more characters entered than allowed in the virtual keyboard, the characters would "overflow" and persist beyond the normal limit. It made for an unsatisfying user experience since you couldn't tell the bug was happening just by looking at it - you'd only realize the issue when you tried to backspace.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;Coming fresh off the previous issue, I was familiar with this project already (you can read my experiences &lt;a href="https://dev.to/paulkim26/hacktoberfest-week-2-4648"&gt;here&lt;/a&gt;). The solution was to truncate the stored input value in the keyboard component (accessed via the keyboard component reference) if the value exceeded the maximum input size (&lt;a href="https://github.com/avikantz/ikea-word-games/pull/42/files#diff-2207c6f6ccf81324c5e22842f260a3578efb8944ca56cf91edee0b33435e620a"&gt;link&lt;/a&gt;). This was an unfortunate circumstance of the keyboard's input value "desynchronizing" from the rest of the code. Since this input value was not maintained using React state but rather the simple keyboard API, there needed to be some extra checks and balances to make sure it was properly being watched.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;It surprised me that such a bug was there and unreported until I discovered it. It really goes to show how selective all of our perceptions and experiences around the same software are. We all experience software uniquely and catch onto certain issues that other's won't know. It goes to show the power of the open source community and having an extra set of eyes watching over one's shoulder 👀.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Adding a search feature to my app</title>
      <dc:creator>Paul Kim</dc:creator>
      <pubDate>Mon, 30 Oct 2023 04:59:34 +0000</pubDate>
      <link>https://dev.to/paulkim26/adding-a-search-feature-to-my-app-12g4</link>
      <guid>https://dev.to/paulkim26/adding-a-search-feature-to-my-app-12g4</guid>
      <description>&lt;p&gt;For this week in &lt;a href="https://github.com/Seneca-CDOT/topics-in-open-source-2023"&gt;Topics in Open Source Development&lt;/a&gt;, I was tasked with &lt;a href="https://dev.to/paulkim26/performing-a-code-reading-of-docusaurus-o1j"&gt;performing a code reading of a specific feature in Docusaurus&lt;/a&gt;, and implementing said feature into &lt;a href="https://github.com/paulkim26/til-to-html"&gt;my own project&lt;/a&gt;. The feature I selected was a search function. You can see it running live at &lt;a href="https://paulkim26.github.io/til-to-html/"&gt;https://paulkim26.github.io/til-to-html/&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does this feature entail?
&lt;/h2&gt;

&lt;p&gt;The feature I implemented was a search field, similar to the one found in Docusaurus. I added an HTML input field that, upon a change in input, will mark text in the generated static site that matches what was entered in the search field (&lt;a href="https://github.com/paulkim26/til-to-html/blob/13c7359f81dcc69a07eca9a6680aedebdce46aaf/src/website/index.js"&gt;source&lt;/a&gt;). It'll allow users to quick find text they are looking for and, in the future, across multiple pages - not just the current page. It works by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reading the contents of a TIL post's HTML after it is generated.&lt;/li&gt;
&lt;li&gt;Checking for instances of the current keyword entered in the search field via a regex match (not including text encapsulated within the chevrons of HTML tags).&lt;/li&gt;
&lt;li&gt;Replacing matched text with a copy encapsulated between HTML &lt;code&gt;&amp;lt;mark&amp;gt;&lt;/code&gt; tags.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why this feature?
&lt;/h2&gt;

&lt;p&gt;Working with new features, frameworks, and tools, the experience of reading documentation is a critical part of it. I have been lucky to work with projects that feature really easy to read documentation such as &lt;a href="https://designsystem.digital.gov/templates/documentation-page/"&gt;USWDS&lt;/a&gt; and &lt;a href="https://bun.sh/docs"&gt;Bun&lt;/a&gt;, but I've also had the misfortune to work with pretty terrible documentation like &lt;a href="https://jsdoc.app/"&gt;JSDoc&lt;/a&gt;. The JSDoc documentation lacks a search field which makes searching for specific items an ordeal and also does not cover many hidden use cases. It provides less than the bare minimum for what it needs to do - a lot of the time I am forced to rely on external user documentation elsewhere to use JSDoc effectively. That was why I was drawn to the search field in particular in Docusaurus.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison to the Docusaurus Search feature
&lt;/h2&gt;

&lt;p&gt;The most important distinction is that it is an offline local search function and not the Algolia DocSearch powered search featured in Docusaurus. I considered implementing Algolia DocSearch in my application but realized that does not make sense in this context since Algolia DocSearch needs to scrape sites to generate its search results. til-to-html is a static site generator for short form posts in similar scope to a blog - it is not "documentation" in the sense that Algolia DocSearch is primarily built for. It would still be nice to be able to search for specific content within til-to-html, but without the extensive overhead and functionality that Algolia provides. I determined an offline solution would be more suited for this context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;This is just the start of the feature. At the moment, the search is limited to the current page - it is no better than the &lt;code&gt;ctrl-f&lt;/code&gt; function of any browser. I plan to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provide the ability to search between multiple pages&lt;/li&gt;
&lt;li&gt;Allow the user to see a list of all search result instances&lt;/li&gt;
&lt;li&gt;Allow users to quickly switch between generated pages via a table of contents either within a sidebar or an index page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're interested in helping out, take a look at the issues page - the more the merrier!&lt;/p&gt;

&lt;p&gt;Issues: &lt;a href="https://github.com/paulkim26/til-to-html/issues"&gt;https://github.com/paulkim26/til-to-html/issues&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Performing a Code Reading of Docusaurus</title>
      <dc:creator>Paul Kim</dc:creator>
      <pubDate>Mon, 30 Oct 2023 04:27:51 +0000</pubDate>
      <link>https://dev.to/paulkim26/performing-a-code-reading-of-docusaurus-o1j</link>
      <guid>https://dev.to/paulkim26/performing-a-code-reading-of-docusaurus-o1j</guid>
      <description>&lt;p&gt;For this week in &lt;a href="https://github.com/Seneca-CDOT/topics-in-open-source-2023"&gt;Topics in Open Source Development&lt;/a&gt;, I was tasked with performing a code reading of &lt;a href="https://docusaurus.io/"&gt;Docusaurus&lt;/a&gt;, a popular documentation static site generator.&lt;/p&gt;

&lt;p&gt;Docusaurus provides the ability for users to search through documentation. Instead of bootstrapping its own search function, it leverages existing solutions which the developer can choose from, including &lt;a href="https://docsearch.algolia.com/"&gt;Algolia DocSearch&lt;/a&gt;, &lt;a href="https://typesense.org/"&gt;Typesense&lt;/a&gt;, a variety of &lt;a href="https://docusaurus.io/community/resources#search"&gt;community plugins&lt;/a&gt;, or one's own search solution. Since Docusaurus does not provide a native search function and relies on third party solutions, this code reading will focus on how it integrates the Algolia Docsearch search functionality into its UI.&lt;/p&gt;

&lt;p&gt;Docusaurus Repository: &lt;a href="https://github.com/facebook/docusaurus"&gt;https://github.com/facebook/docusaurus&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;The documentation to configure a search function for one's website is found in &lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/website/docs/search.mdx"&gt;website/docs/search.mdx&lt;/a&gt;. This same page is hosted officially at &lt;a href="https://docusaurus.io/docs/search"&gt;https://docusaurus.io/docs/search&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is a &lt;a href="https://mdxjs.com/"&gt;MDX&lt;/a&gt; file that combines both markdown and JSX syntax, though it does not use MDX specific syntax. It does however use Front Matter syntax for use with the &lt;a href="https://frontmatter.codes/docs/markdown"&gt;Front Matter&lt;/a&gt; extension, adding a &lt;code&gt;keywords&lt;/code&gt; attribute in a front matter block as its header, which defines parseable metadata.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
keywords:
  - algolia
  - search
---
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I haven't worked with MDX or Front Matter before, but I've seen (remarkably) similar syntax with Obsidian's &lt;a href="https://dev.to****"&gt;Tags&lt;/a&gt; syntax. This provides a way to tag and parse otherwise simple markdown files in a powerful, programmatic way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docusaurus Classic Preset
&lt;/h2&gt;

&lt;p&gt;Docusaurus features a set of presets - bundles of packages and plugins. Of note, the &lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-preset-classic/src/index.ts"&gt;classic preset&lt;/a&gt; supports the Algolia DocSearch by default. It does so by incorporating the &lt;code&gt;theme-search-algolia&lt;/code&gt; theme.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;preset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LoadContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Preset&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;siteConfig&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;themeConfig&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;siteConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;algolia&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;themeConfig&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ThemeConfig&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;isProd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;sitemap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;googleAnalytics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;gtag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;googleTagManager&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;opts&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;themes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PluginConfig&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nx"&gt;themes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;makePluginConfig&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/theme-classic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;algolia&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;themes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&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/theme-search-algolia&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="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;If a configuration object (resolved into the &lt;code&gt;algolia&lt;/code&gt; &lt;code&gt;Partial&amp;lt;ThemeConfig&amp;gt;&lt;/code&gt;) is not provided when instantiating this preset, the preset will not include the &lt;code&gt;theme-search-algolia&lt;/code&gt; theme. This is due to the fact that usage of the Algolia API requires the API variables to be defined in &lt;code&gt;docusaurus.config.js&lt;/code&gt; (details &lt;a href="https://docusaurus.io/docs/search#connecting-algolia"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Docusaurus Algolia Search Theme
&lt;/h2&gt;

&lt;p&gt;The Algolia search theme package is found in &lt;a href="https://github.com/facebook/docusaurus/tree/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia"&gt;/packages/docusaurus-theme-search-algolia&lt;/a&gt;. The package module and its types are defined in the &lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/theme-search-algolia.d.ts"&gt;theme-search-algolia.d.ts&lt;/a&gt; file. I've seen and used similar instances of declaring types (and their subtypes) in their own dedicated file for visibility.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/index.ts"&gt;docusaurus-theme-search-algolia/src/index.ts&lt;/a&gt; file defines the function &lt;code&gt;themeSearchAlgolia&lt;/code&gt; which returns the instantiated plugin of type &lt;code&gt;Plugin&amp;lt;void&amp;gt;&lt;/code&gt;, which is a type used to define Docusaurus plugins and contains data members such as its name, webpack configuration, file paths, HTML tags to inject, and translation files. Of note, it takes in a &lt;code&gt;themeConfig&lt;/code&gt; object which includes the Algolia API configuration data.&lt;/p&gt;

&lt;p&gt;In this package's &lt;code&gt;src&lt;/code&gt; folder there are the following directories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;__tests__&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Jest tests including:

&lt;ul&gt;
&lt;li&gt;A minimal configuration using a sample Algolia configuration (including a sample Algolia key and Algolia application ID) (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/__tests__/validateThemeConfig.test.ts#L29"&gt;link&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Passing an unknown key in this configuration (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/__tests__/validateThemeConfig.test.ts#L43C3-L43C3"&gt;link&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;If the Algolia configuration object is undefined (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/__tests__/validateThemeConfig.test.ts#L58C7-L58C8"&gt;link&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;If the API key is missing (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/__tests__/validateThemeConfig.test.ts#L78"&gt;link&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;client&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;A function to retrieve the theme configuration object (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/client/useAlgoliaThemeConfig.ts"&gt;link&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;A function to parse URLs returned from Algolia into local paths that can be navigated to within Docusaurus. This is done by first checking whether it is an external domain with a regex pattern match, then converting it to a relative URL (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/client/useSearchResultUrlProcessor.ts"&gt;link&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;templates&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Contains an HTML tag to integrate with the &lt;a href="https://opensearch.org/"&gt;OpenSearch API&lt;/a&gt; (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/templates/opensearch.ts"&gt;link&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;theme&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;The Search Bar React component (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx"&gt;link&lt;/a&gt;)

&lt;ul&gt;
&lt;li&gt;Returns a custom DocSearch component (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx#L268C11-L268C21"&gt;link&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;This component includes a property titled &lt;code&gt;transformSearchClient&lt;/code&gt; (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx#L251"&gt;link&lt;/a&gt;) which calls the &lt;code&gt;addAlgoliaAgent&lt;/code&gt; method from the &lt;code&gt;algoliasearch/lite&lt;/code&gt; package, which adds a custom user agent to interact with Algolia API (&lt;a href="https://www.algolia.com/doc/api-reference/api-methods/add-algolia-agent/"&gt;link&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;This search bar component is meant to be inserted into the navbar component for a theme, such as the Docusarus classic theme's navbar component (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-classic/src/theme/Navbar/Content/index.tsx#L90"&gt;link&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;To "prepare" the browser to load subsequent queries from the Algolia API, a &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tag referencing the Algolia service (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/index.tsx#L224"&gt;link&lt;/a&gt;) is placed in the &lt;code&gt;&amp;lt;Head&amp;gt;&lt;/code&gt; component that is not actually rendered to the client and serves no other purpose.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;The Search Page React component (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/index.tsx"&gt;link&lt;/a&gt;)

&lt;ul&gt;
&lt;li&gt;A dedicated search page component.&lt;/li&gt;
&lt;li&gt;An Algolia client is constructed using the &lt;code&gt;appId&lt;/code&gt; and &lt;code&gt;apiKey&lt;/code&gt; stored in the theme configuration object (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/index.tsx#L216"&gt;link&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;To use this client in a meaningful way, an Algolia helper is constructed where the parent component can define options including how many results to show per page (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/index.tsx#L217"&gt;link&lt;/a&gt;).

&lt;ul&gt;
&lt;li&gt;Upon receiving a search result (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/index.tsx#L223"&gt;link&lt;/a&gt;), a callback function is called that sanitizes the returned result and parses the result array via the JavaScript map method, returning an array of objects that includes the title, URL, a textual summary, and a trail of breadcrumbs to follow.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;searchResultStateDispatcher&lt;/code&gt; method is called with the returned and parsed search results to be stored in state.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Renders a dedicated link to &lt;code&gt;&lt;a href="http://www.algolia.com"&gt;www.algolia.com&lt;/a&gt;&lt;/code&gt; (&lt;a href="https://github.com/facebook/docusaurus/blob/495c7936b605e6b8881f000d23a8463a9d6d850c/packages/docusaurus-theme-search-algolia/src/theme/SearchPage/index.tsx#L424"&gt;link&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code Reading Techniques
&lt;/h2&gt;

&lt;p&gt;To perform this code reading, I opened this project in VS Code which I am more comfortable with instead of using GitHub code search or &lt;code&gt;git grep&lt;/code&gt;. The "search all" function was the most useful, as well as "Go To Definition" to see where a function alias was originally defined. I started by searching for the instances of the word &lt;code&gt;search&lt;/code&gt; throughout the project to find modules that were relevant to the search function. Next, I observed the file and folder structure to understand how the project was laid out.&lt;/p&gt;

&lt;p&gt;Directories of note include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;__tests__&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Tests specific to validating the &lt;code&gt;packages.json&lt;/code&gt; and &lt;code&gt;tsconfig.json&lt;/code&gt; files.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;admin&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Instructions for environment setup, testing, debugging, publishing, and other miscellaneous files.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;examples&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Example Docusaurus projects.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;packages&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Docusaurus packages including presets, scripts, plugins, types, utility functions, and themes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;website&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;The official Docusaurus website to be rendered and hosted. Acts as the single source of truth for Docusaurus documentation.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If there was any code that was unfamiliar to me (such as MDX syntax), I pasted it into ChatGPT to identify the type of syntax I was looking at (if I could not discern it from the filename extension). I also looked through the official Docusaurus documentation on how to implement the search function for more clues.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks for reading!&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hacktoberfest Week 2</title>
      <dc:creator>Paul Kim</dc:creator>
      <pubDate>Mon, 16 Oct 2023 00:39:25 +0000</pubDate>
      <link>https://dev.to/paulkim26/hacktoberfest-week-2-4648</link>
      <guid>https://dev.to/paulkim26/hacktoberfest-week-2-4648</guid>
      <description>&lt;p&gt;For &lt;a href="https://github.com/Seneca-CDOT/topics-in-open-source-2023"&gt;Topics in Open Source Development&lt;/a&gt;, the other students in this course and I are partaking in &lt;a href="https://hacktoberfest.com/"&gt;Hacktoberfest&lt;/a&gt; - a month-long open source community event where participants submit 4 pull requests to participating projects.&lt;/p&gt;

&lt;p&gt;In this post I will cover my experience finding a second issue to work with and submitting a pull request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ordspel
&lt;/h2&gt;

&lt;p&gt;For this entry, I've found a project called &lt;a href="https://github.com/avikantz/ikea-word-games"&gt;Ordspel&lt;/a&gt; - a website that features a collection of word games based on IKEA furniture names. You can play them at &lt;a href="https://ikeawordgames.com"&gt;https://ikeawordgames.com&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issue
&lt;/h2&gt;

&lt;p&gt;The issue can be found &lt;a href="https://github.com/avikantz/ikea-word-games/issues/37"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The problem is that in Jumble - one of the word games - the visual keyboard allows players to enter any letter in the alphabet. This causes some friction since players cannot enter any letters outside of the provided ones. You can give Jumble a try &lt;a href="https://ikeawordgames.com/en/jumble"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The maintainer wanted the non-solution letters to appear disabled/faded out so players wouldn't click on them. Additionally, there should be negative visual feedback from the game if the player were to click on a disabled letter anyway (i.e. the input field shakes).&lt;/p&gt;

&lt;p&gt;How it looked before:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VBctJ6R---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yekstm34xrhkt2jeq22q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VBctJ6R---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yekstm34xrhkt2jeq22q.png" alt="Before image" width="501" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How it looked after:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xJ5w6mhh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v11jcfelvr7zaopzd7qw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xJ5w6mhh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v11jcfelvr7zaopzd7qw.png" alt="After image" width="501" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Analyzing the project's code
&lt;/h2&gt;

&lt;p&gt;Looking through the code, I was pleasantly surprised with how straightforward and well organized the project was. Project setup was straightforward; just installed the node dependencies and ran in development mode. Ordspel is a React &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt; web application that uses &lt;a href="https://chakra-ui.com/"&gt;Chakra UI&lt;/a&gt; as its UI component library, which was right up my alley.&lt;/p&gt;

&lt;p&gt;The first step was to identify the part of the code that was responsible for handling the visual keyboard. I found that it was a custom React component named &lt;a href="https://github.com/avikantz/ikea-word-games/blob/main/src/components/wordInput.tsx"&gt;WordInput&lt;/a&gt;. It acted as a wrapper for a package called &lt;a href="https://hodgef.com/simple-keyboard/"&gt;simple-keyboard&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My first suggestion (&lt;a href="https://github.com/avikantz/ikea-word-games/issues/37#issuecomment-1762994947"&gt;post&lt;/a&gt; here) was to implement a &lt;code&gt;disabledKeys&lt;/code&gt; property where a parent component can stipulate which keys to specifically disable. &lt;a href="https://github.com/avikantz"&gt;avikantz&lt;/a&gt; (the maintainer) suggested to use the existing &lt;code&gt;targetValue&lt;/code&gt; property to determine which keys to disable, which was fine by me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Figuring out which keys to disable
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;targetValue&lt;/code&gt; property represented the target answer string the game was looking for. It was simple enough to figure out that the "bad" keys are just the rest of the keyboard (&lt;a href="https://github.com/avikantz/ikea-word-games/pull/40/files#diff-2207c6f6ccf81324c5e22842f260a3578efb8944ca56cf91edee0b33435e620aR58"&gt;link&lt;/a&gt;). However, since this game is based on Swedish words, there are special diacritics to handle - letters with umlauts i.e. Ö, Ä, Ü. Thankfully, the maintainer already provides a &lt;code&gt;removeAccents()&lt;/code&gt; method that strips these umlauts, making using the latin-only simple-keyboard interface easy to work with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making changes - look and feel
&lt;/h2&gt;

&lt;p&gt;The next step was to see if simple-keyboard's API provided an easy way to disable specific keys already. Turns out it didn't - should've figured as much. I looked through the documentation to see if there were any options that would be helpful. The &lt;a href="https://hodgef.com/simple-keyboard/documentation/options/buttonattributes/"&gt;buttonAttributes&lt;/a&gt; option allowed me to assign a specific attribute to specific keyboard keys which I could target via CSS (&lt;a href="https://github.com/avikantz/ikea-word-games/pull/40/files#diff-25039ca596a3c87daeca8f95c02e4e5f8d395754b2eb0ee07407dcb999a7625cL43"&gt;link&lt;/a&gt;). That handled the "look" of the disabled keys at least.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making changes - functionality
&lt;/h2&gt;

&lt;p&gt;To make the disabled keys non-interactable I used the &lt;code&gt;inputPattern&lt;/code&gt; option provided by simple-keyboard. This allowed me to specify a regex pattern that determined which keys to allow input for - in this case any characters not found in the solution. While this works, it did not allow me to satisfy the maintainer's design requirement to provide negative visual feedback (i.e. a shaking input field) since the input is simply ignored. So I had to look for another solution provided by the keyboard's API. It was a shame that this documentation does not provide a search function - it would have made searching for specific functionality a lot easier.&lt;/p&gt;

&lt;p&gt;I realized that the only way to handle this situation was to leverage the existing &lt;code&gt;onKeyPress&lt;/code&gt; callback function (&lt;a href="https://github.com/avikantz/ikea-word-games/pull/40/files#diff-2207c6f6ccf81324c5e22842f260a3578efb8944ca56cf91edee0b33435e620aR93"&gt;link&lt;/a&gt;). From there I could check what the current input of the field was and determine whether it contained a character from a disabled key or not. If so, I "jiggle" the input field as negative reinforcement and return early (&lt;a href="https://github.com/avikantz/ikea-word-games/pull/40/files#diff-2207c6f6ccf81324c5e22842f260a3578efb8944ca56cf91edee0b33435e620aR100"&gt;link&lt;/a&gt;). The animation uses the &lt;a href="https://www.framer.com/motion/use-animate/"&gt;useAnimate&lt;/a&gt; function from the Framer Motion animation library.&lt;/p&gt;

&lt;p&gt;Afterwards, I created a &lt;a href="https://github.com/avikantz/ikea-word-games/pull/40"&gt;pull request&lt;/a&gt; following the template provided by the maintainer and am now waiting to hear back.&lt;/p&gt;

&lt;h2&gt;
  
  
  A new issue
&lt;/h2&gt;

&lt;p&gt;While I was working on this project, I noticed there was a pre-existing bug - one could enter additional characters into the input field for Jumble via the visual keyboard. You couldn't see them but they were there - you can backspace to get rid of them. Thankfully I already had a solution in mind.&lt;/p&gt;

&lt;p&gt;I posted a new &lt;a href="https://github.com/avikantz/ikea-word-games/issues/41"&gt;issue&lt;/a&gt; and created a &lt;a href="https://github.com/avikantz/ikea-word-games/pull/42"&gt;pull request&lt;/a&gt; - the problem was that the length of the stored "input" of the keyboard component could exceed Jumble's allowed length. The solution was to truncate this value during the &lt;code&gt;onKeyPress&lt;/code&gt; callback so that any extra characters were always sliced off (&lt;a href="https://github.com/avikantz/ikea-word-games/pull/42/files"&gt;source&lt;/a&gt;). While it was possible to limit this field's length in other ways, doing this check during the callback allowed me to provide negative visual feedback (i.e. the same "jiggle").&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;All in all this was a very fun project to work with. The website was interesting, the project was well organized and documented, it was straightforward to set up, the maintainer was amicable and timely in their responses, and it was fun to use new libraries. &lt;/p&gt;

&lt;p&gt;The most difficult part was working around the limitations of the simple-keyboard API. It was tempting to look for workarounds or create a custom fork of this library that gave me more control, but in the end it provided just enough functionality for me to work with to complete my tasks. The lack of a search function in the documentation made the process surprisingly difficult - I hope that all of the documentation I have to deal with in the future provides one.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Hacktoberfest Week 1</title>
      <dc:creator>Paul Kim</dc:creator>
      <pubDate>Sun, 15 Oct 2023 13:51:53 +0000</pubDate>
      <link>https://dev.to/paulkim26/hacktoberfest-week-1-33hh</link>
      <guid>https://dev.to/paulkim26/hacktoberfest-week-1-33hh</guid>
      <description>&lt;p&gt;For &lt;a href="https://github.com/Seneca-CDOT/topics-in-open-source-2023"&gt;Topics in Open Source Development&lt;/a&gt;, the other students in this course and I are partaking in &lt;a href="https://hacktoberfest.com/"&gt;Hacktoberfest&lt;/a&gt; - a month-long open source community event where participants submit 4 pull requests to participating projects.&lt;/p&gt;

&lt;p&gt;In this post I will cover my experience finding a good issue to work with and submitting my first pull request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Searching for issues
&lt;/h2&gt;

&lt;p&gt;The first challenge was to find issues that were acceptable to work with. I queried for issues on GitHub with the following filters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;is:open is:issue label:hacktoberfest label:"good first issue" archived:false no:assignee -linked:pr comments:0 created:&amp;gt;2023-01-01 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will filter down issues that are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Participating in Hacktoberfest&lt;/li&gt;
&lt;li&gt;Open and unassigned&lt;/li&gt;
&lt;li&gt;Created recently&lt;/li&gt;
&lt;li&gt;Marked by the maintainer to be easier to work with&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Browsing through various repos, I learned to avoid repos that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Were inactive/abandoned&lt;/li&gt;
&lt;li&gt;Had few to no comments&lt;/li&gt;
&lt;li&gt;Were simple student projects&lt;/li&gt;
&lt;li&gt;I simply did not understand&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I avoided issues that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Involved adding onto lists of content&lt;/li&gt;
&lt;li&gt;Involved localization (I only know English)&lt;/li&gt;
&lt;li&gt;Were about providing wireframes/design prototypes

&lt;ul&gt;
&lt;li&gt;I presumed that designing (vs. actual coding) was outside the scope of this class&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Were about creating their readme

&lt;ul&gt;
&lt;li&gt;This signaled to me that the project was unorganized and unmaintained if they relied on external contributors to document their project&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Involved refactoring the entire project

&lt;ul&gt;
&lt;li&gt;Out of scope&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Process
&lt;/h2&gt;

&lt;p&gt;My original plan to contribute was:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find available issues that are labelled &lt;code&gt;hacktoberfest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check that I can properly set up the project locally&lt;/li&gt;
&lt;li&gt;Respond to the issue and:

&lt;ul&gt;
&lt;li&gt;Introduce myself to the maintainer&lt;/li&gt;
&lt;li&gt;Briefly described my propose solution and approach&lt;/li&gt;
&lt;li&gt;Request assignment &amp;amp; permission before starting&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Blockers
&lt;/h2&gt;

&lt;p&gt;Within these parameters, I found there was no shortage of interesting projects to worth with. The difficulty came however with certain blockers.&lt;/p&gt;

&lt;p&gt;My first blocker was being unable to successfully run certain projects despite following their set up guide. After following the extensive set up guide for a repo, the program would act in an aberrant way that prevented future development i.e. receiving random errors. It would be unclear without further context whether this was an issue during set up, runtime, or if the project was simply broken.&lt;/p&gt;

&lt;p&gt;The second blocker were projects with inaccessible pre-requisites. Many projects I've looked into required signing up for an external proprietary service that I was unable to set up.&lt;/p&gt;

&lt;p&gt;For example, a project required that I specifically created a developer account in the development platform &lt;a href="https://deta.space/"&gt;Deta Space&lt;/a&gt;. According to the &lt;a href="https://deta.space/docs/en/build/new-apps#sign-up-for-space-and-log-in"&gt;documentation&lt;/a&gt;, this was done by enabling an &lt;code&gt;Enable Developer Mode&lt;/code&gt; switch on the &lt;a href="https://deta.space/signup"&gt;sign up page&lt;/a&gt; which was not present. Unfortunately, I later realized that the documentation was obsolete and there was an undocumented developer-specific sign-up route &lt;code&gt;https://deta.space/signup?dev_mode=true&lt;/code&gt;. Now that I know, I may revisit this project. It's just a shame that the requisite platforms for certain projects may be blockers in and of themselves.&lt;/p&gt;

&lt;p&gt;Another blocker was waiting on feedback for proposed improvements prior to starting. Certain issues like &lt;a href="https://github.com/trussworks/react-uswds/issues/2608"&gt;this one&lt;/a&gt; with this &lt;a href="https://github.com/trussworks/react-uswds"&gt;accessibility-focused USWDS React component library&lt;/a&gt; have multiple approaches. In this case, the maintainer wondered whether or not a label should be hardcoded into a combo box React component for the sake of enforcing accessibility and that they could be convinced of either approach. I posted my &lt;a href="https://github.com/trussworks/react-uswds/issues/2608#issuecomment-1751302237"&gt;response&lt;/a&gt; detailing my approach to this problem. Unfortunately, I did not receive a response. I am not sure whether I should have submitted a pull request anyway, but I would prefer to have some initial feedback before starting one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding the first issue
&lt;/h2&gt;

&lt;p&gt;I found a project called &lt;a href="https://github.com/movesthatmatter/movex"&gt;movex&lt;/a&gt; - a serverless data sharing infrastructure that allows one to easily develop network-focused apps without worrying about the back end logic. This looked like a great tool to use especially for front-end developers who want to focus on client-facing functionality and aesthetics.&lt;/p&gt;

&lt;p&gt;The set up process was straightforward. The project was very well documented, between its &lt;a href="https://github.com/movesthatmatter/movex/blob/main/CONTRIBUTING.md"&gt;contributing guide&lt;/a&gt; to its &lt;a href="https://www.movex.dev/docs/overview/get_started"&gt;API documentation&lt;/a&gt;. The only new requisite I had to prepare was &lt;a href="https://nx.dev/"&gt;NX&lt;/a&gt; to handle building and testing the project.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/movesthatmatter/movex/issues/135"&gt;issue&lt;/a&gt; was simple - to add &lt;a href="https://github.com/commitizen/cz-cli"&gt;commitizen&lt;/a&gt; to the list of project dependencies. This project uses commitizen to enforce a structure to commits, similar to the &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/"&gt;Conventional Commits&lt;/a&gt; specification which I already know. Up until now, the project relied on contributors to install commitizen globally on their machine (i.e. &lt;code&gt;npm install -g commitizen&lt;/code&gt;) before they made commits. This way, everyone was using commitizen from the start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Submitting my first pull request
&lt;/h2&gt;

&lt;p&gt;After reading through the contribution guidelines and pushing my changes, I noticed that in my pull request I forgot to properly sign my commits - whoops! The fix was easy thankfully - I set up a new gpg key, associated it to my GitHub profile, amended my commit retroactively (making sure to sign it this time), and force pushed it to my feature branch on my fork. The maintainer was fast to respond and pleasant to interact with - certainly a project I look forward to following and potentially to work on further.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;The biggest lesson I learned from submitting my first Hacktoberfest pull request and talking with my colleagues was that instead of always waiting for permission from maintainers to publish a pull request, sometimes I should put one out anyway. A pull request can be a great starting point for discussion under some circumstances. The same can't be said for larger, more involved issues that absolutely do require further communication and coordination. The experience of submitting this first issue, while simple, helped me learn the intricacies of contribution, particularly with signed commits.&lt;/p&gt;

&lt;p&gt;Another lesson I learned was that it truly is a wild west of projects out there. Aside from the time pressure of racing to contribute to Hacktoberfest-specific issues before they're assigned to someone else, there is a spectrum of quality with these projects. They may feature incomprehensible errors out of the gate, lack proper documentation, are cumbersome to set up, etc. There are also many well-maintained projects out there as well, it just takes some time (and luck) to sift through and find them.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Code refactoring practice</title>
      <dc:creator>Paul Kim</dc:creator>
      <pubDate>Sat, 14 Oct 2023 05:53:56 +0000</pubDate>
      <link>https://dev.to/paulkim26/code-refactoring-practice-og3</link>
      <guid>https://dev.to/paulkim26/code-refactoring-practice-og3</guid>
      <description>&lt;p&gt;For this week's &lt;a href="https://github.com/Seneca-CDOT/topics-in-open-source-2023/wiki/lab-5"&gt;lab&lt;/a&gt; in &lt;a href="https://github.com/Seneca-CDOT/topics-in-open-source-2023"&gt;Topics in Open Source Development&lt;/a&gt;, I was tasked with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Refactoring my code repository&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;git rebase&lt;/code&gt; to alter my commit history&lt;/li&gt;
&lt;li&gt;Squashing multiple commits into one&lt;/li&gt;
&lt;li&gt;Amending a previous commit&lt;/li&gt;
&lt;li&gt;Merging commits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub Repository: &lt;a href="https://github.com/paulkim26/til-to-html"&gt;til-to-html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Refactoring
&lt;/h2&gt;

&lt;p&gt;With two recent pull requests from external contributors merged in, the code repository was ready for some refactoring. A lot of new features had been added onto my code base from a lot of different people - it was time to clean it all up. Refactoring changes included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rethinking how my program handles custom command line arguments&lt;/li&gt;
&lt;li&gt;Cleaning up extraneous whitespace and deviations in coding style&lt;/li&gt;
&lt;li&gt;Adding missing documentation&lt;/li&gt;
&lt;li&gt;Removing extraneous files (i.e. a newly added &lt;code&gt;package-lock.json&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Consolidating redundant functionality into one code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was satisfying to look at my code again and see new patterns and flows appearing. The act of looking over new features like the &lt;code&gt;--config&lt;/code&gt; flag recontextualized my prior code - instead of leaving it in a state where it was "added onto" existing code, I found new ways to "integrate" it.&lt;/p&gt;

&lt;p&gt;The previous pull request had added new configuration file parsing functionality to my main &lt;code&gt;index.ts&lt;/code&gt; file (&lt;a href="https://github.com/paulkim26/til-to-html/commit/df4dd8bd08ab11feb25b0d75ab66585f3df53da0#diff-a2a171449d862fe29692ce031981047d7ab755ae7f84c707aef80701b3ea0c80R1-L15"&gt;source&lt;/a&gt;). I moved this new feature into my &lt;code&gt;parseArguments.ts&lt;/code&gt; module (&lt;a href="https://github.com/paulkim26/til-to-html/commit/df4dd8bd08ab11feb25b0d75ab66585f3df53da0#diff-b5525fc172c205cb1bd05b3a60fee0de57249d15235a4bc1ef0701eb29a0e59dR36-R55"&gt;source&lt;/a&gt;) and consolidated the previously added &lt;code&gt;configuration.ts&lt;/code&gt; and &lt;code&gt;configurationParse.ts&lt;/code&gt; modules into a single one.&lt;/p&gt;

&lt;p&gt;I also cleaned up some inconsistencies with the coding style, including replacing the usage of the &lt;code&gt;var&lt;/code&gt; keyword with &lt;code&gt;const&lt;/code&gt; or &lt;code&gt;let&lt;/code&gt; and reformatting my code with Prettier.&lt;/p&gt;

&lt;p&gt;After all of these changes, I tested all of my use cases again to ensure they were all working. There were no bugs before to fix so that was good. I did notice the configuration loading feature handled command line switches like &lt;code&gt;-v&lt;/code&gt; and &lt;code&gt;-h&lt;/code&gt; - I eliminated support for those since that was out of the domain of &lt;code&gt;.toml&lt;/code&gt; configuration files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rebasing and amending commits
&lt;/h2&gt;

&lt;p&gt;After making all of my changes in a &lt;code&gt;refactoring&lt;/code&gt; branch, I performed an interactive git rebase which allowed me to squash all of my commits into one. Then I used &lt;code&gt;git commit --amend&lt;/code&gt; to change the commit message. Then I merged this refactoring branch into the main branch.&lt;/p&gt;

&lt;p&gt;Squashing commits definitely helped clean up my git commit history. While I could have simply fast forward merged all of these individual commits into my main branch, it would have polluted my commit history for the future. In the grand scheme of things, I doubt I would need to pick apart and checkout specific commits from this refactoring process down the line.&lt;/p&gt;

&lt;p&gt;I typically perform commit squashes and merges on GitHub directly but it was nice to do all of that in a local git environment. That said, I plan to still utilize GitHub's versions of these interfaces when collaborating with others in addition to using git.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Working with Git remotes and merging</title>
      <dc:creator>Paul Kim</dc:creator>
      <pubDate>Fri, 06 Oct 2023 05:40:20 +0000</pubDate>
      <link>https://dev.to/paulkim26/working-with-parallel-branches-4ngp</link>
      <guid>https://dev.to/paulkim26/working-with-parallel-branches-4ngp</guid>
      <description>&lt;p&gt;For this week in &lt;a href="https://github.com/Seneca-CDOT/topics-in-open-source-2023"&gt;Topics in Open Source Development&lt;/a&gt; at &lt;a href="https://www.senecacollege.ca/home.html"&gt;Seneca College&lt;/a&gt;, I was tasked with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding a new feature to another student's repository&lt;/li&gt;
&lt;li&gt;Practicing working with &lt;code&gt;git fetch&lt;/code&gt; and &lt;code&gt;git merge&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;For this lab, instead of working with my previous partner, I was asked to work with someone else for a change. I noticed my buddy &lt;a href="https://github.com/bryce-seefieldt"&gt;Bryce&lt;/a&gt;'s project &lt;a href="https://github.com/bryce-seefieldt/ez-txt2html"&gt;ez-txt2html&lt;/a&gt; was not yet worked on by anyone else. His version of our tool was written in Python - a language I've only had minimal experience working with. It looked like a great opportunity to work with that language so I decided to post an &lt;a href="https://github.com/bryce-seefieldt/ez-txt2html/issues/21"&gt;issue&lt;/a&gt; to add this week's new feature.&lt;/p&gt;

&lt;p&gt;While I was going through and playing with his code, I noticed it was missing a &lt;code&gt;.gitignore&lt;/code&gt; file which made it cumbersome when VS Code kept trying to track some generated HTML files; I opened a separate &lt;a href="https://github.com/bryce-seefieldt/ez-txt2html/issues/19"&gt;issue&lt;/a&gt; and &lt;a href="https://github.com/bryce-seefieldt/ez-txt2html/pull/20"&gt;PR&lt;/a&gt; to address that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to TOML
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Seneca-CDOT/topics-in-open-source-2023/wiki/lab-4"&gt;Lab 4&lt;/a&gt; asked us to add the ability to load &lt;a href="https://toml.io/en/"&gt;TOML&lt;/a&gt; configuration files with pre-defined arguments to each others' projects. I had never heard of TOML, it's pretty neat! It reminded me of &lt;a href="https://yaml.org/"&gt;YAML&lt;/a&gt; and its intent to be a human readable, simple, open-source alternative to JSON that was still widely used. It's pretty interesting how ubiquitous open-sourced standards and conventions can become in the global code space. I only worked with TOML a little bit for this lab and just barely scratched the surface (which I get into below). It looks like a standard &lt;code&gt;.ini&lt;/code&gt; file but with fancy new features like keys, values, section headers, but with some interesting caveats like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A standardized datetime type&lt;/li&gt;
&lt;li&gt;Arrays&lt;/li&gt;
&lt;li&gt;Objects&lt;/li&gt;
&lt;li&gt;Tables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will definitely look for ways to integrate TOML into my future projects and working with it more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the new TOML loading function
&lt;/h2&gt;

&lt;p&gt;I looked over Bryce's code; all of the core functionality was on one &lt;code&gt;.py&lt;/code&gt; file so that made things simple to understand. I added a new &lt;code&gt;-c/--config&lt;/code&gt; argument to his &lt;code&gt;argparse&lt;/code&gt; command line parser. I added a new TOML loading function which leverages the &lt;code&gt;tomllib&lt;/code&gt; module. Again, its fantastic that this Python specific implementation of TOML exists and is open source. Best of all, it's natively integrated into Python 3.11 - no fuss, no muss. It's also fantastic that there's not just one implementation - there's also &lt;a href="https://github.com/bobfang1992/pytomlpp"&gt;pytomlpp&lt;/a&gt; and &lt;a href="https://github.com/hukkin/tomli"&gt;tomli&lt;/a&gt;, pick your poison.&lt;/p&gt;

&lt;p&gt;Here's my function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Load arguments from a config file
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;loadConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configPath&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"rb"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tomllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;FileNotFoundError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"Config file '&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;configPath&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;' could not be found."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty simple stuff. I both catch and throw an exception if there's problems with loading the config file. I call this function in the main argument handling function and override the command line argument values.&lt;/p&gt;

&lt;p&gt;I add a new sample &lt;code&gt;config.toml&lt;/code&gt; file to play with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"./HTML"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This application does not yet implementing more options, so the TOML sample was accordingly simple; just an option to pre-define the output parameter. After testing and making sure it looked okay, I pushed a PR for Bryce.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback
&lt;/h2&gt;

&lt;p&gt;Bryce accepted the PR, but did note that some more documentation would be ideal. I totally forgot to include the implementation details in the &lt;code&gt;README.md&lt;/code&gt;, silly me. I added that soon after.&lt;/p&gt;

&lt;p&gt;All in all, a fun little feature addition experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with Git remotes and merging
&lt;/h2&gt;

&lt;p&gt;Note: As of writing, I have not received a pull request for my application &lt;a href="https://github.com/paulkim26/til-to-html"&gt;til-to-html&lt;/a&gt;, sadly.&lt;/p&gt;

&lt;p&gt;As this part of the lab is contingent on receiving a pull request from someone else to experiment with, I will update this section when I do.&lt;/p&gt;

&lt;p&gt;Thanks for reading! See y'all next week.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
