<?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: Peter Wan</title>
    <description>The latest articles on DEV Community by Peter Wan (@peterdanwan).</description>
    <link>https://dev.to/peterdanwan</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%2F2027096%2F70d467c0-3e79-4673-877d-4c361d816da7.jpeg</url>
      <title>DEV Community: Peter Wan</title>
      <link>https://dev.to/peterdanwan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/peterdanwan"/>
    <language>en</language>
    <item>
      <title>Coming Full Circle: It starts and ends with Git and GitHub</title>
      <dc:creator>Peter Wan</dc:creator>
      <pubDate>Fri, 06 Dec 2024 21:04:48 +0000</pubDate>
      <link>https://dev.to/peterdanwan/coming-full-circle-it-starts-and-ends-with-git-and-github-n9o</link>
      <guid>https://dev.to/peterdanwan/coming-full-circle-it-starts-and-ends-with-git-and-github-n9o</guid>
      <description>&lt;p&gt;As I begin to finish my &lt;a href="https://github.com/humphd/topics-in-open-source-2024/wiki/release-0.4" rel="noopener noreferrer"&gt;final assessment for the &lt;code&gt;Topics In Open Source 2024&lt;/code&gt;&lt;/a&gt; course, led by Professor &lt;a href="https://github.com/humphd" rel="noopener noreferrer"&gt;David Humphrey&lt;/a&gt;, I find myself reflecting on how fitting this moment is. My journey in open source began with learning the fundamentals of Git and GitHub - understanding commits, branches, pull requests, and the intricate dance of version control. Now, here I am, contributing to a browser extension that helps others visualize and understand these same concepts better.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/NirmalScaria" rel="noopener noreferrer"&gt;
        NirmalScaria
      &lt;/a&gt; / &lt;a href="https://github.com/NirmalScaria/le-git-graph" rel="noopener noreferrer"&gt;
        le-git-graph
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Browser extension to add git graph to GitHub website.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Le Git Graph - Commits Graph for GitHub&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/d4a6d2e86e70830b9fa62b78aac7bbb97ce6f21abeb986e19d915d1240873c58/68747470733a2f2f64726976652e676f6f676c652e636f6d2f75633f6578706f72743d646f776e6c6f61642669643d3132626e51717934636d327651635a534b576f32494e42762d363969716b465f70"&gt;&lt;img src="https://camo.githubusercontent.com/d4a6d2e86e70830b9fa62b78aac7bbb97ce6f21abeb986e19d915d1240873c58/68747470733a2f2f64726976652e676f6f676c652e636f6d2f75633f6578706f72743d646f776e6c6f61642669643d3132626e51717934636d327651635a534b576f32494e42762d363969716b465f70" width="150"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A browser extension that displays the git graph for any GitHub repository.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/NirmalScaria/le-git-graph" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/901f9db3e963448dcd1b8bd8816e4063dec2250babf7447d7937d5a3c9d5cc45/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f77" alt="Version"&gt;&lt;/a&gt;
&lt;a href="https://github.com/NirmalScaria/le-git-graph" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/ba8f48da5457637433cf2746efa5806678d54023c86bde68ff3a88f347216687/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f56657273696f6e2d312e322e382d79656c6c6f77677265656e" alt="Version"&gt;&lt;/a&gt;
&lt;a href="https://github.com/NirmalScaria/le-git-graph" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/f405f8a1032394e4d6028b2abdd28861f105700540680a7986f7d41daae66291/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4368726f6d655f43492f43442d537563636573732d677265656e" alt="Version"&gt;&lt;/a&gt;
&lt;a href="https://github.com/NirmalScaria/le-git-graph" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/7120eca3bc1960c3b0401edd9c2f030104b170c2df3d480d3cc3751082df974d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f46697265666f785f43492f43442d537563636573732d677265656e" alt="Version"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Demo&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/46727865/218700103-c26082db-a696-435c-934c-cc66e1c067bd.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F46727865%2F218700103-c26082db-a696-435c-934c-cc66e1c067bd.png" alt="Demo Image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Install the extension from the link -&lt;/p&gt;
&lt;p&gt;For Google Chrome, Opera, Vivaldi, Brave, and Microsoft Edge:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://chrome.google.com/webstore/detail/le-git-graph-commits-grap/joggkdfebigddmaagckekihhfncdobff" rel="nofollow noopener noreferrer"&gt;https://chrome.google.com/webstore/detail/le-git-graph-commits-grap/joggkdfebigddmaagckekihhfncdobff&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For Mozilla Firefox:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://addons.mozilla.org/firefox/addon/le-git-graph-github-git-graph/" rel="nofollow noopener noreferrer"&gt;https://addons.mozilla.org/firefox/addon/le-git-graph-github-git-graph/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After installation, open any GitHub repository and a new 'Commits' tab will be visible.&lt;/p&gt;
&lt;p&gt;Open the commits tab and follow the prompt to authenticate with your GitHub account.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Setup for Private Repos owned by an Organization&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Access to private repositories owned by an organization is restricted by default. To access the commits graph for such repositories, you need to follow the following steps.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://github.com/settings/tokens" rel="noopener noreferrer"&gt;https://github.com/settings/tokens&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Create a Personal Access Token (PAT)  with the following scopes -
&lt;ul&gt;
&lt;li&gt;repo |  Full control of private repositories&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;For a more secure option, use a Fine-Grained token (beta) with the following scopes -&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;repo |  Read access to code, commit statuses…&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/NirmalScaria/le-git-graph" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://github.com/NirmalScaria/le-git-graph" rel="noopener noreferrer"&gt;Le Git Graph&lt;/a&gt; is a browser extension that enhances GitHub's interface by adding a visual commit graph (note - if you have the repository installed locally, it'd be equivalent to running &lt;code&gt;git log --all --graph&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;While GitHub &lt;em&gt;does&lt;/em&gt; have the ability to show you the list of commits on a repository, this extension provides the ability to view these commits in a &lt;code&gt;graph&lt;/code&gt; form, which in my opinion, is really helpful.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GitHub's normal feature of showing commit history&lt;/code&gt;:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fme0b09oiv87c6w5gz1on.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fme0b09oiv87c6w5gz1on.png" alt="github-commits" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Le Git Graph's Commit View&lt;/code&gt;:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnlbb089babapzxb6iidz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnlbb089babapzxb6iidz.png" alt="le-git-graph-in-action" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ability to see the commit history &lt;em&gt;and&lt;/em&gt; get a visual idea of when branches were made and merged serve to enhance one's understanding of a repository's development progress. I think those looking to contribute in &lt;code&gt;open source development&lt;/code&gt; would find this extension to be highly valuable. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge
&lt;/h2&gt;

&lt;p&gt;My contribution to this project involved fixing some of the broken behaviors when clicking the &lt;code&gt;Commits&lt;/code&gt; button that is injected by &lt;code&gt;Le Git Graph&lt;/code&gt;. The original issue can be found &lt;a href="https://github.com/NirmalScaria/le-git-graph/issues/23" rel="noopener noreferrer"&gt;here&lt;/a&gt;, and my pull request showing what has been updated can be found &lt;a href="https://github.com/NirmalScaria/le-git-graph/pull/87" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To sum up the issue - the &lt;code&gt;Commits&lt;/code&gt; button would disappear sometimes when navigating across different GitHub links (e.g., simply clicking the name of the repository would cause the &lt;code&gt;Commits&lt;/code&gt; button to disappear!).&lt;/p&gt;

&lt;p&gt;The solution involved implementing robust event listeners for GitHub's various navigation events and improving how the extension detects and maintains UI elements across different page contexts. This fix ensures the Commits button stays visible and functional regardless of how users navigate through GitHub's interface, whether clicking repository links or switching between tabs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Learning Journey
&lt;/h2&gt;

&lt;p&gt;Looking back, it's almost poetic how this project encapsulates my identity and growth in open source development:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Understanding Git&lt;/strong&gt;: When I first started, visualizing Git's branching and merging concepts was one of the biggest challenges for me. However, once I understood those concepts, I started using &lt;code&gt;git log --all --graph&lt;/code&gt; daily as if it was a matter of fact thing to do. Jump forward to the present, I'm trying to improve the functionality of &lt;code&gt;Le Git Graph&lt;/code&gt;, which offers this visualization to others.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Browser Extensions&lt;/strong&gt;: As mentioned in my previous blogs when I worked on the &lt;a href="https://github.com/code-charity/youtube" rel="noopener noreferrer"&gt;ImprovedTube&lt;/a&gt; extension - I have recently been invested in learning more about browser extensions. The work I did for &lt;code&gt;Le Git Graph&lt;/code&gt;, has taught me about the complexities of integrating with existing web applications (you have to know a &lt;em&gt;lot&lt;/em&gt; about GitHub's interface in order to manipulate it!). Working on this extension made realize GitHub's dynamic nature requires me to carefully handle different page states and navigation patterns - and even then, there might be things that change and I'll have to update the code accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open Source Collaboration&lt;/strong&gt;: Contributing to an existing project means understanding someone else's code, following their conventions, and thinking about backward compatibility - skills that weren't even on my radar when I first learned Git. Wrapping my head around someone else's codebase has always been quite difficult for me - even with &lt;code&gt;Le Git Graph&lt;/code&gt;, I had to move cautiously since I'm familiar with &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; variable declarations which have block level scope, vs. &lt;code&gt;var&lt;/code&gt; which has function level scope - believe me, these little things add up. Nevertheless, I couldn't let little things like that completely overwhelm me, instead I tried to understand the purpose of &lt;code&gt;Le Git Graph&lt;/code&gt; by &lt;em&gt;staring&lt;/em&gt; at its &lt;code&gt;manifest.json&lt;/code&gt; found in the root of the project. By looking at the filenames listed under &lt;code&gt;content_scripts&lt;/code&gt;, my top-level understanding of the extension improved. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foasi3ohmc40nksluc9us.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foasi3ohmc40nksluc9us.png" alt="content_scripts" width="800" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the picture above, you can see files that are &lt;em&gt;dedicated&lt;/em&gt; to drawing the git graph (i.e., drawGraph.js). By taking a moment to digest these different filenames, I was able to better understand how this repository worked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Deep Dive
&lt;/h2&gt;

&lt;p&gt;The technical challenges I faced were particularly interesting because they touched on multiple aspects of modern web development:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Navigation Handling&lt;/strong&gt;: GitHub uses Turbo (formerly Turbolinks) for navigation, which required careful handling of different events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://turbo.hotwired.dev/reference/events#turbo%3Aload" rel="noopener noreferrer"&gt;turbo:load&lt;/a&gt; for initial page loads&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/defunkt/jquery-pjax/blob/master/README.md" rel="noopener noreferrer"&gt;pjax:end&lt;/a&gt; for partial page updates&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DOMContentLoaded&lt;/code&gt; for ensuring our code runs at the right time&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DOM Management&lt;/strong&gt;: The solution required careful management of the DOM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detecting and handling different UI containers based on context&lt;/li&gt;
&lt;li&gt;Preventing duplicate buttons during reinitialization&lt;/li&gt;
&lt;li&gt;Maintaining state across navigation events&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;: Robust error handling was crucial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Graceful fallbacks when expected elements aren't found&lt;/li&gt;
&lt;li&gt;Cleanup of stale elements and event listeners&lt;/li&gt;
&lt;li&gt;Proper logging for debugging purposes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Results and Achievements
&lt;/h2&gt;

&lt;p&gt;Looking at my initial goals from the beginning of the course to right before this final blog post, I would say I was able to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;✅ Learn about Git and GitHub for the purpose of working in Open Source&lt;/li&gt;
&lt;li&gt;✅ Pick a niche that I wanted to focus on for development (browser extension development).&lt;/li&gt;
&lt;li&gt;✅ Find repositories that aligned with my goals and aspirations (&lt;code&gt;ImprovedTube&lt;/code&gt; and &lt;code&gt;Le Git Graph&lt;/code&gt;). Fixed the disappearing Commits button issue&lt;/li&gt;
&lt;li&gt;✅ Work on using my pre-existing web-development skills to contribute meaningful code to an open source project&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These 4 results and achievements make me realize how far I've come since the start of my open source journey and makes me excited to venture further down this path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion of my experience of the &lt;code&gt;Topics in Open Source 2024&lt;/code&gt; course
&lt;/h2&gt;

&lt;p&gt;As I wrap up my journey in the Topics in Open Source 2024 course, I've seen my skills progress from learning basic Git commands to contributing to a tool that helps others visualize those very concepts. Through my work on Le Git Graph and ImprovedTube, I've grown from someone who knew nothing about browser extensions to a developer who can navigate a browser extension's codebase and potentially enhance it. This course has taught me that open source development is more than just writing code; it's about understanding existing systems, collaborating effectively, and contributing to tools that make development more accessible for others. As I move forward, I'm excited to continue growing in the open source community, armed with the knowledge, skills, and confidence I've gained from this course. Thank you Professor Humphrey, for providing great guidance during this journey and helping me discover my place in the open source world.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>git</category>
      <category>github</category>
      <category>extensions</category>
    </item>
    <item>
      <title>Continuous contributions</title>
      <dc:creator>Peter Wan</dc:creator>
      <pubDate>Sun, 01 Dec 2024 03:44:26 +0000</pubDate>
      <link>https://dev.to/peterdanwan/continuous-contributions-10p</link>
      <guid>https://dev.to/peterdanwan/continuous-contributions-10p</guid>
      <description>&lt;p&gt;Following up on my last &lt;a href="https://dev.to/peterdanwan/learning-by-doing-working-on-improvedtube-4pbe"&gt;blog&lt;/a&gt;, I've been aiming to learn more about browser extension development through practical experience. In particular, I've been trying my hand at contributing to the open-source project, &lt;code&gt;ImprovedTube&lt;/code&gt;, which enhances one's viewing experience on YouTube. The source code for &lt;code&gt;ImprovedTube&lt;/code&gt; can be found below:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/code-charity" rel="noopener noreferrer"&gt;
        code-charity
      &lt;/a&gt; / &lt;a href="https://github.com/code-charity/youtube" rel="noopener noreferrer"&gt;
        youtube
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      [top~1 open YouTube &amp;amp; Video browser-extension] - Enrich your experience &amp;amp; choice! 🧰180+ options &amp;amp; clever features 📌set+forget📌Longest-standing(been tough). Please join🧩us👨‍👩‍👧‍👧 ..⋮ {playback|content discovery|player|extra buttons|distractions|related videos|shorts|ads|quality|codec|full tab|full screen}
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table id="user-content-header"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;
&lt;p&gt;&lt;a href="https://apps.apple.com/us/app/improved-tube/id1672777754" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/12d5bb398a5eaad1b8fd7dfa67d2607cc315314117c497f366823aa95e6dead1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2532302d5361666172692d77686974653f6c6f676f3d736166617269266c6f676f436f6c6f723d626c61636b"&gt;&lt;/a&gt;  &lt;a href="https://store.whale.naver.com/detail/npfgdbojchpofhjdleehaoddbmbonbpa" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/516c184192a7a2e40b71d6002fcd2c1b59df08bede8f71667efe7f3206b7be2b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2532302d5768616c652d77686974653f266c6f676f436f6c6f723d7768697465266c6f676f3d646174613a696d6167652f706e673b6261736536342c6956424f5277304b47676f414141414e53556845556741414143414141414167434159414141427a656e72304141414853456c4551565159475a5842653279645a52334138652f76665a397a36376d30362b5730335a56326d347a4a4c69344f51534a522f73434151675155495153694349354969496b59304768417855426b476f326141437247674970475553516d784552425359774556494934324b42686a6c334b6474617550646633386a7a507a35367849573764566a346673327a64585277766730674f4a494e49426a416747595177514d4b7a5144594159304176623267414f3047665239307a69724e6f436c685555394155315268494f5a62686c415351746144584b2f5979314b376743424777715563434951774535624464774b4d6750774c35463664674f436b5a4250384e534b39444535517535536a6e6f466a4d594b306e535277534d4565574364774d636a506f67784238415a6a6b42417a7a45755a38444c5550714b5a6c554f597a4d784e783655587265586c696d6d662b7559394b4f5564714859454959526967797255675677413367507955655267516a716566563032336775656f4942436932434a414c6d667758756d72434c2f2f777a6138563070464a5537615641654b5248464b71783054424d4b635041515041574d676433494d6b336d747857465763534d355843587a4f62484a566f3752365667576a31525168646350314d6c6d445946414843754251424149596143304f30326355305138654a4459496246484c462f54514c535764723765626e513479737838636752556f5a49682b2b7a734a626b5847392f7946594f71306955696443564a52434666515553774e695a6a504f306f705a445049434a3456594a41364551705954306c4f355767755141375771413561706a4f7864424f3733783364664845423961663967754f4d4e4e337259474d674446395131632b2f5474706450446c5047456769416a576572777131614543722b3035534b736455796e6e41636671385558736e5a7a467130496f4241646a736c4d78795a6d394e4b35595157667a49714a6c436f4e354c6870617a6a58354a58796b734f5468504477424847434f5956384535517779325867673939496866432b344e4b62535679536244646c666135416d6c6f5a5036656e4a676759346c78494751716654416247493957516d6d71517279787a36346a7161467939426c2b65684e63745a7273703365742f4a4f6652796c46502f45504242356867555546614a366d5634692b4977786c4276746b444270516b72783674593639693165347043506b75583837447634417946757358733731442f7845716d62312b504c692f425a41753254624a6c594333336a57366b797a755052546e69416d416438494b684b334b332b4f454336564357334f7374664939776d45436e4537466b6353394a596e6c3559682f356645695868674539753576346f7548412f652b6839616e5663436942485856776461345a574d4e396f7876425138656c434d6535566545614134516b2f6b715746576d665636583435463773534235786e71372b77524a502f47556267516a3969346f3437384572756532486944594f555076782b374162426d426e4856494633325a6c6f637144493576414b55325849737a726375414741327847364f4e415250505461796a39396a2f6b586a7045737159507352356e4c6156696c6936484a35694e4d5875624e44362b696f50665077637157646778413646416f4f413850786859523163396a5245526c486b5667484d4e734a6d753251526458754c41672b396e2b4b6f2f6b582b68527271346842597a49434374464c4f766a5233746f66627463326a6574425a6942337561494149497043334f4c69336a2f474b566468796a674b70794570734d4d455a584b4c437267567654782b546a46374a6f362f4d556e706f6b714555495949634b4e4338646f3337393662674e673743334351374947516773704235452b4770354444783076434d513452535747714445555361416e5856304d4d2f303938354664737867646a5951685853386a4a376542374d4a544d7a436f4b4636355461436a756631333679446d53617273304e636b4b2f5354447567696c666c46486f4d6e76385842444356774853436c724f6b377833687347594b7239524241535067517a5349304e43424479473133466865416b464979316f4368495577346d6879496e554c64637478596f566151753365643445415532324d4c334646766b715352714467555261675a6243384b734c625a785642414d45333233796f6635796c32544b54535a4f3359612f52314436725155676f416143636b484b386a73634c6f434658397779444f707771776f4c397731786357667a3350395a724d354633666145454b41736e417070476a425547754b5130524331706f366f6f433949422f6d724f372b6c3365317174587a37587247325262423555655a4d4143675142694841734653424f32544b386d4679516f5a6c476841674c394373674e6f30305a564f2b3873336e706d70626e45384a526667664251537949636353494c457070577776312f614f4d4a323045515750736b44334d4d664d784447726338574a74626e4b49793865716c326579526451565544416538686d51515738386c5971416c484d6a645678526e4d4658756b30434245573648466747334f4d574b574435634a46773964746e35712b5047354635444d5a31486b49425049474c4b4338535944497876526b5333783261436d3175494d6f654a51467570596a544e555970744b5569736e557a2b736676767250753137396d5373496f66646f75515145594431484365414661456663736d6f3153374d46746e63616841674c644431776b43504d6243506c7245714a4d346f39334c353078633976792b54666363384c7a392f42344342687467434a4134517559593449536250422b7346527672786b426275694e714c6755526267486b51653443334d33524e374f4b306e7a345a4b6b6333397653516d3935584b34504336646935336d5351656c4d4d45554245367a53624478544b5072546d54794473617a6d4a45574943747747326f386c616d6b416e5a47556673334e2f6b30636d396b4d7665564f6f706e5a647a4472564b6c346a51736862614863376f583853764e3279676d736e776372744e4a676a7771707945416a63464976637944784d41785443455444696d6b767375384745665777515151494449575843657a3479506338657163584969374769337959696771707a4549774b33697369726e494142567144636a6563713452674b6b66654e6e41512f65586a6a57767652306547726437553731583357596b5251356e555165417a346f6344546e494942596c476577724d643641574b674166324932797a547038634b47536d4e7657573264317566326e5775724e44574b2b7153344579623267436534422f432f774e6b52594c3946386262566d78634c3959616741414141424a52553545726b4a6767673d3d"&gt;&lt;/a&gt; &lt;a href="https://chrome.google.com/webstore/detail/improve-youtube-video-you/bnomihfieiccainjcjblhegjgglakjdd" rel="nofollow noopener noreferrer"&gt;
&lt;/a&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/youtube-addon/" title="Firefox recommends only 109 extensions" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/18bd43f6d9ddf0b48c2b2c9d68f658c7c42b125b94283ed0d959ea685d6e1b7d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2532302d46697265666f782d77686974653f6c6f676f3d66697265666f7862726f77736572266c6f676f436f6c6f723d6f72616e6765"&gt;&lt;/a&gt;  &lt;a href="https://chrome.google.com/webstore/detail/improve-youtube-video-you/bnomihfieiccainjcjblhegjgglakjdd" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/52ef21dd059f37d887001884ac1ff65ab7ed3ea7b1c9cfcb41c2277f46713bdb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2532302d4368726f6d652d77686974653f6c6f676f3d676f6f676c656368726f6d65266c6f676f436f6c6f723d6c6967687467726579"&gt;&lt;/a&gt;
&lt;a href="https://microsoftedge.microsoft.com/addons/detail/improve-youtube-video-/knbckijjjbmkjiagojjneoplbjilfllc" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/30753bc29bfccfb6fe13428d95abc4a8fcf7252ddfb4d8e263f52cb68de8f8a5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f253230456467652532302532302d77686974653f6c6f676f3d6d6963726f736f667465646765266c6f676f436f6c6f723d7465616c"&gt;&lt;/a&gt;
(&lt;a href="https://addons.opera.com/de/extensions/details/improvedtube-youtube-extension/" rel="nofollow noopener noreferrer"&gt;&lt;img height="12px" src="https://camo.githubusercontent.com/1ab5ec5552615b34ef2ee29b0ee2d212c594a7a41b6b7613f0316918798e22f5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2532302d4f706572612d77686974653f6c6f676f3d6f70657261266c6f676f436f6c6f723d726564"&gt;&lt;/a&gt;)&lt;a href="https://github.com/code-for-charity/ImprovedTube-for-YouTube/releases/latest" title="Release.zip" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcode-charity%2Fyoutubegithub.png" height="18px"&gt; &lt;/a&gt; &lt;br&gt; &lt;a href="https://github.com/code-charity/youtube/issues/new?assignees=&amp;amp;labels=Bug%2C+good+first+issue%2C+help+wanted%2C+up-for-grabs&amp;amp;projects=&amp;amp;template=bug_report.md&amp;amp;title=" rel="noopener noreferrer"&gt;Report a bug&lt;/a&gt; ·
&lt;a href="https://github.com/code-for-charity/ImprovedTube-for-YouTube/issues/new?assignees=&amp;amp;labels=Feature+request%2C+help+wanted&amp;amp;template=feature-request---suggestion---idea.md&amp;amp;title=" rel="noopener noreferrer"&gt;Wish a feature&lt;/a&gt; ·
&lt;a href="https://github.com/code-for-charity/ImprovedTube-for-YouTube/wiki/Contributing" rel="noopener noreferrer"&gt;Contribute&lt;/a&gt; ·
&lt;a href="https://github.com/code-for-charity/ImprovedTube-for-YouTube/wiki/Contributing#donate" rel="noopener noreferrer"&gt;Donate&lt;/a&gt; · &lt;a href="https://github.com/code-for-charity/ImprovedTube-for-YouTube/archive/refs/heads/master.zip" title="Latest.zip" rel="noopener noreferrer"&gt;Test🧪&lt;/a&gt;  &lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/code-for-charity/ImprovedTube-for-YouTube/blob/a61f214ddfab91f0a29f41beaf6c3c52e738e0d7/assets/icons/32.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcode-for-charity%2FImprovedTube-for-YouTube%2Fraw%2Fa61f214ddfab91f0a29f41beaf6c3c52e738e0d7%2Fassets%2Ficons%2F32.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;&lt;code&gt;/ImprovedTube/&lt;/code&gt;&lt;/b&gt; a powerful but lightweight extension, &lt;br&gt; to enrich your video experience &amp;amp; enable your content selection
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Top &lt;a href="https://addons.mozilla.org/en-US/firefox/search/?page=3&amp;amp;type=extension" rel="nofollow noopener noreferrer"&gt;50&lt;/a&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/youtube-addon/" title="(We started late on Firefox, yet are among their few recommentations and featured on about:addons)" rel="nofollow noopener noreferrer"&gt;&lt;img width="140" alt="recommended by firefox" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F9015764%2F178100681-728b9513-b6f8-4bf7-8949-c3d8449669ec.svg"&gt;&lt;/a&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/youtube-addon/" title="(We started late on Firefox, yet are among their ~100 recommentations)" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/c4bcaf866cb99abd4cff720b5cea82aef6c9f5ec25b727456d8e20997c09501e/68747470733a2f2f7777772e6d6f7a696c6c612e6f72672f6d656469612f70726f746f636f6c2f696d672f6c6f676f732f66697265666f782f62726f777365722f6c6f676f2e6562313332346534343434322e737667" height="19px"&gt;&lt;/a&gt;&lt;a href="https://lifehacker.com/this-might-be-the-only-youtube-browser-extension-youll-1846575110" title="- Lifehacker.com 2021" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8b330b4c5c5d11c479b8a82169fafe7dc0095c726867b01020162a542b49e506/68747470733a2f2f6c6966656861636b65722e636f6d2f66617669636f6e2e69636f" height="19px"&gt;&lt;/a&gt; &lt;a href="https://www.ghacks.net/2021/03/26/improved-youtube-enhances-youtube-in-meaningful-ways" title="- gHacks.net" rel="nofollow noopener noreferrer"&gt;g&lt;/a&gt; &lt;a href="https://www.chip.de/downloads/Improve-YouTube-fuer-Chrome_183480435.html" title="- Chip.de" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/7464fa29eed3412a2194849d56722c620e5089539292cdc0b0b61f8658a226e0/68747470733a2f2f7777772e636869702e64652f66617669636f6e2e69636f" height="15px"&gt;&lt;/a&gt;
&lt;i&gt;'Might &lt;br&gt; be the only YouTube Extension you'll ever need' &lt;br&gt; 'enhances YouTube in meaningful ways'  &lt;br&gt; 'Strong Add-on, full control. Yet clear &amp;amp; easy' &lt;/i&gt;
&lt;br&gt; Thanks ♡ to our &lt;a href="https://github.com/ImprovedTube/ImprovedTube/graphs/contributors" rel="noopener noreferrer"&gt;c&lt;/a&gt;ontributors, &lt;a href="https://github.com/dodieboy" title="🏅" rel="noopener noreferrer"&gt;A&lt;/a&gt;lan Tan, &lt;a href="https://github.com/raszpl" title="🏅" rel="noopener noreferrer"&gt;R&lt;/a&gt;aszpl
&lt;br&gt;&lt;a href="https://github.com/code-for-charity/YouTube-Extension#--translators-" rel="noopener noreferrer"&gt;t&lt;/a&gt;ranslators (+ wiki-authors? +&lt;a href="https://improvedtube.com/donate" rel="nofollow noopener noreferrer"&gt;d&lt;/a&gt;onators?)&lt;a href="https://improvedtube.com/donate" rel="nofollow noopener noreferrer"&gt;&lt;img class="emoji" title=":bowtie:" alt=":bowtie:" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.githubassets.com%2Fimages%2Ficons%2Femoji%2Fbowtie.png" height="20" width="20"&gt;&lt;/a&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;br&gt;
&lt;div&gt;  &lt;/div&gt; 
Original introduction &lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;
«Improve YouTube!»    &lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;b&gt;
&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;code&gt;/ImprovedTube/&lt;/code&gt;&lt;/b&gt; is a strong &amp;amp; lightweight extension! - 80 features / the only one of a kind!&lt;/p&gt;
Since 2012 we have gradually been adding lightweight features, while keeping up with Youtube changes.
(throughout the years we witnessed the birth &amp;amp; fall of other promising &amp;amp; open YouTube Extensions &lt;a href="https://github.com/YePpHa/YouTubeCenter" title="YouTubeCenter" rel="noopener noreferrer"&gt;1&lt;/a&gt;, &lt;a href="https://github.com/ParticleCore/Iridium" title="Iridium" rel="noopener noreferrer"&gt;2&lt;/a&gt;, ... )
Today adding features can be easier &amp;amp; so motivating as there are 500 000 users. &lt;a href="https://github.com/code-for-charity/YouTube-Extension/discussions/1006" title="github.com/Code-for-Charity" rel="noopener noreferrer"&gt;[👪Join us]&lt;/a&gt;. …&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/code-charity/youtube" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Currently, I've been researching a &lt;em&gt;family of related issues&lt;/em&gt; pertaining to &lt;code&gt;ImprovedTube's&lt;/code&gt; &lt;code&gt;Cinema Mode&lt;/code&gt; setting. &lt;code&gt;Cinema Mode&lt;/code&gt; is a neat feature that hides all of the clutter on YouTube as you're watching a video. &lt;/p&gt;

&lt;p&gt;In the screenshot below, you can see that on the top-right, &lt;code&gt;ImprovedTube&lt;/code&gt; provides a &lt;em&gt;switch&lt;/em&gt; that lets you enable the &lt;code&gt;Cinema Mode&lt;/code&gt; &lt;em&gt;button&lt;/em&gt; shown on the YouTube player (NOTE: whenever I say switch, I am referring to the setting at the top-right, whenever I say button, I am referring to what's on the YouTube player).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqqaj7tzbqviv6jlrt2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqqaj7tzbqviv6jlrt2s.png" alt="cinema-mode" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If I actually press on the &lt;code&gt;Cinema Mode&lt;/code&gt; &lt;em&gt;button&lt;/em&gt;, you'll notice that many things disappear - video suggestions, comments, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfafglx68wlfq9w4q50e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfafglx68wlfq9w4q50e.png" alt="cinema-mode-in-use" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This feature is really neat! But as I was testing this feature personally, I noticed some inconsistencies with how the extension behaved. The most apparent inconsistency was that I expected to see the &lt;code&gt;Cinema Mode&lt;/code&gt; button &lt;em&gt;disappear&lt;/em&gt; if I disabled the &lt;code&gt;Cinema Mode&lt;/code&gt; switch, and similarly, I expected the &lt;code&gt;Cinema Mode&lt;/code&gt; button to &lt;em&gt;appear&lt;/em&gt; if I toggle the &lt;code&gt;Cinema Mode&lt;/code&gt; switch &lt;em&gt;on&lt;/em&gt;. Long story short - the toggle switch wasn't working as expected. Whenever I tried to disable the &lt;code&gt;Cinema Mode&lt;/code&gt; switch, I noticed that the YouTube Player button still persisted. I was confident that this was not the expected behaviour either since ImprovedTube's other toggle switches would cause their respective buttons to appear or disappear accordingly. As such, I logged this issue: &lt;a href="https://github.com/code-charity/youtube/issues/2700" rel="noopener noreferrer"&gt;https://github.com/code-charity/youtube/issues/2700&lt;/a&gt; (you can see exactly what I mean because I posted a video showcasing the issue). &lt;/p&gt;

&lt;p&gt;I noticed that there was a lot of "buzz" around the &lt;code&gt;Cinema Mode&lt;/code&gt; option in general(you can see that I linked some other related issues and pull requests), and so on the particular issue that I logged, I wanted to be very specific as to what I thought was wrong, and what I thought should be changed.&lt;/p&gt;

&lt;p&gt;I volunteered to fix the issue that I brought up because I think that I had a clear expectation on how this issue should look like once it's been resolved. I also logged this issue to help me get into the flow of trying to fix some of the other issues related to the &lt;code&gt;Cinema Mode&lt;/code&gt; setting. While I haven't exactly figured out the exact expected behaviour of the other issues yet, I will carefully review them later.&lt;/p&gt;

&lt;p&gt;For now, I'll leave you with the pull request that I made, which hopefully, fixes the weird behaviour I stated in my issue: &lt;a href="https://github.com/code-charity/youtube/pull/2701" rel="noopener noreferrer"&gt;https://github.com/code-charity/youtube/pull/2701&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>extensions</category>
      <category>github</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Learning by Doing: working on ImprovedTube</title>
      <dc:creator>Peter Wan</dc:creator>
      <pubDate>Fri, 29 Nov 2024 02:54:44 +0000</pubDate>
      <link>https://dev.to/peterdanwan/learning-by-doing-working-on-improvedtube-4pbe</link>
      <guid>https://dev.to/peterdanwan/learning-by-doing-working-on-improvedtube-4pbe</guid>
      <description>&lt;p&gt;Hi! &lt;/p&gt;

&lt;p&gt;This blog a mental note about how I want to start learning about browser extensions by contributing to &lt;a href="https://github.com/code-charity/youtube" rel="noopener noreferrer"&gt;ImprovedTube&lt;/a&gt;, a well known browser extension that enhances your experience on YouTube. &lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Install ImprovedTube on &lt;a href="https://chromewebstore.google.com/detail/improve-youtube-%F0%9F%8E%A7-for-yo/bnomihfieiccainjcjblhegjgglakjdd" rel="noopener noreferrer"&gt;Chrome&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Install ImprovedTube on &lt;a href="https://addons.mozilla.org/en-CA/firefox/addon/youtube-addon/" rel="noopener noreferrer"&gt;Firefox&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've always wanted to learn more about browser extensions, but never found myself in a position where I had the &lt;em&gt;time&lt;/em&gt; to do so. Fortunately, one of the courses I'm currently taking - &lt;a href="https://github.com/humphd/topics-in-open-source-2024" rel="noopener noreferrer"&gt;Topics in Open Source 2024&lt;/a&gt;, has presented an opportunity for me to work on projects that I'm actually interested in. For me right now, that is browser extension development.&lt;/p&gt;

&lt;p&gt;I chose browser extension development because I wanted to use and refine the existing skillset I have with regards to Web Development (i.e., knowledge of HTML, JavaScript, and CSS). Browser extensions from what I have seen, lets me make use of all of the skills that I built so far with regards to web development, but won't necessarily force me to build a whole web app or web page by myself. From my experience, I find that most extensions that I use such as adblockers or light mode/dark mode extensions really adjust the content of &lt;em&gt;existing web pages&lt;/em&gt;. By working on extensions that manipulate &lt;em&gt;existing web pages&lt;/em&gt;, I hope to learn more about how websites like YouTube are structured by directly controlling some of the elements that they provide.&lt;/p&gt;

&lt;p&gt;I was particularly drawn to ImprovedTube because it lets me customize my experience on YouTube - something I use on a daily basis. I &lt;em&gt;know&lt;/em&gt; that if I work on ImprovedTube and if my changes get accepted, that I will feel immensely rewarded.&lt;/p&gt;

&lt;h2&gt;
  
  
  My plan of attack for learning about extensions in general
&lt;/h2&gt;

&lt;p&gt;As &lt;a href="https://dev.to/peterdanwan/working-on-a-browser-extension-40bc"&gt;mentioned in one of my previous blogs&lt;/a&gt;, I initially was going to peruse Mozilla's documentation on cross-browser development. However, I never really got to doing their particular examples. Instead, I've begun working through some examples from Chrome's guide instead:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://developer.chrome.com/docs/extensions/get-started" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gstatic.com%2Fdevrel-devsite%2Fprod%2Fv870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625%2Fchrome%2Fimages%2Flockup.svg" height="745" class="m-0" width="5838"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://developer.chrome.com/docs/extensions/get-started" rel="noopener noreferrer" class="c-link"&gt;
          Extensions / Get started  |  Chrome for Developers
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          All the basics to get started with Chrome extensions
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.gstatic.com%2Fdevrel-devsite%2Fprod%2Fv870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625%2Fchrome%2Fimages%2Ffavicon.png" width="32" height="32"&gt;
        developer.chrome.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;You can kind of see that I have a little note-taking thing here going on:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F161k9bw667xlchanthft.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F161k9bw667xlchanthft.png" alt="my-notes" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without diving too much into the details, I plan on reading through this documentation and getting a hands-on feel for how things work. The great thing about browser extension development for me so far is that I get &lt;em&gt;immediate feedback&lt;/em&gt; from the changes I make to the browser extension code. I plan on completing the rest of the Getting Started section from Chrome's documentation, while constantly looking back at ImprovedTube's code to see how they make use of these concepts in their own extension.&lt;/p&gt;

&lt;h2&gt;
  
  
  The family of issues I think would be good for me to tackle on ImprovedTube
&lt;/h2&gt;

&lt;p&gt;At the time of writing, I've been working on this particular &lt;a href="https://github.com/code-charity/youtube/pull/2684" rel="noopener noreferrer"&gt;pull request&lt;/a&gt;, that aims to hide a link that appears on videos and video cards on YouTube. After working on this issue (even though it hasn't been accepted yet), I think I have a decent grasp on what files I need to modify to see the desired changes.&lt;/p&gt;

&lt;p&gt;The particular family of issues I think I'd be able to handle would be any issues regarding &lt;em&gt;hiding&lt;/em&gt; something from YouTube that users don't want to see.&lt;/p&gt;

&lt;p&gt;In fact, I might ask the maintainers if they'd be open to me writing some documentation for them so that it will be easier for new open source contributors to add features like this themselves. &lt;/p&gt;

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

&lt;p&gt;I still have lots to learn about Browser Extensions and ImprovedTube, but I'll try to learn more about both by &lt;em&gt;doing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That's all from me, see you next time!&lt;/p&gt;

</description>
      <category>extensions</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Re-publishing gimme_readme to npm with GitHub Actions</title>
      <dc:creator>Peter Wan</dc:creator>
      <pubDate>Fri, 22 Nov 2024 18:58:52 +0000</pubDate>
      <link>https://dev.to/peterdanwan/re-publishing-gimmereadme-to-npm-with-github-actions-23cd</link>
      <guid>https://dev.to/peterdanwan/re-publishing-gimmereadme-to-npm-with-github-actions-23cd</guid>
      <description>&lt;p&gt;This week in my Open Source class, my classmates and I were tasked with publishing each of our own programs to a &lt;code&gt;package registry&lt;/code&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When you hear someone say &lt;code&gt;code registry&lt;/code&gt;, &lt;code&gt;package registry&lt;/code&gt;, or &lt;code&gt;registry&lt;/code&gt;, I like to think of these words as representing a place where developers and companies publish their code for others to download. For a more accurate description, you can read this article by Mozilla:&lt;/p&gt;
&lt;/blockquote&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Package_management#package_registries" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.mozilla.org%2Fmdn-social-share.d893525a4fb5fb1f67a2.png" height="450" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Package_management#package_registries" rel="noopener noreferrer" class="c-link"&gt;
          Package management basics - Learn web development | MDN
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          This brings us to the end of our tour of package managers. Our next move is to build up a sample toolchain, putting all that we've learnt so far into practice.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.mozilla.org%2Ffavicon-48x48.bc390275e955dacb2e65.png" width="48" height="48"&gt;
        developer.mozilla.org
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Why download code from a registry? Why not just go to GitHub?
&lt;/h2&gt;

&lt;p&gt;Individuals familiar with GitHub might wonder, "Why should I even &lt;em&gt;bother&lt;/em&gt; posting my tool to a registry? Why not have my users go to GitHub, clone my repository, install the necessary dependencies, build the intermediary files, and run my program?".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Long story short: developers publish their code to registries to make it &lt;em&gt;easy&lt;/em&gt; for end users to use their programs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With that little introduction on why we publish code to registries, let me tell you my process of publishing my JavaScript tool, &lt;a href="https://github.com/peterdanwan/gimme_readme" rel="noopener noreferrer"&gt;gimme_readme&lt;/a&gt; to the &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm registry&lt;/a&gt; which was built to host JavaScript code.&lt;/p&gt;

&lt;p&gt;You can download my code by visiting its &lt;code&gt;npm registry link&lt;/code&gt; below:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.npmjs.com/package/gimme_readme" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic-production.npmjs.com%2F338e4905a2684ca96e08c7780fc68412.png" height="420" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.npmjs.com/package/gimme_readme" rel="noopener noreferrer" class="c-link"&gt;
          gimme_readme - npm
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          gimme_readme is a command-line tool powered by AI that generates a comprehensive README.md file for your project. It analyzes multiple source code files at once, providing concise explanations of each file's purpose, functionality, and key components, all. Latest version: 1.0.0, last published: 16 hours ago. Start using gimme_readme in your project by running `npm i gimme_readme`. There are no other projects in the npm registry using gimme_readme.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic-production.npmjs.com%2Fb0f1a8318363185cc2ea6a40ac23eeb2.png" width="32" height="32"&gt;
        npmjs.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Re-publishing my code to npm
&lt;/h2&gt;

&lt;p&gt;As mentioned in the title of this article, I have already published my code to &lt;code&gt;npm&lt;/code&gt; before, and this time around, I was &lt;em&gt;re-publishing&lt;/em&gt; my code with new features that weren't included in a previous release.&lt;/p&gt;

&lt;p&gt;In addition to publishing the new features that my code has, I also wanted to ensure my end users systems weren't bloated with any extra files from my program.&lt;/p&gt;

&lt;p&gt;Here is a picture that shows what my users are &lt;em&gt;currently&lt;/em&gt; getting when they download &lt;code&gt;gimme_readme&lt;/code&gt;, following the instructions on the `npm registry:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flp61t96csuq7rwzjq635.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flp61t96csuq7rwzjq635.png" alt="gimme_readme-downloaded-from-npm" width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see above, there are a lot of folders and files that are unnecessary for a &lt;em&gt;user&lt;/em&gt; to have (as opposed to a developer). For example, do you think my users would want my "tests" folder to test my program's code? &lt;em&gt;Probably not&lt;/em&gt;. Do you think my users need the config files needed to format and lint my source code? &lt;em&gt;Probably not&lt;/em&gt;. Do you think my users would need to use my  ".github" folder for any particular reason? &lt;em&gt;Probably not&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To this end, I have been working to find a solution to minimize what is downloaded by a user; specifically, I want them to only have the &lt;em&gt;source code&lt;/em&gt; needed for my program to run.&lt;/p&gt;

&lt;h2&gt;
  
  
  To &lt;code&gt;.npmignore&lt;/code&gt; or to not &lt;code&gt;.npmignore&lt;/code&gt;? That is the question.
&lt;/h2&gt;

&lt;p&gt;As I was thinking about re-publishing my code, I was also talking with my friend &lt;a href="https://github.com/uday-rana" rel="noopener noreferrer"&gt;Uday Rana&lt;/a&gt;, about the idea of using a &lt;code&gt;.npmignore&lt;/code&gt; file to "ignore" files I didn't want to publish. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Literally right after I mentioned the topic&lt;/em&gt;, Uday Googled &lt;code&gt;.npmignore&lt;/code&gt;, and found an &lt;a href="https://medium.com/@jdxcode/for-the-love-of-god-dont-use-npmignore-f93c08909d8d" rel="noopener noreferrer"&gt;article&lt;/a&gt; written by &lt;a href="https://medium.com/@jdxcode" rel="noopener noreferrer"&gt;Jeff D&lt;/a&gt; on why one should &lt;em&gt;never&lt;/em&gt; use a &lt;code&gt;.npmignore&lt;/code&gt; file. To be clear, I wholeheartedly agree with Jeff's article.&lt;/p&gt;

&lt;p&gt;Essentially, the idea is that we should be &lt;em&gt;explicit&lt;/em&gt; with what we &lt;em&gt;want&lt;/em&gt; to publish (whitelisting), as opposed to stating which files we &lt;em&gt;don't&lt;/em&gt; want to publish (blacklisting).&lt;/p&gt;

&lt;p&gt;Whitelisting the files we wish to publish is simple with &lt;code&gt;npm&lt;/code&gt;. All we need to do is edit our &lt;code&gt;package.json&lt;/code&gt; file by adding a "files" option, that indicates which files we want to publish for our program.&lt;/p&gt;

&lt;p&gt;Below, I've taken a screenshot of &lt;code&gt;package.json's&lt;/code&gt; "files" option, which states, "include the src/ directory when publishing this program". I have since committed these changes and these changes are available in my &lt;code&gt;v1.0.0&lt;/code&gt; release of my code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkh6d2s1ovijnkbdbxv9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkh6d2s1ovijnkbdbxv9f.png" alt="files-field-package.json" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: Certain files by default, are &lt;em&gt;always&lt;/em&gt; published to &lt;code&gt;npm&lt;/code&gt;, regardless of what you specify or don't specify in your "files" option. If you want to learn more about how to use the "files" option, check out &lt;a href="https://docs.npmjs.com/cli/v10/configuring-npm/package-json" rel="noopener noreferrer"&gt;npm's official documentation on how to use the file option&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After publishing my code to &lt;code&gt;npm&lt;/code&gt; with my updated &lt;code&gt;package.json&lt;/code&gt;, users that install/re-install &lt;code&gt;gimme_readme&lt;/code&gt; will now have a lot less bloat on their computers! See the difference below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flnie0t41mbaawrarl9m7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flnie0t41mbaawrarl9m7.gif" alt="less-bloat" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding a GitHub action to publish my code to &lt;code&gt;npm&lt;/code&gt; when I add a new release
&lt;/h2&gt;

&lt;p&gt;Besides enhancing the experience of my users (by reducing the bloat that comes from installing &lt;code&gt;gimme_readme&lt;/code&gt; via npm), I also added a &lt;code&gt;continuous development pipeline&lt;/code&gt; (&lt;code&gt;cd pipeline&lt;/code&gt; for short) that would automate my publishing process to &lt;code&gt;npm&lt;/code&gt; when I make a new &lt;a href="https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases" rel="noopener noreferrer"&gt;release&lt;/a&gt; on &lt;code&gt;GitHub&lt;/code&gt;. For exact details on how to do this, you can refer to &lt;a href="https://docs.github.com/en/actions/use-cases-and-examples/publishing-packages/publishing-nodejs-packages#publishing-packages-to-the-npm-registry" rel="noopener noreferrer"&gt;GitHub's Publishing Node.js packages guide&lt;/a&gt;. This feels good now, because at the click of a few buttons, I'm able to publish code that I know is stable (according to my CI pipeline), &lt;em&gt;from&lt;/em&gt; GitHub. &lt;/p&gt;

&lt;p&gt;You can find the code for my &lt;code&gt;cd&lt;/code&gt; pipeline &lt;a href="https://github.com/peterdanwan/gimme_readme/blob/main/.github/workflows/cd.yml" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing with Uday
&lt;/h2&gt;

&lt;p&gt;As I mentioned earlier, I was working with my friend, &lt;a href="https://github.com/uday-rana" rel="noopener noreferrer"&gt;Uday Rana&lt;/a&gt;, with regards to testing. At the time of writing, he was able to install my tool, and use it like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo295ursjbw8bwfnqcsfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo295ursjbw8bwfnqcsfz.png" alt="test-with-uday" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Things look good to me, and most of the options I have for my tool more or less behave the way he expects. But I'll have to repeat this process again, because I have some further optimizations I want to add!&lt;/p&gt;

&lt;h2&gt;
  
  
  The journey never ends... but that's what makes it fun!
&lt;/h2&gt;

&lt;p&gt;I have also recently heard of ways to optimize my code further. Particularly, I'm invested in learning how to improve my &lt;code&gt;CI&lt;/code&gt; and &lt;code&gt;CD&lt;/code&gt; pipelines by learning about &lt;a href="https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-composite-action" rel="noopener noreferrer"&gt;composite actions&lt;/a&gt;, and &lt;a href="https://docs.github.com/en/actions/sharing-automations/reusing-workflows" rel="noopener noreferrer"&gt;reusable workflows&lt;/a&gt; with regards to GitHub actions. My hope is that these techniques will help me reduce the amount of code I write, and offer some type of performance boost! I don't know much about these topics yet, but you can bet I will probably blog about it soon.&lt;/p&gt;

&lt;p&gt;And that my friends, concludes what I wanted to talk about in this blog.&lt;/p&gt;

&lt;p&gt;See you next time!&lt;/p&gt;

</description>
      <category>github</category>
      <category>javascript</category>
      <category>githubactions</category>
      <category>npm</category>
    </item>
    <item>
      <title>Working on a browser extension</title>
      <dc:creator>Peter Wan</dc:creator>
      <pubDate>Thu, 21 Nov 2024 00:37:14 +0000</pubDate>
      <link>https://dev.to/peterdanwan/working-on-a-browser-extension-40bc</link>
      <guid>https://dev.to/peterdanwan/working-on-a-browser-extension-40bc</guid>
      <description>&lt;p&gt;This week, I wanted to look for an open-source project that I could use on a daily basis &lt;em&gt;and&lt;/em&gt; where I could myself contributing a lot to &lt;em&gt;going forward&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Lucky for me, I stumbled upon the &lt;a href="https://chromewebstore.google.com/detail/improve-youtube-%F0%9F%8E%A7-for-yo/bnomihfieiccainjcjblhegjgglakjdd" rel="noopener noreferrer"&gt;ImprovedTube&lt;/a&gt; extension and found its GitHub repository, shown below:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/code-charity" rel="noopener noreferrer"&gt;
        code-charity
      &lt;/a&gt; / &lt;a href="https://github.com/code-charity/youtube" rel="noopener noreferrer"&gt;
        youtube
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      [top~1 open YouTube &amp;amp; Video browser-extension] - Enrich your experience &amp;amp; choice! 🧰180+ options &amp;amp; clever features 📌set+forget📌Longest-standing(been tough). Please join🧩us👨‍👩‍👧‍👧 ..⋮ {playback|content discovery|player|extra buttons|distractions|related videos|shorts|ads|quality|codec|full tab|full screen}
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table id="user-content-header"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;
&lt;p&gt;&lt;a href="https://apps.apple.com/us/app/improved-tube/id1672777754" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/12d5bb398a5eaad1b8fd7dfa67d2607cc315314117c497f366823aa95e6dead1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2532302d5361666172692d77686974653f6c6f676f3d736166617269266c6f676f436f6c6f723d626c61636b"&gt;&lt;/a&gt;  &lt;a href="https://store.whale.naver.com/detail/npfgdbojchpofhjdleehaoddbmbonbpa" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/516c184192a7a2e40b71d6002fcd2c1b59df08bede8f71667efe7f3206b7be2b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2532302d5768616c652d77686974653f266c6f676f436f6c6f723d7768697465266c6f676f3d646174613a696d6167652f706e673b6261736536342c6956424f5277304b47676f414141414e53556845556741414143414141414167434159414141427a656e72304141414853456c4551565159475a5842653279645a52334138652f76665a397a36376d30362b5730335a56326d347a4a4c69344f51534a522f73434151675155495153694349354969496b59304768417855426b476f326141437247674970475553516d784552425359774556494934324b42686a6c334b6474617550646633386a7a507a35367849573764566a346673327a64585277766730674f4a494e49426a416747595177514d4b7a5144594159304176623267414f3047665239307a69724e6f436c685555394155315268494f5a62686c415351746144584b2f5979314b376743424777715563434951774535624464774b4d6750774c35463664674f436b5a4250384e534b39444535517535536a6e6f466a4d594b306e535277534d4565574364774d636a506f67784238415a6a6b42417a7a45755a38444c5550714b5a6c554f597a4d784e783655587265586c696d6d662b7559394b4f5564714859454959526967797255675677413367507955655267516a716566563032336775656f4942436932434a414c6d667758756d72434c2f2f777a6138563070464a5537615641654b5248464b71783054424d4b635041515041574d676433494d6b336d747857465763534d355843587a4f62484a566f3752365667576a31525168646350314d6c6d445946414843754251424149596143304f30326355305138654a4459496246484c462f54514c535764723765626e513479737838636752556f5a49682b2b7a734a626b5847392f7946594f71306955696443564a52434666515553774e695a6a504f306f705a445049434a3456594a41364551705954306c4f355767755141375771413561706a4f7864424f3733783364664845423961663967754f4d4e4e337259474d674446395131632b2f5474706450446c5047456769416a576572777131614543722b3035534b736455796e6e41636671385558736e5a7a467130496f4241646a736c4d78795a6d394e4b35595157667a49714a6c436f4e354c6870617a6a58354a58796b734f5468504477424847434f5956384535517779325867673939496866432b344e4b62535679536244646c666135416d6c6f5a5036656e4a676759346c78494751716654416247493957516d6d71517279787a36346a7161467939426c2b65684e63745a7273703365742f4a4f6652796c46502f45504242356867555546614a366d5634692b4977786c4276746b444270516b72783674593639693165347043506b75583837447634417946757358733731442f7845716d62312b504c692f425a41753254624a6c594333336a57366b797a755052546e69416d416438494b684b334b332b4f454336564357334f7374664939776d45436e4537466b6353394a596e6c3559682f356645695868674539753576346f7548412f652b6839616e5663436942485856776461345a574d4e396f7876425138656c434d6535566545614134516b2f6b715746576d665636583435463773534235786e71372b77524a502f47556267516a3969346f3437384572756532486944594f555076782b374162426d426e4856494633325a6c6f637144493576414b55325849737a726375414741327847364f4e415250505461796a39396a2f6b586a7045737159507352356e4c6156696c6936484a35694e4d5875624e44362b696f50665077637157646778413646416f4f413850786859523163396a5245526c486b5667484d4e734a6d753251526458754c41672b396e2b4b6f2f6b582b68527271346842597a49434374464c4f766a5233746f66627463326a6574425a6942337561494149497043334f4c69336a2f474b566468796a674b70794570734d4d455a584b4c437267567654782b546a46374a6f362f4d556e706f6b714555495949634b4e4338646f3337393662674e673743334351374947516773704235452b4770354444783076434d513452535747714445555361416e5856304d4d2f303938354664737867646a5951685853386a4a376542374d4a544d7a436f4b4636355461436a756631333679446d53617273304e636b4b2f5354447567696c666c46486f4d6e76385842444356774853436c724f6b377833687347594b7239524241535067517a5349304e43424479473133466865416b464979316f4368495577346d6879496e554c64637478596f566151753365643445415532324d4c334646766b715352714467555261675a6243384b734c625a785642414d45333233796f6635796c32544b54535a4f3359612f52314436725155676f416143636b484b386a73634c6f434658397779444f707771776f4c397731786357667a3350395a724d354633666145454b41736e417070476a425547754b5130524331706f366f6f433949422f6d724f372b6c3365317174587a37587247325262423555655a4d4143675142694841734653424f32544b386d4679516f5a6c476841674c394373674e6f30305a564f2b3873336e706d70626e45384a526667664251537949636353494c457070577776312f614f4d4a323045515750736b44334d4d664d784447726338574a74626e4b49793865716c326579526451565544416538686d51515738386c5971416c484d6a645678526e4d4658756b30434245573648466747334f4d574b574435634a46773964746e35712b5047354635444d5a31486b49425049474c4b4338535944497876526b5333783261436d3175494d6f654a51467570596a544e555970744b5569736e557a2b736676767250753137396d5373496f66646f75515145594431484365414661456663736d6f3153374d46746e63616841674c644431776b43504d6243506c7245714a4d346f39334c353078633976792b54666363384c7a392f42344342687467434a4134517559593449536250422b7346527672786b426275694e714c6755526267486b51653443334d33524e374f4b306e7a345a4b6b6333397653516d3935584b34504336646935336d5351656c4d4d45554245367a53624478544b5072546d54794473617a6d4a45574943747747326f386c616d6b416e5a47556673334e2f6b30636d396b4d7665564f6f706e5a647a4472564b6c346a51736862614863376f583853764e3279676d736e776372744e4a676a7771707945416a63464976637944784d41785443455444696d6b767375384745665777515151494449575843657a3479506338657163584969374769337959696771707a4549774b33697369726e494142567144636a6563713452674b6b66654e6e41512f65586a6a57767652306547726437553731583357596b5251356e555165417a346f6344546e494942596c476577724d643641574b674166324932797a547038634b47536d4e7657573264317566326e5775724e44574b2b7153344579623267436534422f432f774e6b52594c3946386262566d78634c3959616741414141424a52553545726b4a6767673d3d"&gt;&lt;/a&gt; &lt;a href="https://chrome.google.com/webstore/detail/improve-youtube-video-you/bnomihfieiccainjcjblhegjgglakjdd" rel="nofollow noopener noreferrer"&gt;
&lt;/a&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/youtube-addon/" title="Firefox recommends only 109 extensions" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/18bd43f6d9ddf0b48c2b2c9d68f658c7c42b125b94283ed0d959ea685d6e1b7d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2532302d46697265666f782d77686974653f6c6f676f3d66697265666f7862726f77736572266c6f676f436f6c6f723d6f72616e6765"&gt;&lt;/a&gt;  &lt;a href="https://chrome.google.com/webstore/detail/improve-youtube-video-you/bnomihfieiccainjcjblhegjgglakjdd" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/52ef21dd059f37d887001884ac1ff65ab7ed3ea7b1c9cfcb41c2277f46713bdb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2532302d4368726f6d652d77686974653f6c6f676f3d676f6f676c656368726f6d65266c6f676f436f6c6f723d6c6967687467726579"&gt;&lt;/a&gt;
&lt;a href="https://microsoftedge.microsoft.com/addons/detail/improve-youtube-video-/knbckijjjbmkjiagojjneoplbjilfllc" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/30753bc29bfccfb6fe13428d95abc4a8fcf7252ddfb4d8e263f52cb68de8f8a5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f253230456467652532302532302d77686974653f6c6f676f3d6d6963726f736f667465646765266c6f676f436f6c6f723d7465616c"&gt;&lt;/a&gt;
(&lt;a href="https://addons.opera.com/de/extensions/details/improvedtube-youtube-extension/" rel="nofollow noopener noreferrer"&gt;&lt;img height="12px" src="https://camo.githubusercontent.com/1ab5ec5552615b34ef2ee29b0ee2d212c594a7a41b6b7613f0316918798e22f5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2532302d4f706572612d77686974653f6c6f676f3d6f70657261266c6f676f436f6c6f723d726564"&gt;&lt;/a&gt;)&lt;a href="https://github.com/code-for-charity/ImprovedTube-for-YouTube/releases/latest" title="Release.zip" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcode-charity%2Fyoutubegithub.png" height="18px"&gt; &lt;/a&gt; &lt;br&gt; &lt;a href="https://github.com/code-charity/youtube/issues/new?assignees=&amp;amp;labels=Bug%2C+good+first+issue%2C+help+wanted%2C+up-for-grabs&amp;amp;projects=&amp;amp;template=bug_report.md&amp;amp;title=" rel="noopener noreferrer"&gt;Report a bug&lt;/a&gt; ·
&lt;a href="https://github.com/code-for-charity/ImprovedTube-for-YouTube/issues/new?assignees=&amp;amp;labels=Feature+request%2C+help+wanted&amp;amp;template=feature-request---suggestion---idea.md&amp;amp;title=" rel="noopener noreferrer"&gt;Wish a feature&lt;/a&gt; ·
&lt;a href="https://github.com/code-for-charity/ImprovedTube-for-YouTube/wiki/Contributing" rel="noopener noreferrer"&gt;Contribute&lt;/a&gt; ·
&lt;a href="https://github.com/code-for-charity/ImprovedTube-for-YouTube/wiki/Contributing#donate" rel="noopener noreferrer"&gt;Donate&lt;/a&gt; · &lt;a href="https://github.com/code-for-charity/ImprovedTube-for-YouTube/archive/refs/heads/master.zip" title="Latest.zip" rel="noopener noreferrer"&gt;Test🧪&lt;/a&gt;  &lt;/p&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/code-for-charity/ImprovedTube-for-YouTube/blob/a61f214ddfab91f0a29f41beaf6c3c52e738e0d7/assets/icons/32.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcode-for-charity%2FImprovedTube-for-YouTube%2Fraw%2Fa61f214ddfab91f0a29f41beaf6c3c52e738e0d7%2Fassets%2Ficons%2F32.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;b&gt;&lt;code&gt;/ImprovedTube/&lt;/code&gt;&lt;/b&gt; a powerful but lightweight extension, &lt;br&gt; to enrich your video experience &amp;amp; enable your content selection
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Top &lt;a href="https://addons.mozilla.org/en-US/firefox/search/?page=3&amp;amp;type=extension" rel="nofollow noopener noreferrer"&gt;50&lt;/a&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/youtube-addon/" title="(We started late on Firefox, yet are among their few recommentations and featured on about:addons)" rel="nofollow noopener noreferrer"&gt;&lt;img width="140" alt="recommended by firefox" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F9015764%2F178100681-728b9513-b6f8-4bf7-8949-c3d8449669ec.svg"&gt;&lt;/a&gt;&lt;a href="https://addons.mozilla.org/en-US/firefox/addon/youtube-addon/" title="(We started late on Firefox, yet are among their ~100 recommentations)" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/c4bcaf866cb99abd4cff720b5cea82aef6c9f5ec25b727456d8e20997c09501e/68747470733a2f2f7777772e6d6f7a696c6c612e6f72672f6d656469612f70726f746f636f6c2f696d672f6c6f676f732f66697265666f782f62726f777365722f6c6f676f2e6562313332346534343434322e737667" height="19px"&gt;&lt;/a&gt;&lt;a href="https://lifehacker.com/this-might-be-the-only-youtube-browser-extension-youll-1846575110" title="- Lifehacker.com 2021" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8b330b4c5c5d11c479b8a82169fafe7dc0095c726867b01020162a542b49e506/68747470733a2f2f6c6966656861636b65722e636f6d2f66617669636f6e2e69636f" height="19px"&gt;&lt;/a&gt; &lt;a href="https://www.ghacks.net/2021/03/26/improved-youtube-enhances-youtube-in-meaningful-ways" title="- gHacks.net" rel="nofollow noopener noreferrer"&gt;g&lt;/a&gt; &lt;a href="https://www.chip.de/downloads/Improve-YouTube-fuer-Chrome_183480435.html" title="- Chip.de" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/7464fa29eed3412a2194849d56722c620e5089539292cdc0b0b61f8658a226e0/68747470733a2f2f7777772e636869702e64652f66617669636f6e2e69636f" height="15px"&gt;&lt;/a&gt;
&lt;i&gt;'Might &lt;br&gt; be the only YouTube Extension you'll ever need' &lt;br&gt; 'enhances YouTube in meaningful ways'  &lt;br&gt; 'Strong Add-on, full control. Yet clear &amp;amp; easy' &lt;/i&gt;
&lt;br&gt; Thanks ♡ to our &lt;a href="https://github.com/ImprovedTube/ImprovedTube/graphs/contributors" rel="noopener noreferrer"&gt;c&lt;/a&gt;ontributors, &lt;a href="https://github.com/dodieboy" title="🏅" rel="noopener noreferrer"&gt;A&lt;/a&gt;lan Tan, &lt;a href="https://github.com/raszpl" title="🏅" rel="noopener noreferrer"&gt;R&lt;/a&gt;aszpl
&lt;br&gt;&lt;a href="https://github.com/code-for-charity/YouTube-Extension#--translators-" rel="noopener noreferrer"&gt;t&lt;/a&gt;ranslators (+ wiki-authors? +&lt;a href="https://improvedtube.com/donate" rel="nofollow noopener noreferrer"&gt;d&lt;/a&gt;onators?)&lt;a href="https://improvedtube.com/donate" rel="nofollow noopener noreferrer"&gt;&lt;img class="emoji" title=":bowtie:" alt=":bowtie:" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.githubassets.com%2Fimages%2Ficons%2Femoji%2Fbowtie.png" height="20" width="20"&gt;&lt;/a&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;br&gt;
&lt;div&gt;  &lt;/div&gt; 
Original introduction &lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;
«Improve YouTube!»    &lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;b&gt;
&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;code&gt;/ImprovedTube/&lt;/code&gt;&lt;/b&gt; is a strong &amp;amp; lightweight extension! - 80 features / the only one of a kind!&lt;/p&gt;
Since 2012 we have gradually been adding lightweight features, while keeping up with Youtube changes.
(throughout the years we witnessed the birth &amp;amp; fall of other promising &amp;amp; open YouTube Extensions &lt;a href="https://github.com/YePpHa/YouTubeCenter" title="YouTubeCenter" rel="noopener noreferrer"&gt;1&lt;/a&gt;, &lt;a href="https://github.com/ParticleCore/Iridium" title="Iridium" rel="noopener noreferrer"&gt;2&lt;/a&gt;, ... )
Today adding features can be easier &amp;amp; so motivating as there are 500 000 users. &lt;a href="https://github.com/code-for-charity/YouTube-Extension/discussions/1006" title="github.com/Code-for-Charity" rel="noopener noreferrer"&gt;[👪Join us]&lt;/a&gt;. …&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/code-charity/youtube" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;A project like this is &lt;em&gt;very&lt;/em&gt; important to me, because it enhances the experience of something I do daily - watching videos on YouTube via my desktop. In addition, this project focuses on a topic I was interested in since I started programming: &lt;code&gt;adblocking technology&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The fact that &lt;code&gt;ImprovedTube&lt;/code&gt; offers the ability to block ads &lt;em&gt;and&lt;/em&gt; its code is open-source, hit all of the right checkmarks for me.&lt;/p&gt;

&lt;p&gt;So with my limited amount of web programming knowledge, I decided to take a stab at one of &lt;code&gt;ImprovedTube&lt;/code&gt;'s open issues that involved blocking ads.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I tried to approach the codebase
&lt;/h2&gt;

&lt;p&gt;I knew that there &lt;em&gt;must&lt;/em&gt; be some great resource for me to read and learn the nitty gritty nuances of building a browser extension for different browsers (e.g., building for Chrome, Firefox, etc.) - but I wanted quickly see how I could add changes to some extension code and have those changes reflect in a browser.&lt;/p&gt;

&lt;p&gt;To that end, I decided to follow the tutorial below from freeCodeCamp.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/0n809nd4Zu4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Long story short, this video got me to the point where I could quickly understand how I could edit &lt;code&gt;ImprovedTube&lt;/code&gt;'s code and have my changes reflect within my browser. Since I intend to work on this repository more going forward, I thought that I should dive deeper into learning the ins and outs of a browser extension, and will probably begin reading Mozilla's Guide on Building a cross-browser extension:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Build_a_cross_browser_extension" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.mozilla.org%2Fmdn-social-share.d893525a4fb5fb1f67a2.png" height="450" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Build_a_cross_browser_extension" rel="noopener noreferrer" class="c-link"&gt;
          Build a cross-browser extension - Mozilla | MDN
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          The introduction of the browser extensions API created a uniform landscape for the development of browser extensions. However, there are differences in the API implementations and the scope of coverage among the browsers that use the extensions API (the major ones being Chrome, Edge, Firefox, Opera, and Safari).
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdeveloper.mozilla.org%2Ffavicon-48x48.bc390275e955dacb2e65.png" width="48" height="48"&gt;
        developer.mozilla.org
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Currently, I'm waiting for some clarification with regards to the proper way of implementing the fix for the original issue. You can find the original issue and my pull request below.&lt;/p&gt;

&lt;p&gt;The original issue logged, where I was able to at least reproduce the issue:&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/code-charity/youtube/issues/2634" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Hide "Includes Paid Promotion"
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#2634&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/SuperTRev16" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F178081515%3Fv%3D4" alt="SuperTRev16 avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/SuperTRev16" rel="noopener noreferrer"&gt;SuperTRev16&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/code-charity/youtube/issues/2634" rel="noopener noreferrer"&gt;&lt;time&gt;Oct 28, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;⚬ &lt;em&gt;PROBLEM&lt;/em&gt;:
The annoying "Includes Paid Promotion" popup that tells us there is a paid promotion in the video.
I can see how that's a legal thing, but is still unwanted bloat.
Most YouTube channels always have some kind of affiliate marketing nowadays anyway.  We don't really need a reminder of that on every other video.&lt;/p&gt;
&lt;p&gt;⚬ &lt;em&gt;SOLUTION&lt;/em&gt;:&lt;br&gt;
Create a new feature that gives us the ability to hide that.&lt;/p&gt;
&lt;p&gt;⚬ &lt;em&gt;RELEVANCE / SCOPE&lt;/em&gt;:
YouTube player&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/code-charity/youtube/issues/2634" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;My pull request:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/code-charity/youtube/pull/2684" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat: add styles to hide 'Includes Paid Promotion' elements
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#2684&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/peterdanwan" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F97978729%3Fv%3D4" alt="peterdanwan avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/peterdanwan" rel="noopener noreferrer"&gt;peterdanwan&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/code-charity/youtube/pull/2684" rel="noopener noreferrer"&gt;&lt;time&gt;Nov 19, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;This pull request attempts to close #2634.&lt;/p&gt;
&lt;p&gt;As discussed in #2634, certain videos include a clickable link on top of the video titled, &lt;code&gt;Includes Paid Promotion&lt;/code&gt; as shown in the video below:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/user-attachments/assets/5a67afbb-2bb1-4991-bf4f-4ad20b29ef76" rel="noopener noreferrer"&gt;https://github.com/user-attachments/assets/5a67afbb-2bb1-4991-bf4f-4ad20b29ef76&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With the changes made, the extension now &lt;em&gt;hides&lt;/em&gt; the HTML elements related to the &lt;code&gt;Includes Paid Promotion&lt;/code&gt; link:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/user-attachments/assets/d4772053-d1cf-40d5-abe3-0e4b86c61546" rel="noopener noreferrer"&gt;https://github.com/user-attachments/assets/d4772053-d1cf-40d5-abe3-0e4b86c61546&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Please let me know if there's anything else I should change - I'm happy to learn and fix more issues!&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/code-charity/youtube/pull/2684" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;My goal right now as I await further clarification is to read more of Mozilla's documentation regarding building a cross browser extension, in hopes of making it easier for me to contribute to ImprovedTube going forward.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>browser</category>
      <category>opensource</category>
      <category>extensions</category>
    </item>
    <item>
      <title>Contributing to expressjs</title>
      <dc:creator>Peter Wan</dc:creator>
      <pubDate>Wed, 20 Nov 2024 00:51:17 +0000</pubDate>
      <link>https://dev.to/peterdanwan/contributing-to-expressjs-2088</link>
      <guid>https://dev.to/peterdanwan/contributing-to-expressjs-2088</guid>
      <description>&lt;p&gt;Hi! My name is Peter, and if you don't know me, I'm a computer science student, currently taking &lt;a href="https://github.com/humphd" rel="noopener noreferrer"&gt;Professor David Humphrey's&lt;/a&gt; &lt;a href="https://github.com/humphd/topics-in-open-source-2024" rel="noopener noreferrer"&gt;Topics in Open Source 2024 class&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since September of 2024, I've been working to build my presence in the open source community. If you'd like to follow my journey, you can find me on GitHub:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://github.com/peterdanwan" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F97978729%3Fv%3D4%3Fs%3D400" height="460" class="m-0" width="460"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://github.com/peterdanwan" rel="noopener noreferrer" class="c-link"&gt;
          peterdanwan (Peter Wan) · GitHub
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Full Stack Developer | Games and AI Enthusiast 

 - peterdanwan
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.githubassets.com%2Ffavicons%2Ffavicon.svg" width="32" height="32"&gt;
        github.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;With my final semester and the &lt;code&gt;Topics In Open Source&lt;/code&gt; course coming to an end, I want to share my progress as a budding open-source developer and my roadmap for future growth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I'm at right now
&lt;/h2&gt;

&lt;p&gt;Let me start with one key realization: &lt;strong&gt;I have a lot to learn&lt;/strong&gt;. If you'd asked me at the start of the semester what I needed to learn, I would have said "Everything!"&lt;/p&gt;

&lt;p&gt;Now? I'd say "&lt;em&gt;Enough to get the job done&lt;/em&gt;."&lt;/p&gt;

&lt;p&gt;As I near the end of both this course and my final semester, I'm incredibly grateful to have taken Topics in Open Source. Without it, I wouldn't have gained nearly as much practical experience with Git and GitHub. After months of hands-on work, I can confidently say I've mastered many aspects of these tools.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;However, open-source is &lt;em&gt;more&lt;/em&gt; than just Git and GitHub.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To me, Git and GitHub are just a means to an end of understanding a code base. With regards to &lt;code&gt;Git&lt;/code&gt;, I no longer have problems with creating branches to work on, navigating between branches, resolving merge conflicts, rebasing my branch's commits onto the current changes on the upstream main branch, squashing commits, testing code on different branches, etc.&lt;/p&gt;

&lt;p&gt;I'm pretty happy to say those things are second nature now! But once again - to me, Git and GitHub are just a &lt;em&gt;part&lt;/em&gt; of what it means to be an open-source developer. Let me tell you how I want to improve as an open-source developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I want to improve as an open source developer
&lt;/h2&gt;

&lt;p&gt;Remember when I mentioned knowing "&lt;em&gt;Enough to get the job done&lt;/em&gt;"? Let me show you what that actually means through my recent &lt;a href="https://github.com/expressjs/expressjs.com/pull/1685" rel="noopener noreferrer"&gt;pull request&lt;/a&gt; for &lt;a href="https://github.com/expressjs/expressjs.com" rel="noopener noreferrer"&gt;expressjs.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi90ipfixdth00c9ko417.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi90ipfixdth00c9ko417.gif" alt="basics-zuko" width="400" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding the project's scope
&lt;/h3&gt;

&lt;p&gt;First step: understanding what I'm working with. &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;expressjs.com&lt;/a&gt; is the official documentation site for &lt;a href="https://github.com/expressjs/express" rel="noopener noreferrer"&gt;express&lt;/a&gt;, one of the most popular web frameworks for Node.js. While this was quick to grasp from their beautifully designed website, the journey was just beginning.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://expressjs.com/" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fexpressjs.com%2Fimages%2Fog.png" height="420" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://expressjs.com/" rel="noopener noreferrer" class="c-link"&gt;
          Express - Node.js web application framework
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Express is a fast, unopinionated, minimalist web framework for Node.js, providing a robust set of features for web and mobile applications.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fexpressjs.com%2Fimages%2Ffavicon.png" width="32" height="32"&gt;
        expressjs.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Understanding the issue at hand
&lt;/h3&gt;

&lt;p&gt;After getting familiar with the project as it is, I looked for an issue I could tackle. I found this one:&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/expressjs/expressjs.com/issues/1684" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Broken link and missing page
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1684&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/chrisdel101" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F14151974%3Fv%3D4" alt="chrisdel101 avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/chrisdel101" rel="noopener noreferrer"&gt;chrisdel101&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/expressjs/expressjs.com/issues/1684" rel="noopener noreferrer"&gt;&lt;time&gt;Nov 17, 2024&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;The following links are broken
&lt;code&gt;_includes/header/header-id.html&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;a href="/{{ page.lang }}/changelog/4x.html"&amp;gt;Release Change Log&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;_includes/header/header-th.html&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;a href="/{{ page.lang }}/changelog/4x.html"&amp;gt;บันทึกการเปลี่ยนแปลง&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Suggest change to: &lt;code&gt;&amp;lt;a href="/en/changelog/"&amp;gt;Release Change Log&amp;lt;/a&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Missing page causes console error in UZ language:
&lt;code&gt;/css/langs/uz.css&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Suggest adding this page.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/expressjs/expressjs.com/issues/1684" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I chose this issue because it involved HTML and CSS - technologies I'm comfortable and familiar with. However, what &lt;em&gt;looked&lt;/em&gt; simple actually taught me an important lesson about open source development:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Even familiar-looking tasks can involve unfamiliar territory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The repository used technologies I'd never touched before, and that's where the real learning began. It took me about an hour just to decide whether to attempt this issue - maybe too long in retrospect. I was hesitant because the project used &lt;a href="https://www.ruby-lang.org/en/" rel="noopener noreferrer"&gt;Ruby&lt;/a&gt;, which was completely new to me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Spoiler alert: Setting up Ruby was... an adventure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Understanding how to setup the project locally
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Setting up your local development environment is often one of the most educational parts of an open-source contribution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I learned a little about &lt;a href="https://www.ruby-lang.org/en/" rel="noopener noreferrer"&gt;Ruby&lt;/a&gt; and &lt;a href="https://jekyllrb.com/docs/installation/" rel="noopener noreferrer"&gt;Jekyll&lt;/a&gt;, simply by trying to run &lt;code&gt;expressjs.com&lt;/code&gt; locally.&lt;/p&gt;

&lt;p&gt;Here's how my journey unfolded:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Initial Confusion&lt;/strong&gt;: I started by installing Ruby directly on Windows. While it worked, it wasn't ideal, because I was having problems with the version I installed being different than the one used in the project. Version management on Windows was not fun. As such, I uninstalled my installation of Ruby on Windows and its other dependencies and looked for an alternative solution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The WSL Discovery&lt;/strong&gt;: My research led me to the conclusion that I should run Ruby on the Windows Subsystem for Linux (WSL), since it offers a much better development environment and access to the powerful Ruby Version Manager (RVM), which would allow me to work on projects that use different versions of Ruby. To me, installing &lt;code&gt;RVM&lt;/code&gt; was a very similar feeling, since I use &lt;a href="https://github.com/coreybutler/nvm-windows" rel="noopener noreferrer"&gt;nvm-windows&lt;/a&gt; to allow me to switch between different &lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;node&lt;/a&gt; versions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Version Management Learning Curve&lt;/strong&gt;: Once again, I learned about RVM and its similarity to Node.js's nvm. This taught me the importance of version management in development environments.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below are the actual commands I used to get my development environment ready:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;## 1. Installing RVM (Ruby Version Manager)&lt;/span&gt;
&lt;span class="c"&gt;# First, import GPG keys needed to verify RVM installation&lt;/span&gt;
gpg &lt;span class="nt"&gt;--keyserver&lt;/span&gt; hkp://keyserver.ubuntu.com &lt;span class="nt"&gt;--recv-keys&lt;/span&gt; 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB

&lt;span class="c"&gt;# Download and install RVM&lt;/span&gt;
&lt;span class="se"&gt;\c&lt;/span&gt;url &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://get.rvm.io | bash &lt;span class="nt"&gt;-s&lt;/span&gt; stable

&lt;span class="c"&gt;# Verify RVM is installed and get its path&lt;/span&gt;
which rvm

&lt;span class="c"&gt;# Load RVM into your current shell session&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; /home/peter/.rvm/scripts/rvm

&lt;span class="c"&gt;## 2. Installing Ruby&lt;/span&gt;
&lt;span class="c"&gt;# Install Ruby version 3.3.5 (latest stable as of early 2024)&lt;/span&gt;
rvm &lt;span class="nb"&gt;install &lt;/span&gt;3.3.5

&lt;span class="c"&gt;# Set 3.3.5 as your default Ruby version&lt;/span&gt;
rvm use 3.3.5

&lt;span class="c"&gt;# Verify RVM and Ruby installations&lt;/span&gt;
rvm &lt;span class="nt"&gt;-v&lt;/span&gt;
ruby &lt;span class="nt"&gt;-v&lt;/span&gt;

&lt;span class="c"&gt;## 3. Setting up Jekyll&lt;/span&gt;
&lt;span class="c"&gt;# Install Jekyll and Bundler gems&lt;/span&gt;
gem &lt;span class="nb"&gt;install &lt;/span&gt;bundler jekyll

&lt;span class="c"&gt;# Install project dependencies from Gemfile (must be within the target directory with the Gemfile)&lt;/span&gt;
bundle &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Start the Jekyll server with live reload and external access&lt;/span&gt;
&lt;span class="c"&gt;# --host 0.0.0.0 allows access from other devices on your network&lt;/span&gt;
&lt;span class="c"&gt;# --livereload automatically refreshes your browser when files change&lt;/span&gt;
bundle &lt;span class="nb"&gt;exec &lt;/span&gt;jekyll serve &lt;span class="nt"&gt;--host&lt;/span&gt; 0.0.0.0 &lt;span class="nt"&gt;--livereload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tackling the issue
&lt;/h3&gt;

&lt;p&gt;With my development environment configured, I was able to begin addressing the issue at hand, that is to simply update the&lt;br&gt;
anchor tags containing broken links to an English version of the link (since the English version of the link isn't broken).&lt;/p&gt;

&lt;p&gt;That was the easiest part of this whole contribution.&lt;/p&gt;

&lt;p&gt;I also made sure to look at some logs to see if there were any errors to fix. I suggested adding another file &lt;code&gt;css/id.css&lt;/code&gt;, which follows the same&lt;br&gt;
coding format of files that were added already, since I had an inkling that would resolve some of the error logs.&lt;/p&gt;

&lt;p&gt;One of the maintainers of &lt;code&gt;expressjs.com&lt;/code&gt; &lt;a href="https://github.com/chrisdel101" rel="noopener noreferrer"&gt;Chris Del&lt;/a&gt;, provided very immediate feedback stating that was the thing to do (thank you Chris!).&lt;/p&gt;

&lt;p&gt;As such, I also added this change to my pull request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Waiting to merge changes and learning to get involved with discussions
&lt;/h3&gt;

&lt;p&gt;With that said, the changes I have made are now waiting to be merged into &lt;code&gt;expressjs.com&lt;/code&gt;'s main branch.&lt;br&gt;
A follow-up issue was made to discuss the standards of the &lt;code&gt;expressjs.com&lt;/code&gt; website. That is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;should a user be redirected to a working English page than to a broken-link in the correct language?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;That is not up to me to decide&lt;/em&gt;, but I wanted to be part of the discussion. You can follow the discussion over &lt;a href="https://github.com/expressjs/expressjs.com/issues/1686" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning to Grow as an Open Source Developer
&lt;/h2&gt;

&lt;p&gt;What started as a simple HTML/CSS fix turned into a journey that taught me valuable lessons about open source development:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stepping Out of Comfort Zones&lt;/strong&gt;: While I chose an issue that involved familiar technologies (HTML/CSS), I ended up learning an entirely new tech stack (Ruby/Jekyll). This taught me that growth happens when we're willing to tackle the unfamiliar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Technical Growth&lt;/strong&gt;: Setting up development environments, managing versions, and working with new tools are all crucial skills. Each challenge makes the next one easier to approach.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Community Engagement&lt;/strong&gt;: Through discussions like the &lt;a href="https://github.com/expressjs/expressjs.com/issues/1686" rel="noopener noreferrer"&gt;language redirect discussion&lt;/a&gt;, I learned that open source isn't just about code - it's about participating in meaningful discussions that shape project decisions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Looking ahead, I plan to improve by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Taking on increasingly challenging issues&lt;/li&gt;
&lt;li&gt;Learning to work with different tech stacks and development environments&lt;/li&gt;
&lt;li&gt;Engaging more actively in project discussions and decision-making&lt;/li&gt;
&lt;li&gt;Contributing to documentation and helping other newcomers&lt;/li&gt;
&lt;li&gt;Building relationships within open source communities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most importantly, I've learned that being an effective open source developer isn't about knowing everything - it's about being willing to learn anything. Every contribution, no matter how small, is an opportunity to grow and make a positive impact on the projects we care about.&lt;/p&gt;

&lt;p&gt;If you're considering getting involved in open source, remember: start small, be curious, and don't be afraid to learn as you go. The community is here to help you grow.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>express</category>
    </item>
    <item>
      <title># From Jest to Pytest: A JavaScript Developer's Journey into Python Testing</title>
      <dc:creator>Peter Wan</dc:creator>
      <pubDate>Thu, 14 Nov 2024 23:30:32 +0000</pubDate>
      <link>https://dev.to/peterdanwan/-from-jest-to-pytest-a-javascript-developers-journey-into-python-testing-gl0</link>
      <guid>https://dev.to/peterdanwan/-from-jest-to-pytest-a-javascript-developers-journey-into-python-testing-gl0</guid>
      <description>&lt;h1&gt;
  
  
  From Jest to Pytest: A JavaScript Developer's Journey into Python Testing
&lt;/h1&gt;

&lt;p&gt;As a developer with a JavaScript background, I've spent a fair amount of time writing tests with &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;. In my project, &lt;a href="https://github.com/peterdanwan/gimme_readme" rel="noopener noreferrer"&gt;gimme_readme&lt;/a&gt;, I had to play around with some experimental features with &lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;Node&lt;/a&gt; and Jest because of the 3rd party npm modules I was using. I was able to find great &lt;a href="https://stackoverflow.com/questions/35756479/does-jest-support-es6-import-export" rel="noopener noreferrer"&gt;Stack Overflow threads&lt;/a&gt; that taught me how to run Jest tests when using ES6 syntax. Without the wisdom of these smart individuals, let's just say I would have struggled! However, armed with this knowledge of how to use Jest's experimental features, I was able to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;write my tests in Jest (despite my weird configurations)&lt;/li&gt;
&lt;li&gt;set up my &lt;code&gt;CI pipeline&lt;/code&gt; very early on, which is set up to:

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;lint&lt;/code&gt; my code (i.e., check for any potential lines of code that can be problematic in the future or can cause bugs as they are now)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;test&lt;/code&gt; my source code (i.e., runs tests that I have written which explain how my source code should work).&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;The code for the CI pipeline I described above can be found &lt;a href="https://github.com/peterdanwan/gimme_readme/blob/main/.github/workflows/ci.yml" rel="noopener noreferrer"&gt;here&lt;/a&gt;, and is set to run whenever a push is made to any branch or when there's a pull request. This way, anyone who's trying to contribute to my repository will know if the code they contributed is "good enough to go" with regards to merging it into my main branch - at least as far as automated tests go.&lt;/p&gt;

&lt;p&gt;Anywho, that's enough about the work I've done for &lt;em&gt;my&lt;/em&gt; repository way back when.&lt;/p&gt;

&lt;p&gt;This week, I decided to take on the challenge of writing some tests for a Python project written by my friend &lt;a href="https://github.com/AryanK1511" rel="noopener noreferrer"&gt;Aryan Khurana&lt;/a&gt;. Aryan's project is a command-line tool called &lt;a href="https://github.com/AryanK1511/github-echo" rel="noopener noreferrer"&gt;github-echo&lt;/a&gt; which provides insights on a GitHub repository. Using an unfamiliar language + a testing framework I had never used (&lt;a href="https://docs.pytest.org/en/stable/" rel="noopener noreferrer"&gt;PyTest&lt;/a&gt;) was definitely outside my comfort zone, but I really appreciated that Aryan was willing to show me the ropes (thanks Aryan!).&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Python code with &lt;code&gt;pytest&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;When I started working on &lt;a href="https://github.com/AryanK1511/github-echo/pull/54" rel="noopener noreferrer"&gt;tests for Aryan's repository&lt;/a&gt;, I was immediately overwhelmed by how different the tests looked. While Jest had become familiar territory for me, Python's &lt;code&gt;pytest&lt;/code&gt; felt very foreign. Nevertheless, with Aryan's guidance and some determination, I started to understand its unique features.&lt;/p&gt;

&lt;p&gt;Let's break down what I discovered in their test cases:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parameterized Testing&lt;/strong&gt;: One of the first things that caught my eye was the &lt;code&gt;@pytest.mark.parametrize&lt;/code&gt; decorator. This is similar to Jest's &lt;code&gt;test.each&lt;/code&gt;, but with a cleaner syntax:&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="nd"&gt;@pytest.mark.parametrize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;invalid_url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="p"&gt;[&lt;/span&gt;
           &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://gitlab.com/username/repository&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://github.com/username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="c1"&gt;# ... more test cases
&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;&lt;strong&gt;Context Managers&lt;/strong&gt;: Instead of Jest's &lt;code&gt;expect().toThrow()&lt;/code&gt;, Python uses context managers with &lt;code&gt;pytest.raises&lt;/code&gt;:&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="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;typer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BadParameter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Invalid GitHub repository URL&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
      &lt;span class="nf"&gt;check_cli_arguments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invalid_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gemini&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;output.md&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Temporary File System&lt;/strong&gt;: The tests use pytest's &lt;code&gt;tmp_path&lt;/code&gt; fixture for file system operations, which is much cleaner than setting up mock file systems in Jest:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_output_file_is_directory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tmp_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
      &lt;span class="c1"&gt;# tmp_path is automatically provided and cleaned up
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This experience of working with both JavaScript and Python testing frameworks has broadened my perspective on software testing. While Jest felt like home territory, I've come to appreciate pytest's powerful features like parameterized testing and fixtures. Whether you're writing JavaScript or Python tests, the end goal remains the same: delivering reliable, well-tested code to your users.&lt;/p&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>Testing LLM Applications: Misadventures in Mocking SDKs vs Direct HTTP Requests</title>
      <dc:creator>Peter Wan</dc:creator>
      <pubDate>Mon, 11 Nov 2024 03:40:01 +0000</pubDate>
      <link>https://dev.to/peterdanwan/testing-llm-applications-misadventures-in-mocking-sdks-vs-direct-http-requests-5dgi</link>
      <guid>https://dev.to/peterdanwan/testing-llm-applications-misadventures-in-mocking-sdks-vs-direct-http-requests-5dgi</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Let me preface this blog by saying this &lt;em&gt;isn't&lt;/em&gt; like my other blogs where I was able to walk through the steps I took to complete a task. Instead, this is more of a reflection on the challenges I've encountered while trying to add tests to my project, &lt;a href="https://github.com/peterdanwan/gimme_readme" rel="noopener noreferrer"&gt;gimme_readme&lt;/a&gt;, and what I've learned about testing LLM-powered applications along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Context
&lt;/h2&gt;

&lt;p&gt;This week, my Open Source Development classmates and I were tasked with adding tests to our command-line tools that incorporate Large Language Models (LLMs). This seemed straightforward at first, but it led me down a rabbit hole of testing complexities I hadn't anticipated.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Testing Journey
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Initial Approach
&lt;/h3&gt;

&lt;p&gt;When I first built &lt;code&gt;gimme_readme&lt;/code&gt;, I added some basic tests using &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest.js&lt;/a&gt;. These tests were fairly simple, focusing mainly on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verifying function outputs&lt;/li&gt;
&lt;li&gt;Checking basic error handling&lt;/li&gt;
&lt;li&gt;Testing simple utility functions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While these tests provided some coverage, they weren't testing one of the most critical parts of my application: the LLM interactions.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Challenge: Testing LLM Interactions
&lt;/h3&gt;

&lt;p&gt;As I tried to add more comprehensive tests, I ran into an interesting realization about how my application communicates with LLMs. Initially, I thought I could use &lt;a href="https://github.com/nock/nock" rel="noopener noreferrer"&gt;Nock.js&lt;/a&gt; to mock the HTTP requests to these language models. After all, that's what Nock is great at - intercepting and mocking HTTP requests for testing.&lt;/p&gt;

&lt;p&gt;However, I discovered that the &lt;em&gt;way&lt;/em&gt; I am using the LLM is making it hard for me to write tests using &lt;code&gt;Nock&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The SDK vs Direct HTTP Requests Dilemma
&lt;/h3&gt;

&lt;p&gt;Here's where things get interesting. My application uses official SDK clients provided by LLM services like Google's Gemini and Groq. These SDKs act as abstraction layers that &lt;em&gt;handle all the HTTP communication behind the scenes&lt;/em&gt;. While this makes the code cleaner and easier to work with in production, it creates an interesting testing challenge.&lt;/p&gt;

&lt;p&gt;Consider these two approaches to implementing LLM functionality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Approach 1: Using SDK&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;groq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Groq&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;apiKey&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;groq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mixtral-8x7b-32768&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Approach 2: Direct HTTP requests&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.groq.com/v1/completions&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="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mixtral-8x7b-32768&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SDK approach is cleaner and provides better developer experience, but it makes traditional HTTP mocking tools like Nock less useful. The HTTP requests are happening inside the SDK, making them harder to &lt;em&gt;intercept&lt;/em&gt; with Nock.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consider Testing Strategy Early&lt;/strong&gt;: When choosing between SDKs and direct HTTP requests, consider how you'll test the implementation. Sometimes the "cleaner" production code might make testing more challenging.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SDK Testing Requires Different Tools&lt;/strong&gt;: When using SDKs, you need to mock at the SDK level rather than the HTTP level. This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mocking the entire SDK client&lt;/li&gt;
&lt;li&gt;Focusing on the SDK's interface rather than HTTP requests&lt;/li&gt;
&lt;li&gt;Using Jest's module mocking capabilities instead of HTTP interceptors&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Balance Between Convenience and Testability&lt;/strong&gt;: While SDKs provide great developer experience, they can make certain testing approaches more difficult. It's worth considering this trade-off when architecting your application.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Going Forward
&lt;/h2&gt;

&lt;p&gt;While I haven't yet fully resolved my testing challenges, this experience has taught me valuable lessons about testing applications that rely on external services via SDKs. For anyone building similar applications, I'd recommend:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Think about testing strategy when choosing between SDKs and direct API calls&lt;/li&gt;
&lt;li&gt;If using SDKs, plan to mock at the SDK level rather than the HTTP level&lt;/li&gt;
&lt;li&gt;Consider writing thin wrappers around SDKs to make them more testable&lt;/li&gt;
&lt;li&gt;Document the testing approach for others who might work on the project&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Testing LLM applications presents unique challenges, especially when balancing modern development conveniences like SDKs with the need for thorough testing. While I'm still working on improving the test coverage for gimme_readme, this experience has given me a better understanding of how to approach testing in future projects that involve external services and SDKs.&lt;/p&gt;

&lt;p&gt;Has anyone else encountered similar challenges when testing applications that use LLM SDKs? I'd love to hear about your experiences and solutions in the comments!&lt;/p&gt;

</description>
      <category>jest</category>
      <category>opensource</category>
      <category>javascript</category>
      <category>testing</category>
    </item>
    <item>
      <title>Hacktoberfest 2024: A retrospective</title>
      <dc:creator>Peter Wan</dc:creator>
      <pubDate>Thu, 31 Oct 2024 23:39:56 +0000</pubDate>
      <link>https://dev.to/peterdanwan/hacktoberfest-2024-a-retrospective-3a7c</link>
      <guid>https://dev.to/peterdanwan/hacktoberfest-2024-a-retrospective-3a7c</guid>
      <description>&lt;p&gt;Hi fellas! It's the end of October and by extension, the &lt;em&gt;end&lt;/em&gt; of &lt;a href="https://hacktoberfest.com/" rel="noopener noreferrer"&gt;Hacktoberfest 2024&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the month of October, I've been constantly contributing to open source projects and in doing so, I learned a &lt;em&gt;lot&lt;/em&gt;. For walkthroughs on the &lt;code&gt;issues&lt;/code&gt; and &lt;code&gt;pull requests&lt;/code&gt; I had done during this time period, you can check out my other blogs below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/peterdanwan/devlog-hacktoberfest-2024-14-23b"&gt;Devlog: Hacktoberfest 2024 (1/4)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/peterdanwan/devlog-hacktoberfest-2024-24-32ja"&gt;Devlog: Hacktoberfest 2024 (2/4)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/peterdanwan/devlog-hacktoberfest-2024-34-44f"&gt;Devlog: Hacktoberfest 2024 (3/4)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/peterdanwan/devlog-hacktoberfest-2024-44-k2m"&gt;Devlog: Hacktoberfest 2024 (4/4)&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I wanted to take a moment to reflect on the takeaways I got from participating in &lt;code&gt;Hacktoberfest&lt;/code&gt; as a contributor.&lt;/p&gt;

&lt;p&gt;Below, are the list of things &lt;em&gt;I&lt;/em&gt; did that I believe helped me on my journey. I would highly recommend others to follow a similar approach!&lt;/p&gt;

&lt;h2&gt;
  
  
  Master Git Fundamentals
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Learn essential git commands and workflows&lt;/li&gt;
&lt;li&gt;Practice branching, merging, and resolving conflicts&lt;/li&gt;
&lt;li&gt;Don't hesitate to consult &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;Git documentation&lt;/a&gt; or ask for help in project discussions&lt;/li&gt;
&lt;li&gt;Keep a cheat sheet of commonly used git commands handy

&lt;ul&gt;
&lt;li&gt;I keep all of my &lt;code&gt;git shortcuts&lt;/code&gt; in my &lt;code&gt;.gitignore&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;And if all else fails... ask &lt;code&gt;GPT&lt;/code&gt; or &lt;code&gt;Claude&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Familiarize yourself with Searching for Projects and looking through them
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Use GitHub's advanced search filters (language, labels, "good first issue", etc.)
&amp;gt; Try finding issues from &lt;a href="https://github.com/issues?q=is%3Aopen+is%3Aissue+archived%3Afalse+label%3A%22good+first+issue%22" rel="noopener noreferrer"&gt;here&lt;/a&gt; and working with different filters: &lt;/li&gt;
&lt;li&gt;Follow projects that interest you to stay updated on new issues

&lt;ul&gt;
&lt;li&gt;Personally, I followed projects that I have seen on YouTube (with regards to gaming) and projects whose tools I use (e.g., &lt;a href="https://github.com/microsoft/vscode" rel="noopener noreferrer"&gt;Microsoft Visual Studio Code&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Look for projects with active maintainers and study their contribution guidelines

&lt;ul&gt;
&lt;li&gt;Search for the keywords &lt;code&gt;contribute&lt;/code&gt; or &lt;code&gt;contributions&lt;/code&gt; in a repository to ensure that you follow a repository's guidelines&lt;/li&gt;
&lt;li&gt;If you don't follow someone else's contribution guidelines... (don't expect them to accept your PR!)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Research previous &lt;code&gt;issues&lt;/code&gt; and &lt;code&gt;pull requests&lt;/code&gt; to see if you can find hints on how to solve your &lt;em&gt;own&lt;/em&gt; issue.

&lt;ul&gt;
&lt;li&gt;For example, check out my own &lt;a href="https://github.com/streetsidesoftware/vscode-spell-checker/pull/3729" rel="noopener noreferrer"&gt;pull request&lt;/a&gt; you can see that I reference an existing pull request to back up the work I did.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;This was just a short summary of what has been an incredible month-long journey in open source contribution. But rather than just taking my word for it, I encourage anyone reading this to get out there and dive into open source yourself! Remember: every expert was once a beginner, every maintainer was once a first-time contributor, and every journey starts with that first pull request.&lt;/p&gt;

&lt;p&gt;Happy coding, and see you in the next Hacktoberfest! 🎃 💻&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>github</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Tips on Improving an Open Source Project</title>
      <dc:creator>Peter Wan</dc:creator>
      <pubDate>Wed, 30 Oct 2024 01:40:23 +0000</pubDate>
      <link>https://dev.to/peterdanwan/tips-on-improving-an-open-source-project-2peg</link>
      <guid>https://dev.to/peterdanwan/tips-on-improving-an-open-source-project-2peg</guid>
      <description>&lt;p&gt;Hello there!&lt;/p&gt;

&lt;p&gt;I just wanted to leave some notes on what I think are some best practices to follow when creating and maintaining an open source project.&lt;/p&gt;

&lt;p&gt;I have implemented these best practices on my GitHub repository for my command-line tool, &lt;code&gt;gimme_readme&lt;/code&gt;, which allows one to send multiple source files to an LLM easily, and get a quick response on what those source files are doing.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/peterdanwan" rel="noopener noreferrer"&gt;
        peterdanwan
      &lt;/a&gt; / &lt;a href="https://github.com/peterdanwan/gimme_readme" rel="noopener noreferrer"&gt;
        gimme_readme
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      gimme_readme is a command-line tool powered by AI that generates a comprehensive README.md file for your project. It analyzes multiple source code files at once, providing concise explanations of each file's purpose, functionality, and key components, all in a single, easy-to-read document.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;gimme_readme&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;gimme_readme&lt;/code&gt; is a command-line tool powered by AI that generates a comprehensive &lt;code&gt;README.md&lt;/code&gt; file for your project. It analyzes multiple source code files at once, providing concise explanations of each file's purpose, functionality, and key components, all in a single, easy-to-read document.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/43114e73a62f09ab2afa2c10fea0dd74c58eceab1453e57f5429fe8e185cdd05/68747470733a2f2f6465762d746f2d75706c6f6164732e73332e616d617a6f6e6177732e636f6d2f75706c6f6164732f61727469636c65732f74717033317037666d386d3135737333716b776c2e676966"&gt;&lt;img src="https://camo.githubusercontent.com/43114e73a62f09ab2afa2c10fea0dd74c58eceab1453e57f5429fe8e185cdd05/68747470733a2f2f6465762d746f2d75706c6f6164732e73332e616d617a6f6e6177732e636f6d2f75706c6f6164732f61727469636c65732f74717033317037666d386d3135737333716b776c2e676966" alt="gimme_readme-0.1-demo-revised"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See our &lt;a href="https://youtu.be/S6v-u9o_Xx8" rel="nofollow noopener noreferrer"&gt;0.1 Release Demo&lt;/a&gt;!&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Table of Contents&lt;/h2&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/peterdanwan/gimme_readme#1-getting-started" rel="noopener noreferrer"&gt;Getting Started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/peterdanwan/gimme_readme#2-usage" rel="noopener noreferrer"&gt;Usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/peterdanwan/gimme_readme#3-example-usage" rel="noopener noreferrer"&gt;Example Usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/peterdanwan/gimme_readme#4-supported-models-by-providers" rel="noopener noreferrer"&gt;Supported Models by Providers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/peterdanwan/gimme_readme#5-contributing" rel="noopener noreferrer"&gt;Contributing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/peterdanwan/gimme_readme#6-testing-locally" rel="noopener noreferrer"&gt;Testing Locally&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/peterdanwan/gimme_readme#7-author" rel="noopener noreferrer"&gt;Author&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;1. Getting Started&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;To get started with &lt;code&gt;gimme_readme&lt;/code&gt;, follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install the latest version of &lt;a href="https://nodejs.org/en/download/package-manager" rel="nofollow noopener noreferrer"&gt;Node.js&lt;/a&gt; for your operating system.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the following command to install &lt;code&gt;gimme_readme&lt;/code&gt; globally:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm i -g gimme_readme&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;NOTE: MAC/LINUX users may need to run &lt;code&gt;sudo npm i -g gimme_readme&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Generate a configuration file by running in &lt;em&gt;any&lt;/em&gt; folder you'd like:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;gr-ai -c&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This command creates a &lt;code&gt;.gimme_readme_config&lt;/code&gt; file in your home directory. &lt;strong&gt;Do not move this file from this location.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open the &lt;code&gt;.gimme_readme_config&lt;/code&gt; file and add your API…&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/peterdanwan/gimme_readme" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;My quick advice is to set everything I'm about to mention as soon as possible! It'll make &lt;em&gt;your&lt;/em&gt; development experience as well as the development experience of &lt;em&gt;others&lt;/em&gt; as seamless as possible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Start with a License
&lt;/h2&gt;

&lt;p&gt;Whether you want your project to be worked on by others or not, you &lt;em&gt;should&lt;/em&gt; look into adding a license to your work. Your license will describe what others can or cannot do with your code, so I would highly suggest you think about this before creating your repository.&lt;/p&gt;

&lt;p&gt;That said, I am &lt;em&gt;not&lt;/em&gt; a lawyer, so I cannot disclose information on what's the best license for your use-case or provide any legal advice. &lt;/p&gt;

&lt;p&gt;What I can say is that, I would start by reading the documentation that &lt;code&gt;GitHub&lt;/code&gt; has provided &lt;a href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository" rel="noopener noreferrer"&gt;here&lt;/a&gt; to set up a License for your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add a main README.md file and have it link to other documentation when appropriate
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Your README.md should provide a clear overview of your project and getting started instructions. For detailed topics that require in-depth explanation, create separate documentation files and link to them from your main README.md.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Recently, I have added a section to my &lt;code&gt;README.md&lt;/code&gt; that links to the &lt;code&gt;License&lt;/code&gt; I mentioned earlier. This would be a prime example of when you'd want to provide a link to something instead of explaining it directly in your README.md.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add a &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; file &amp;amp; &lt;code&gt;CODE_OF_CONDUCT.md&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Since I have been invested with learning more about &lt;code&gt;Open Source Development&lt;/code&gt;, I have come across two common files that are usually apparent in large, open-source projects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;CONTRIBUTING.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CODE_OF_CONDUCT.md&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These files appear to be fairly common with large projects and have a very well defined purpose (you can infer what they're about just from the names!).&lt;/p&gt;

&lt;p&gt;You'll note that both of these files are quite lengthy, but at the same time &lt;em&gt;focused&lt;/em&gt;. Having these files can help minimize the bloat of your main &lt;code&gt;README.md&lt;/code&gt; file, which should explain the &lt;code&gt;scope of your project&lt;/code&gt;, and &lt;code&gt;direct others to appropriate resources&lt;/code&gt; when necessary.&lt;/p&gt;

&lt;p&gt;Imagine you're a maintainer for a project and someone asks you for the steps on how to contribute.&lt;/p&gt;

&lt;p&gt;If all your instructions were in your &lt;code&gt;README.md&lt;/code&gt; file, you'd have to say, "Look at my README.md file and look for the contributing section".&lt;/p&gt;

&lt;p&gt;In comparison, if you have a dedicated file to contributing, you can just say, "Please read &lt;code&gt;CONTRIBUTING.md&lt;/code&gt;". That in of itself is a major time saver (believe it or not).&lt;/p&gt;

&lt;p&gt;With regards to the &lt;code&gt;CODE_OF_CONDUCT.md&lt;/code&gt;, it's nice to have a document that explains your expectations of others who interact with your project. Having a document like this serves as a safeguard for you to enforce rules of conduct on your project, and hopefully, gets others to behave properly.&lt;/p&gt;

&lt;p&gt;As such, I would highly recommend creating these files to make your experience as a creator/maintainer of a project seamless.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I don't expect you all to re-invent the wheel when making a &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; file or &lt;code&gt;CODE_OF_CONDUCT.md&lt;/code&gt; file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My Professor, &lt;a href="https://github.com/humphd" rel="noopener noreferrer"&gt;David Humphrey&lt;/a&gt; shared with my class a useful site which &lt;em&gt;generates these files for you&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;That is: &lt;a href="https://generator.contributing.md/" rel="noopener noreferrer"&gt;https://generator.contributing.md/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After discovering this site, I made a &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; file and &lt;code&gt;CODE_OF_CONDUCT.md&lt;/code&gt; file and began simplifying my main &lt;code&gt;README.md&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Below is a screenshot that shows how much clutter was removed from my main &lt;code&gt;README.md&lt;/code&gt; file now that I have dedicated files on how to contribute and how to conduct oneself in my repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7x8ivokoavqylw7u331p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7x8ivokoavqylw7u331p.png" alt="condensed-readme" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For casual users of my tool, I believe this to be a lot less intimidating when trying to get the gist of my repository.&lt;/p&gt;

&lt;p&gt;For people looking to develop, they'll be able to quickly scan my main README.md and know where to find guidelines on how to contribute and conduct themselves.&lt;/p&gt;

&lt;p&gt;Now, I want to talk about adding &lt;code&gt;static analysis tools&lt;/code&gt; to my project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add static analysis tools
&lt;/h2&gt;

&lt;p&gt;Very early on in my project, I added &lt;code&gt;static analysis tools&lt;/code&gt; which are essential utilities that analyze code &lt;em&gt;without&lt;/em&gt; actually running it. These tools help maintain &lt;code&gt;code quality&lt;/code&gt;, &lt;code&gt;consistency&lt;/code&gt;, and &lt;code&gt;catch potential issues&lt;/code&gt; early in development. Below, I have listed different types of &lt;code&gt;static analysis tools&lt;/code&gt; and examples of these tools that I've used in &lt;code&gt;gimme_readme&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: that since static analysis tools are &lt;em&gt;built&lt;/em&gt; to analyze your code, there will be some folders or files that you do &lt;em&gt;not&lt;/em&gt; want them to analyze (to save time in processing). I myself, had to make recent changes on what to ignore to speed up my development.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Linters (ESLint)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Linters&lt;/code&gt; analyze your code for potential errors, suspicious patterns, and style violations. &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; helps enforce coding standards and catch bugs before they make it into production. For example, it can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Detect unused variables&lt;/li&gt;
&lt;li&gt;Find syntax errors&lt;/li&gt;
&lt;li&gt;Enforce consistent code style&lt;/li&gt;
&lt;li&gt;Identify potential runtime errors&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Linters will help you spot potential problem areas when others contribute to your repo. They will often help you spot unneeded code (unused variables), and buggy code.&lt;/p&gt;

&lt;p&gt;Below, is my &lt;code&gt;Eslint&lt;/code&gt; config file, &lt;code&gt;eslint.config.mjs&lt;/code&gt; with explanations on what it's doing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Import predefined global variables for different environments (browser, node, jest, etc.)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;globals&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;globals&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Import ESLint's new flat config for JavaScript (includes recommended rules)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;pluginJs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@eslint/js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="c1"&gt;// First config object: Define file patterns and module settings&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/*.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;           &lt;span class="c1"&gt;// Apply to all JavaScript files&lt;/span&gt;
    &lt;span class="na"&gt;languageOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="na"&gt;sourceType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;        &lt;span class="c1"&gt;// Treat files as ES modules (enables import/export)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; 
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// Include ESLint's recommended ruleset&lt;/span&gt;
  &lt;span class="c1"&gt;// This adds common error-catching rules and best practices&lt;/span&gt;
  &lt;span class="nx"&gt;pluginJs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;configs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recommended&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// Configure language features and global variables&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;languageOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;ecmaVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;latest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// Use the latest ECMAScript features&lt;/span&gt;
      &lt;span class="na"&gt;globals&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="nx"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;commonjs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// Add CommonJS globals (require, module, etc.)&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;es2021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;// Add ES2021 globals&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;// Add Node.js globals&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;// Add Jest testing globals&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="c1"&gt;// Define directories to ignore during linting&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;ignores&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node_modules/**&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;// Third-party dependencies&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_examples/**&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;             &lt;span class="c1"&gt;// Example code directory&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.husky/**&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                &lt;span class="c1"&gt;// Husky git hooks&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.git/**&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                  &lt;span class="c1"&gt;// Git internals&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;coverage/**&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;              &lt;span class="c1"&gt;// Test coverage reports&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;h3&gt;
  
  
  Formatters (Prettier)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Formatters&lt;/code&gt; automatically style your code according to predefined rules. &lt;a href="https://prettier.io/docs/en/install.html" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt; handles all the formatting heavy-lifting, ensuring consistent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Indentation&lt;/li&gt;
&lt;li&gt;Line length&lt;/li&gt;
&lt;li&gt;Quote usage&lt;/li&gt;
&lt;li&gt;Comma placement&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Formatters are particularly helpful to ensure that if multiple people are contributing to your repository, the code "reads the same", since everyone will have their code formatted correctly, using your style guide.&lt;/p&gt;

&lt;p&gt;Below is my &lt;code&gt;.prettierrc&lt;/code&gt; file, that defines the rules I wish to have with regards to formatting my code. &lt;code&gt;Prettier&lt;/code&gt; will look at this file to understand the rules for formatting, and check if my source code files abide by these rules. NOTE: that the comments aren't valid in JSON, but I'm putting them here to explain what they do.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// .prettierrc&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Controls whether parentheses are always added around a single arrow function parameter&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;arrowParens&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;always&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Example: (x) =&amp;gt; x  vs  x =&amp;gt; x&lt;/span&gt;

  &lt;span class="c1"&gt;// Adds spaces between brackets in object literals&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bracketSpacing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// Example: { foo: bar }  vs  {foo: bar}&lt;/span&gt;

  &lt;span class="c1"&gt;// Controls how Prettier formats quoted code embedded in the file&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;embeddedLanguageFormatting&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Automatically formats code inside template literals&lt;/span&gt;

  &lt;span class="c1"&gt;// Line ending style (linefeed only)&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;endOfLine&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Uses \n instead of \r\n (Windows style)&lt;/span&gt;

  &lt;span class="c1"&gt;// Whether to insert a special @format marker at the top of files&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;insertPragma&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Won't add @format marker to formatted files&lt;/span&gt;

  &lt;span class="c1"&gt;// Controls how markdown text is wrapped&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;proseWrap&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;preserve&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Doesn't change wrapping of markdown text&lt;/span&gt;

  &lt;span class="c1"&gt;// Whether to only format files with a special @format marker&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;requirePragma&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Formats all files, not just those with @format marker&lt;/span&gt;

  &lt;span class="c1"&gt;// Use single quotes instead of double quotes&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;singleQuote&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// Example: 'hello'  vs  "hello"&lt;/span&gt;

  &lt;span class="c1"&gt;// Number of spaces per indentation level&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tabWidth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;// Uses 2 spaces for each indent level&lt;/span&gt;

  &lt;span class="c1"&gt;// Adds trailing commas where valid in ES5&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;trailingComma&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;es5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Example: { foo: bar, }  vs  { foo: bar }&lt;/span&gt;

  &lt;span class="c1"&gt;// Whether to use tabs instead of spaces&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;useTabs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;// Uses spaces for indentation&lt;/span&gt;

  &lt;span class="c1"&gt;// Maximum line length before wrapping&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;printWidth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;       &lt;span class="c1"&gt;// Wraps code at 100 characters&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;Prettier&lt;/code&gt;, there is a concept of an &lt;code&gt;ignore&lt;/code&gt; file, which will be used to tell &lt;code&gt;Prettier&lt;/code&gt; which files to avoid when formatting. This file is the &lt;code&gt;.prettierignore&lt;/code&gt; file, and mine is shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Generated files
node_modules/
package.json
package-lock.json
_examples/
.husky/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pre-commit Hooks (Husky)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Pre-commit hooks&lt;/code&gt; are perhaps my favourite &lt;code&gt;static analysis tool&lt;/code&gt; since they can ensure that your &lt;em&gt;other&lt;/em&gt; static analysis tools are being used.&lt;/p&gt;

&lt;p&gt;With regards to &lt;code&gt;git&lt;/code&gt;, a &lt;code&gt;pre-commit hook&lt;/code&gt; runs certain actions &lt;em&gt;prior&lt;/em&gt; to your commit.&lt;/p&gt;

&lt;p&gt;As I explained earlier, we have other static analysis tools such as a linter or formatter - however, there's _nothing enforcing a contributor from linting or formatting their code properly.&lt;/p&gt;

&lt;p&gt;If you set up a &lt;code&gt;pre-commit hook&lt;/code&gt;, you can &lt;em&gt;enforce&lt;/em&gt; that any changes made to your repository (even locally on another user's machine), are formatted and linted properly.&lt;/p&gt;

&lt;p&gt;I use &lt;a href="https://github.com/typicode/husky" rel="noopener noreferrer"&gt;Husky&lt;/a&gt; to write a very simple file that lets me describe the exact steps I want to run before someone commits a change to my repository. This file is found within the &lt;code&gt;.husky&lt;/code&gt; folder, and is called "pre-commit". The content is shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# .husky/pre-commit&lt;/span&gt;
npm run format
npm run lint
npm run &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By looking at this file, you'll see that husky runs the following before a commit:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;a &lt;code&gt;format&lt;/code&gt; script&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;lint&lt;/code&gt; script&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;test&lt;/code&gt; script&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These &lt;code&gt;npm&lt;/code&gt; scripts are defined in my &lt;code&gt;package.json&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node --experimental-vm-modules node_modules/jest/bin/jest.js -c jest.config.js --runInBand"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint --config eslint.config.mjs &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;./src/**/*.js&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;tests/**/*.js&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier --write &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;./src/**/*.js&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;tests/**/*.js&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"coverage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node --experimental-vm-modules node_modules/jest/bin/jest.js -c jest.config.js --runInBand --coverage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prepare"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"husky"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Husky&lt;/code&gt; runs these commands for you before you commit, but users can also run these scripts directly into the command-line themselves.&lt;/p&gt;

&lt;p&gt;The last thing I wanted to talk about was &lt;code&gt;Editor Integration&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;To make development smoother, I've included VSCode configuration files:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;.vscode/extensions.json&lt;/code&gt;: Suggests recommended extensions for the project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"recommendations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"esbenp.prettier-vscode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"dbaeumer.vscode-eslint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"streetsidesoftware.code-spell-checker"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.vscode/settings.json&lt;/code&gt;: Ensures consistent editor settings across the team&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.insertSpaces"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.tabSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.detectIndentation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.defaultFormatter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esbenp.prettier-vscode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.codeActionsOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source.fixAll"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"explicit"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"files.eol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"files.insertFinalNewline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.vscode/javascript.code-snippets&lt;/code&gt;: lets us define shortcuts that will type out repetitive pieces of code with a few characters. I made my own snippet which will print out a file path like &lt;code&gt;// src/ai/ai.js&lt;/code&gt; in a JavaScript file when the user writes &lt;code&gt;rpath&lt;/code&gt; in that file and presses "Enter".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Insert Current File Path Comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rpath"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"// ${RELATIVE_FILEPATH/[&lt;/span&gt;&lt;span class="se"&gt;\\\\&lt;/span&gt;&lt;span class="s2"&gt;]/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;//g}"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Inserts a comment with the relative path of the current file"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These files help new contributors get set up quickly with the right tools and settings.&lt;/p&gt;

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

&lt;p&gt;Implementing these best practices early in your open source project sets a strong foundation for both you and your future contributors. From establishing clear licensing and documentation structure to setting up robust &lt;code&gt;static analysis tools&lt;/code&gt;, each element plays a crucial role in creating a professional and maintainable codebase.&lt;/p&gt;

&lt;p&gt;While it might seem like a lot of upfront work, having proper licensing, well-organized documentation (&lt;code&gt;README.md&lt;/code&gt;, &lt;code&gt;CONTRIBUTING.md&lt;/code&gt;, &lt;code&gt;CODE_OF_CONDUCT.md&lt;/code&gt;), and automated tools (&lt;code&gt;ESLint&lt;/code&gt;, &lt;code&gt;Prettier&lt;/code&gt;, &lt;code&gt;Husky&lt;/code&gt;) will save countless hours of manual work and reduce potential friction in the development process. These practices not only make your project more approachable for contributors but also help maintain high code quality as your project grows.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember: it's much easier to establish these practices at the start than to retrofit them into an existing project. Whether you're building a small tool or planning for a larger open source project, taking the time to implement these configurations early will pay dividends in the long run.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Just take a look at how many commits I needed to do to fix my project (if you set this up early, there will be less work in the future, I promise!):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmcag2rfz245kplrs4xkt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmcag2rfz245kplrs4xkt.png" alt="before-rebasing" width="800" height="952"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was too much for me to stare at, so I decided to squash my commits into one like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvdnl42tink1eo5rju2a1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvdnl42tink1eo5rju2a1.png" alt="after-rebasing" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With that, that's pretty much everything I wanted to cover - organize your documents early and use &lt;code&gt;static analysis tools&lt;/code&gt;. Happy programming!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Devlog: Hacktoberfest 2024 (4/4)</title>
      <dc:creator>Peter Wan</dc:creator>
      <pubDate>Sat, 26 Oct 2024 01:23:34 +0000</pubDate>
      <link>https://dev.to/peterdanwan/devlog-hacktoberfest-2024-44-k2m</link>
      <guid>https://dev.to/peterdanwan/devlog-hacktoberfest-2024-44-k2m</guid>
      <description>&lt;p&gt;Hello all! This is my final &lt;a href="https://hacktoberfest.com/" rel="noopener noreferrer"&gt;Hacktoberfest&lt;/a&gt; devlog for 2024.&lt;/p&gt;

&lt;p&gt;To get more context with regards to this devlog, please see my other devlogs below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/peterdanwan/devlog-hacktoberfest-2024-14-23b"&gt;Devlog: Hacktoberfest 2024 (1/4)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/peterdanwan/devlog-hacktoberfest-2024-24-32ja"&gt;Devlog: Hacktoberfest 2024 (2/4)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/peterdanwan/devlog-hacktoberfest-2024-34-44f"&gt;Devlog: Hacktoberfest 2024 (3/4)&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this final week of Hacktoberfest 2024, I wanted to challenge myself by contributing to &lt;em&gt;larger&lt;/em&gt; open source projects. Specifically, I wanted to provide a pull request that involves a fix or a feature that is larger than just fixing a spelling mistake.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At the time of writing, I have made several pull requests, none of which have currently been merged or seen yet by the maintainers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The work I did this week fell into several categories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;logging new issues for projects&lt;/li&gt;
&lt;li&gt;requesting information on how to get started with an issue I logged, or requesting advice on fixing an existing issue&lt;/li&gt;
&lt;li&gt;creating pull requests for issues that I felt like I had enough information to make an attempt&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Logging new issues for projects
&lt;/h2&gt;

&lt;p&gt;All the issues I worked on this week were related to Visual Studio Code extensions, since Visual Studio Code is my text-editor of choice.&lt;/p&gt;

&lt;p&gt;One of the extensions that I use makes working with &lt;code&gt;markdown&lt;/code&gt; easier. This extension is called, &lt;code&gt;Markdown All in One&lt;/code&gt; on VSCode, but is known as &lt;a href="https://github.com/yzhang-gh/vscode-markdown" rel="noopener noreferrer"&gt;vscode-markdown&lt;/a&gt; on GitHub. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Markdown All in One&lt;/code&gt; has a feature I really like, which is to convert markdown into HTML, but I noticed that I was having an issue where the conversion wasn't working how it used to.&lt;/p&gt;

&lt;p&gt;It turns out that because I had another extension called, &lt;code&gt;Markdown Preview Mermaid Support&lt;/code&gt; in Visual Studio Code enabled (known as &lt;a href="https://github.com/mjbvz/vscode-markdown-mermaid" rel="noopener noreferrer"&gt;vscode-markdown-mermaid&lt;/a&gt; on GitHub), I was unable to use the &lt;code&gt;Markdown All In One&lt;/code&gt;'s feature properly.&lt;/p&gt;

&lt;p&gt;To that end, I logged 2 issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;One for &lt;a href="https://github.com/yzhang-gh/vscode-markdown/issues/1476" rel="noopener noreferrer"&gt;Markdown All In One&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Another for &lt;a href="https://github.com/mjbvz/vscode-markdown-mermaid" rel="noopener noreferrer"&gt;Markdown Preview Mermaid Support&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While I have yet to hear back from &lt;code&gt;Markdown All In One&lt;/code&gt; from the time of writing, I was able to get a quick response from the maintainer of &lt;code&gt;Markdown Preview Mermaid Support&lt;/code&gt; that this issue would not be investigated further because as of right now, the Markdown Preview Mermaid Support is only built to support the base Visual Studio Code settings.&lt;/p&gt;

&lt;p&gt;So despite doing my best to log an issue and reproduce the problem, I was not able to gain enough information as of yet to contribute further to resolving this issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Requesting information on how to get started with an issue I logged or on an existing issue
&lt;/h2&gt;

&lt;p&gt;My next step was trying to find existing issues on projects that I was interested in. I wanted to follow-up on an issue logged for &lt;code&gt;Plasmo&lt;/code&gt;, a framework which is a framework for building browser extensions using React and TypeScript. &lt;/p&gt;

&lt;p&gt;I found this &lt;a href="https://github.com/PlasmoHQ/plasmo/issues/658#issuecomment-2433289258" rel="noopener noreferrer"&gt;issue&lt;/a&gt;, which had the issue of &lt;code&gt;good first issue&lt;/code&gt;. I had no idea how to work on this issue at all, but I wanted to make an attempt to at least set up my development environment so I went straight to Plasmo's guide on &lt;a href="https://github.com/PlasmoHQ/plasmo/blob/main/.github/CONTRIBUTING.md" rel="noopener noreferrer"&gt;how to contribute&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I found a small grammatical mistake which I thought I could fix quickly as I was tackling the main issue, so I raised an &lt;a href="https://github.com/PlasmoHQ/plasmo/issues/1121" rel="noopener noreferrer"&gt;issue&lt;/a&gt; and made a &lt;a href="https://github.com/PlasmoHQ/plasmo/pull/1122" rel="noopener noreferrer"&gt;pull request to fix the issue&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I didn't get a response for my pull request that fixes the grammatical mistake, or any word on how to tackle the original issue in question, but hope to soon.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Creating some pull requests when I had enough information to work off of
&lt;/h2&gt;

&lt;p&gt;Because of how hard it was for me to find an issue that I could actually contribute to, I reached out to my Professor for some guidance. He was able to find &lt;a href="https://github.com/streetsidesoftware/vscode-spell-checker/issues/2409" rel="noopener noreferrer"&gt;this issue&lt;/a&gt; for a Visual Studio Code extension that I use every day - a spell checker. In Visual Studio Code, the extension is known as &lt;code&gt;Code Spell Checker&lt;/code&gt;, and on GitHub, the repository is called, &lt;br&gt;
&lt;a href="https://github.com/streetsidesoftware/vscode-spell-checker" rel="noopener noreferrer"&gt;vscode-spell-checker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After taking the time to sit with the code and go through some of the commit history, I was able to find another &lt;a href="https://github.com/streetsidesoftware/vscode-spell-checker/pull/2133" rel="noopener noreferrer"&gt;pull request&lt;/a&gt; that contained a solution that I think was essentially what I needed to do in my very own pull request.&lt;/p&gt;

&lt;p&gt;As such, I studied the changes made in that pull request, and made my &lt;a href="https://github.com/streetsidesoftware/vscode-spell-checker/pull/3729" rel="noopener noreferrer"&gt;own pull request&lt;/a&gt; which references the fix from the other pull request.&lt;/p&gt;

&lt;p&gt;And with that, I had finally made a contribution that in my mind, met the requirements that I was trying to meet, which was to contribute to a large open-source project and contribute something other than a fix for a simple spelling mistake. &lt;/p&gt;

&lt;p&gt;While this pull request still hasn't been processed by a maintainer, I am hopeful that the fix will go well, given that I more or less followed the example from one of the maintainer's commits.&lt;/p&gt;

&lt;p&gt;With all of this said - I want to conclude this series of devlogs for Hactkoberfest 2024.&lt;/p&gt;

&lt;p&gt;It was a great experience working on small, medium, and large sized projects. I feel like I've gained a little bit more mastery over &lt;code&gt;git&lt;/code&gt; and &lt;code&gt;GitHub&lt;/code&gt;, and know how to use these tools to my advantage now. In addition, I feel a lot more comfortable searching for solutions and reading code, by virtue of viewing all sorts of different open source repositories.&lt;/p&gt;

&lt;p&gt;My immediate hope is to get some feedback from the maintainers for the different issues/pull requests I currently made, but my long-term hope is that in the near future, I can work more closely with a repository of my choosing, and make important and vital changes/improvements that will better the repository and help its community of users.&lt;/p&gt;

</description>
      <category>git</category>
      <category>vscode</category>
      <category>extensions</category>
      <category>hacktoberfest2024</category>
    </item>
    <item>
      <title>Devlog: Hacktoberfest 2024 (4/4)</title>
      <dc:creator>Peter Wan</dc:creator>
      <pubDate>Sat, 26 Oct 2024 01:23:34 +0000</pubDate>
      <link>https://dev.to/peterdanwan/devlog-hacktoberfest-2024-44-118d</link>
      <guid>https://dev.to/peterdanwan/devlog-hacktoberfest-2024-44-118d</guid>
      <description>&lt;p&gt;Hello all! This is my final &lt;a href="https://hacktoberfest.com/" rel="noopener noreferrer"&gt;Hacktoberfest&lt;/a&gt; devlog for 2024.&lt;/p&gt;

&lt;p&gt;To get more context with regards to this devlog, please see my other devlogs below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dev.to/peterdanwan/devlog-hacktoberfest-2024-14-23b"&gt;Devlog: Hacktoberfest 2024 (1/4)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/peterdanwan/devlog-hacktoberfest-2024-24-32ja"&gt;Devlog: Hacktoberfest 2024 (2/4)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/peterdanwan/devlog-hacktoberfest-2024-34-44f"&gt;Devlog: Hacktoberfest 2024 (3/4)&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this final week of Hacktoberfest 2024, I wanted to challenge myself by contributing to &lt;em&gt;larger&lt;/em&gt; open source projects. Specifically, I wanted to provide a pull request that involves a fix or a feature that is larger than just fixing a spelling mistake.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At the time of writing, I have made several pull requests, none of which have currently been merged or seen yet by the maintainers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The work I did this week fell into several categories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;logging new issues for projects&lt;/li&gt;
&lt;li&gt;requesting information on how to get started with an issue I logged, or requesting advice on fixing an existing issue&lt;/li&gt;
&lt;li&gt;creating pull requests for issues that I felt like I had enough information to make an attempt&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Logging new issues for projects
&lt;/h2&gt;

&lt;p&gt;All the issues I worked on this week were related to Visual Studio Code extensions, since Visual Studio Code is my text-editor of choice.&lt;/p&gt;

&lt;p&gt;One of the extensions that I use makes working with &lt;code&gt;markdown&lt;/code&gt; easier. This extension is called, &lt;code&gt;Markdown All in One&lt;/code&gt; on VSCode, but the is known as &lt;a href="https://github.com/yzhang-gh/vscode-markdown" rel="noopener noreferrer"&gt;vscode-markdown&lt;/a&gt; on GitHub. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Markdown All in One&lt;/code&gt; has a feature I really like, which is to convert markdown into HTML, but I noticed that I was having an issue where the conversion wasn't working how it used to.&lt;/p&gt;

&lt;p&gt;It turns out that because I had another extension called, &lt;code&gt;Markdown Preview Mermaid Support&lt;/code&gt; in Visual Studio Code enabled &lt;a href="https://github.com/mjbvz/vscode-markdown-mermaid" rel="noopener noreferrer"&gt;vscode-markdown-mermaid&lt;/a&gt;, I was unable to use the &lt;code&gt;Markdown All In One&lt;/code&gt;'s feature properly&lt;/p&gt;

&lt;p&gt;To that end, I logged 2 issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;One for &lt;a href="https://github.com/yzhang-gh/vscode-markdown/issues/1476" rel="noopener noreferrer"&gt;Markdown All In One&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Another for &lt;a href="https://github.com/mjbvz/vscode-markdown-mermaid" rel="noopener noreferrer"&gt;Markdown Preview Mermaid Support&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While I have yet to hear back from &lt;code&gt;Markdown All In One&lt;/code&gt; from the time of writing, I was able to get a quick response from the maintainer of &lt;code&gt;Markdown Preview Mermaid Support&lt;/code&gt; that this issue would not be investigated further because as of right now, the Markdown Preview Mermaid Support is only built to support the base Visual Studio Code settings.&lt;/p&gt;

&lt;p&gt;So despite doing my best to log an issue and reproduce the problem, I was not able to gain enough information as of yet to contribute further to resolving this issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Requesting information on how to get started with an issue I logged or on an existing issue
&lt;/h2&gt;

&lt;p&gt;My next step was trying to find existing issues on projects that I was interested in. I wanted to follow-up on an issue logged for &lt;code&gt;Plasmo&lt;/code&gt;, a framework which is a framework for building browser extensions using React and TypeScript. &lt;/p&gt;

&lt;p&gt;I found this &lt;a href="https://github.com/PlasmoHQ/plasmo/issues/658#issuecomment-2433289258" rel="noopener noreferrer"&gt;issue&lt;/a&gt;, which had the issue of &lt;code&gt;good first issue&lt;/code&gt;. I had no idea how to work on this issue at all, but I wanted to make an attempt to at least set up my development environment so I went straight to Plasmo's guide on &lt;a href="https://github.com/PlasmoHQ/plasmo/blob/main/.github/CONTRIBUTING.md" rel="noopener noreferrer"&gt;how to contribute&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I found a small grammatical mistake which I thought I could fix quickly as I was tackling the main issue, so I raised an &lt;a href="https://github.com/PlasmoHQ/plasmo/issues/1121" rel="noopener noreferrer"&gt;issue&lt;/a&gt; and made a &lt;a href="https://github.com/PlasmoHQ/plasmo/pull/1122" rel="noopener noreferrer"&gt;pull request to fix the issue&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I didn't get a response for my pull request that fixes the grammatical mistake, or any word on how to tackle the original issue in question, but hope to soon.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Creating some pull requests when I had enough information to work off of
&lt;/h2&gt;

&lt;p&gt;Because of how hard it was for me to find an issue that I could actually contribute to, I reached out to my Professor for some guidance. He was able to find &lt;a href="https://github.com/streetsidesoftware/vscode-spell-checker/issues/2409" rel="noopener noreferrer"&gt;this issue&lt;/a&gt; for a Visual Studio Code extension that I use every day - a spell checker. In Visual Studio Code, the extension is known as &lt;code&gt;Code Spell Checker&lt;/code&gt;, and on GitHub, the repository is called, &lt;br&gt;
&lt;a href="https://github.com/streetsidesoftware/vscode-spell-checker" rel="noopener noreferrer"&gt;vscode-spell-checker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After taking the time to sit with the code and go through some of the commit history, I was able to find another &lt;a href="https://github.com/streetsidesoftware/vscode-spell-checker/pull/2133" rel="noopener noreferrer"&gt;pull request&lt;/a&gt; that contained a solution that I think was essentially what I needed to do in my very own pull request.&lt;/p&gt;

&lt;p&gt;As such, I studied the changes made in that pull request, and made my &lt;a href="https://github.com/streetsidesoftware/vscode-spell-checker/pull/3729" rel="noopener noreferrer"&gt;own pull request&lt;/a&gt; which references the fix from the other pull request.&lt;/p&gt;

&lt;p&gt;And with that, I had finally made a contribution that in my mind, met the requirements that I was trying to meet, which was to contribute to a large open-source project and contribute something other than a fix for a simple spelling mistake. &lt;/p&gt;

&lt;p&gt;While this pull request still hasn't been processed by a maintainer, I am hopeful that the fix will go well, given that I more or less followed the example from one of the maintainer's commits.&lt;/p&gt;

&lt;p&gt;With all of this said - I want to conclude this series of devlogs for Hactkoberfest 2024.&lt;/p&gt;

&lt;p&gt;It was a great experience working on small, medium, and large sized projects. I feel like I've gained a little bit more mastery over &lt;code&gt;git&lt;/code&gt; and &lt;code&gt;GitHub&lt;/code&gt;, and know how to use these tools to my advantage now. In addition, I feel a lot more comfortable searching for solutions and reading code, by virtue of viewing all sorts of different open source repositories.&lt;/p&gt;

&lt;p&gt;My immediate hope is to get some feedback from the maintainers for the different issues/pull requests I currently made, but my long-term hope is that in the near future, I can work more closely with a repository of my choosing, and make important and vital changes/improvements that will better the repository and help its community of users.&lt;/p&gt;

</description>
      <category>git</category>
      <category>vscode</category>
      <category>extensions</category>
      <category>hacktoberfest2024</category>
    </item>
  </channel>
</rss>
