<?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>Forem: Piyush Kumar Baliyan</title>
    <description>The latest articles on Forem by Piyush Kumar Baliyan (@piyushkmr).</description>
    <link>https://forem.com/piyushkmr</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%2F130627%2F24150c90-bb4a-4f8e-a4b5-a378f9130cf2.jpg</url>
      <title>Forem: Piyush Kumar Baliyan</title>
      <link>https://forem.com/piyushkmr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/piyushkmr"/>
    <language>en</language>
    <item>
      <title>Supercharge Your Buttons: Simplifying Loading State with less boilerplate</title>
      <dc:creator>Piyush Kumar Baliyan</dc:creator>
      <pubDate>Tue, 06 Jun 2023 01:12:03 +0000</pubDate>
      <link>https://forem.com/piyushkmr/supercharge-your-buttons-simplifying-loading-state-with-less-boilerplate-fda</link>
      <guid>https://forem.com/piyushkmr/supercharge-your-buttons-simplifying-loading-state-with-less-boilerplate-fda</guid>
      <description>&lt;p&gt;As web developers, we all know the importance of buttons in our applications. Whether it's submitting a form, triggering an action, or making an API call, buttons play a crucial role in driving user interactions. However, when it comes to adding asynchronous code to button clicks, such as performing an API call and waiting for the result, we tend to get lazy, or forget to add it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem for users
&lt;/h2&gt;

&lt;p&gt;Have you ever encountered a situation where the button appeared stuck or unresponsive while waiting for the asynchronous operation to complete? It happens to the best of us. In the heat of coding, it's easy to forget to add the necessary loading state to our buttons, leaving users confused and frustrated.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore a simple yet powerful approach to enhance button functionality, specifically focusing on streamlining the loading state. Although we'll be using React as our example framework, these techniques can be applied to any web development framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Loading State to Buttons
&lt;/h3&gt;

&lt;p&gt;Let's begin by understanding the typical workflow involved in adding asynchronous, continuously running code to a button click:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user clicks the button, initiating the action.&lt;/li&gt;
&lt;li&gt;We set the loading state to true, indicating that the button is in progress.&lt;/li&gt;
&lt;li&gt;We start performing the asynchronous code, such as making an API call.&lt;/li&gt;
&lt;li&gt;Once the operation completes, we update the loading state to false.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;However, every time we need to incorporate this functionality, we find ourselves writing repetitive boilerplate code. Moreover, overlooking the loading state can lead to poor user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simplifying Button Loading
&lt;/h2&gt;

&lt;p&gt;To address these challenges and make the button loading experience easier to handle, we need an intuitive API and less boilerplate code.&lt;/p&gt;

&lt;p&gt;Let's take a look at a typical button code snippet in React:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&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;Button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;APIButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setLoading&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="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;submitFormToBackend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;setLoading&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="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;btn-loading&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;btn-error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Label
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;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;This code demonstrates a common pattern where we manually manage the loading and error states while handling the button click. However, it seems like too much boilerplate (I am lazy to write a few extra key-strokes).&lt;/p&gt;

&lt;h2&gt;
  
  
  Streamlining Button Loading with an Enhanced Component
&lt;/h2&gt;

&lt;p&gt;To make the button loading state easier to manage, we can modify the button component itself. The goal is not to clutter our button code but to complement it in a way that still keeps our code readable and maintainable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Imagine treating the button as an input field with disabled, busy, and error states.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's enhance the button component to handle loading internally and simplify our code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ButtonProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLButtonElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FunctionComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ButtonProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLButtonElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clickResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;?.(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// If our onClick returns a Promise, handle the loading states&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clickResult&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;setLoading&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="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;clickResult&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unauthorized&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;setLoading&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="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttonClasses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;classnames&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;btn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;btn-loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;btn-error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;buttonEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
      &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buttonClasses&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;progressbar&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="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;buttonEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tooltip&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"danger"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buttonEl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Tooltip&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;buttonEl&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;With this enhanced button component, we have a more powerful and intuitive way of managing loading and error states. The component takes care of the loading state internally, allowing us to focus on writing cleaner and more concise code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing the Supercharged Button
&lt;/h3&gt;

&lt;p&gt;Now, let's see how our new and improved button can simplify our code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&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;Button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;APIButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;submitFormToBackend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unauthorized&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Label
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;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;By simply returning the promise from our &lt;code&gt;handleClick&lt;/code&gt; function, we can effortlessly incorporate loading and error states. It's a single additional word that significantly simplifies our code and improves the user experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Taking Control of Loading and Error States
&lt;/h3&gt;

&lt;p&gt;The promisified Button component we've built empowers us to handle different scenarios effectively:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If we don't want to show the loading state without a promise, we can simply omit the promise return from the handleClick function.&lt;/li&gt;
&lt;li&gt;If we want to display the loading state but without an error tooltip, we can return the promise but catch the error, preventing the Button component from catching them.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;In this article, we've explored how to supercharge our buttons by streamlining the loading state. By enhancing our button component, we can simplify the process, reduce boilerplate code, and provide a smoother user experience.&lt;/p&gt;

&lt;p&gt;Lets contiue the discussion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is there any issues that you can find with this approach?&lt;/li&gt;
&lt;li&gt;Let me know about your favorite mini-hacks that have eased your development process.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>ux</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Get the Most Out of Google Docs with These URL Tricks</title>
      <dc:creator>Piyush Kumar Baliyan</dc:creator>
      <pubDate>Tue, 15 Feb 2022 03:38:46 +0000</pubDate>
      <link>https://forem.com/admitkard/google-docs-url-tricks-and-tips-4d44</link>
      <guid>https://forem.com/admitkard/google-docs-url-tricks-and-tips-4d44</guid>
      <description>&lt;h2&gt;
  
  
  Google Docs
&lt;/h2&gt;

&lt;p&gt;Google docs come with some neat URL tricks to use them according to your need.&lt;/p&gt;

&lt;p&gt;Here we go...&lt;/p&gt;

&lt;p&gt;Create new document directly from URL:&lt;br&gt;
&lt;a href="https://docs.new" rel="noopener noreferrer"&gt;https://docs.new&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are signed in with multiple accounts, then &lt;code&gt;https://docs.new/2&lt;/code&gt; will create new document with 2nd account, &lt;code&gt;/3&lt;/code&gt; for 3rd account, and so on.&lt;/p&gt;

&lt;p&gt;This is the document that I get now, and we will use this for our tricks:&lt;br&gt;
&lt;a href="https://docs.google.com/document/d/1emMkr2qXskGDrHtRRrBwUVDNgQYXjtRYW7zTXuHyAak/edit#" rel="noopener noreferrer"&gt;https://docs.google.com/document/d/1emMkr2qXskGDrHtRRrBwUVDNgQYXjtRYW7zTXuHyAak/edit#&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Url Tricks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.google.com/document/d/1emMkr2qXskGDrHtRRrBwUVDNgQYXjtRYW7zTXuHyAak/preview" rel="noopener noreferrer"&gt;/preview&lt;/a&gt;
Non-editable, no menubar, no toolbar, no ruler, just plain page&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.google.com/document/d/1emMkr2qXskGDrHtRRrBwUVDNgQYXjtRYW7zTXuHyAak/copy" rel="noopener noreferrer"&gt;/copy&lt;/a&gt;
Opens a copy of the document, editable by the user, directly from the URL.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.google.com/document/d/1emMkr2qXskGDrHtRRrBwUVDNgQYXjtRYW7zTXuHyAak/export?format=pdf" rel="noopener noreferrer"&gt;/export?format=pdf&lt;/a&gt;
Directly download a pdf of the document.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.google.com/document/d/1emMkr2qXskGDrHtRRrBwUVDNgQYXjtRYW7zTXuHyAak/view?rm=embedded" rel="noopener noreferrer"&gt;/view?rm=embedded&lt;/a&gt;
No title of the document, editable. Good for embedding in iframes.
&lt;img src="https://media.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%2Fpfac2gf4e4x5e6z7vw1d.png" alt="Hides the title of the document"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.google.com/document/d/1emMkr2qXskGDrHtRRrBwUVDNgQYXjtRYW7zTXuHyAak/view?rm=minimal" rel="noopener noreferrer"&gt;/view?rm=minimal&lt;/a&gt;
No title, no menubar, no toolbar, only the ruler and page, editable. Good for distraction free minimal editor.
-&lt;a href="https://docs.google.com/document/d/1emMkr2qXskGDrHtRRrBwUVDNgQYXjtRYW7zTXuHyAak/view?rm=demo" rel="noopener noreferrer"&gt;/view?rm=demo&lt;/a&gt;
No titlebar, no menubar. Shows the toolbar. Good for a editor with basic controls.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Google Sheets
&lt;/h2&gt;

&lt;h3&gt;
  
  
  New Sheet
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://sheet.new" rel="noopener noreferrer"&gt;https://sheet.new&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the sheet that we will work with&lt;br&gt;
&lt;a href="https://docs.google.com/spreadsheets/d/1ZpHY0TMkX_f1jNVSx_Rs0ieTE5yg8djLYvNDs4ZUwmA/edit#gid=0" rel="noopener noreferrer"&gt;https://docs.google.com/spreadsheets/d/1ZpHY0TMkX_f1jNVSx_Rs0ieTE5yg8djLYvNDs4ZUwmA/edit#gid=0&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.google.com/spreadsheets/d/1ZpHY0TMkX_f1jNVSx_Rs0ieTE5yg8djLYvNDs4ZUwmA/preview" rel="noopener noreferrer"&gt;/preview&lt;/a&gt;&lt;br&gt;
Shows only the sheet (no title, no toolbar, no menubar, no cellnumbers). Good to use where only html is supported.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.google.com/spreadsheets/d/1ZpHY0TMkX_f1jNVSx_Rs0ieTE5yg8djLYvNDs4ZUwmA/view?rm=demo" rel="noopener noreferrer"&gt;/view?rm=demo&lt;/a&gt;&lt;br&gt;
No titlebar, no menubar. Shows editor toolbar and formular bar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.google.com/spreadsheets/d/1ZpHY0TMkX_f1jNVSx_Rs0ieTE5yg8djLYvNDs4ZUwmA/view?rm=minimal" rel="noopener noreferrer"&gt;/view?rm=minimal&lt;/a&gt;&lt;br&gt;
No titlebar, no menubar, no toolbar, no formulabar, just shows the sheet. Good for showing data in spreadsheet format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.google.com/spreadsheets/d/1ZpHY0TMkX_f1jNVSx_Rs0ieTE5yg8djLYvNDs4ZUwmA/view?rm=embedded" rel="noopener noreferrer"&gt;/view?rm=embedded&lt;/a&gt;&lt;br&gt;
No titlebar, shows menubar, toolbar, formulabar. Good for embedding in websites.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Google Slides
&lt;/h2&gt;

&lt;h3&gt;
  
  
  New Slides
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://slides.new" rel="noopener noreferrer"&gt;https://slides.new&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the slides that we will be working with:&lt;br&gt;
&lt;a href="https://docs.google.com/presentation/d/1X2_R8KWIadEId964QiyhLdjIH39dxTP1zOj621yWu4A/edit" rel="noopener noreferrer"&gt;https://docs.google.com/presentation/d/1X2_R8KWIadEId964QiyhLdjIH39dxTP1zOj621yWu4A/edit&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.google.com/presentation/d/1X2_R8KWIadEId964QiyhLdjIH39dxTP1zOj621yWu4A/preview" rel="noopener noreferrer"&gt;/preview&lt;/a&gt;&lt;br&gt;
Shows the slides and presentation control only.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.google.com/presentation/d/1X2_R8KWIadEId964QiyhLdjIH39dxTP1zOj621yWu4A/view?rm=embedded" rel="noopener noreferrer"&gt;/view?rm=embedded&lt;/a&gt;&lt;br&gt;
No title and share controls.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>beginners</category>
      <category>googledocs</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Auto generate unique Avatar colors randomly</title>
      <dc:creator>Piyush Kumar Baliyan</dc:creator>
      <pubDate>Sat, 29 Jan 2022 15:27:27 +0000</pubDate>
      <link>https://forem.com/admitkard/auto-generate-avatar-colors-randomly-138j</link>
      <guid>https://forem.com/admitkard/auto-generate-avatar-colors-randomly-138j</guid>
      <description>&lt;p&gt;&lt;a href="https://media.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%2F0hzcgx07cc8o4p4wmx4f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F0hzcgx07cc8o4p4wmx4f.png" alt="JIRA Avatar colors"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;This is how JIRA shows each user avatar&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;br&gt;
Think for a moment about when you visit online discussion forums. Many of the users don't have any profile pic uploaded. Instead, there are just initials and background colors for the User Avatar.

&lt;p&gt;And anytime you refresh, the background color remains the same.&lt;br&gt;
Now take a second to think about how is this done.&lt;/p&gt;



&lt;center&gt;**TLDR; Using string hash**&lt;/center&gt;



&lt;p&gt;There can be two straightforward ways to do it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can store a background color, for each user in DB, and fetch every time with other user details
OR&lt;/li&gt;
&lt;li&gt;Generate a unique (but consistent) background color based on some unique user attribute (like email, username, or userID).&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Let's start on #2.
&lt;/h4&gt;
&lt;h2&gt;
  
  
  Generate random color
&lt;/h2&gt;

&lt;p&gt;Let's first learn some basics of CSS Colors in the webpage. And we will follow the following journey to do this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn about CSS color formats&lt;/li&gt;
&lt;li&gt;Choose a color format&lt;/li&gt;
&lt;li&gt;Basics of string hashing&lt;/li&gt;
&lt;li&gt;Normalize hash&lt;/li&gt;
&lt;li&gt;Generate unique CSS color using Hash&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  CSS color Formats
&lt;/h3&gt;

&lt;p&gt;From &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color" rel="noopener noreferrer"&gt;this MDN page&lt;/a&gt;, we can figure out the common CSS color formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Named Colors

&lt;ul&gt;
&lt;li&gt;red, green, blue, aqua&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RGB Hex

&lt;ul&gt;
&lt;li&gt;#RRGGBB or #RGB&lt;/li&gt;
&lt;li&gt;#3b49df is blue, #333 is dark-grey&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;rgb() function

&lt;ul&gt;
&lt;li&gt;rgb(255, 255, 255) is white&lt;/li&gt;
&lt;li&gt;rgba() for additional alpha (transparency) value&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;hsl() function

&lt;ul&gt;
&lt;li&gt;hsl is Hue-Saturation-Lightness&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hue&lt;/strong&gt; - is for choosing color using the degree&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Saturation&lt;/strong&gt; - less saturation is grey, more saturation is bright color&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lightness&lt;/strong&gt; - less lightness is black, more lightness is white&lt;/li&gt;
&lt;li&gt;hsla(), for additional alpha value
&lt;img src="https://media.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%2Fh0n622tz98b5ygz4jt9k.png" alt="HSL Color wheel"&gt;
There are some others, but we will stop here.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Choosing color format
&lt;/h3&gt;

&lt;p&gt;Now, we can go with RGB and HSL both, but for the task at hand, HSL is comparatively easier to work with. ¯\_(ツ)_/¯ &lt;em&gt;Why, you ask?&lt;/em&gt; Trust me...&lt;br&gt;
And, you will find in end of article.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating string hash
&lt;/h3&gt;

&lt;p&gt;Now we need to reduce a string to a simple number so that we can use that number to generate our color.&lt;br&gt;
I'll dive deep into hashing in a different article (&lt;em&gt;I mean, come-on... Computer Science community have dedicated huge time to create better hashing functions&lt;/em&gt;). But let's take an overview of what hash is.&lt;/p&gt;

&lt;p&gt;From &lt;a href="https://www.educative.io/edpresso/what-is-hashing" rel="noopener noreferrer"&gt;educative.io&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hashing is the process of converting a given key into another value. A hash function is used to generate the new value according to a mathematical algorithm. The result of a hash function is known as a hash value or simply, a hash.&lt;br&gt;
&lt;a href="https://media.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%2Fsjujumt43rjuxzgqc7el.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fsjujumt43rjuxzgqc7el.png" alt="Hash function block diagram"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's understand by an example and taking a string: &lt;code&gt;Piyush Kumar Baliyan&lt;/code&gt;. &lt;em&gt;Don't take this to be a definitive article about hashing. I am still learning about hashing and only know the basics.&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Attempt 1
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getHashOfString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getHashOfString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Piyush Kumar Baliyan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;//20&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;This is a super simple hash function, but it has very high chances of a conflict. (Conflict is when two different strings can generate the same hash).&lt;/p&gt;
&lt;h4&gt;
  
  
  Attempt 2
&lt;/h4&gt;

&lt;p&gt;Lets modify the function to calculate the total of character code of each character in the string.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getHashOfString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;charArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;charArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charCodeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getHashOfString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Piyush Kumar Baliyan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 1922&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;This is better hashing as it has fewer chances of conflict, but any string that has the same characters will result in conflict.&lt;/p&gt;
&lt;h4&gt;
  
  
  Attempt 3
&lt;/h4&gt;

&lt;p&gt;Now, lets take total of &lt;code&gt;charCode*index&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getHashOfString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;charArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;charArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charCodeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;0&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getHashOfString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Piyush Kumar Baliyan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 18329&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;This is better and has fewer chances of a conflict.&lt;/p&gt;

&lt;p&gt;But this becomes a problem as this number (charCode*index) can become very large for large strings, and can still conflict &lt;em&gt;Maths (╯°□°)╯︵ ┻━┻&lt;/em&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Attempt 4
&lt;/h4&gt;
&lt;h4&gt;
  
  
  Attempt 5
&lt;/h4&gt;
&lt;h4&gt;
  
  
  .
&lt;/h4&gt;
&lt;h4&gt;
  
  
  .
&lt;/h4&gt;
&lt;h4&gt;
  
  
  .
&lt;/h4&gt;
&lt;h4&gt;
  
  
  Attempt x-1
&lt;/h4&gt;

&lt;p&gt;Little better, but still no-where near to the actual hashing algos like md5 and sha.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getHashOfString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charCodeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getHashOfString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Piyush Kumar Baliyan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 3206952792&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Normalize Hash
&lt;/h3&gt;

&lt;p&gt;Now we have a hashing algo, but it returns any number, and we need numbers like these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hue&lt;/strong&gt; 0-360&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Saturation&lt;/strong&gt; 0-100&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lightness&lt;/strong&gt; 0-100&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let's create a function &lt;code&gt;normalize&lt;/code&gt; to get the hash number to within our range.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;normalizeHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalizeHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;360&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;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalizeHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&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;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalizeHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Generate Unique Color
&lt;/h3&gt;

&lt;p&gt;Now, we simply create a string using our &lt;code&gt;h,s,l&lt;/code&gt; values.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hRange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;360&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;sRange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&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;lRange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&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;generateHSL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;HSL&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getHashOfString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&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;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalizeHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hRange&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;hRange&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalizeHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sRange&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;sRange&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalizeHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lRange&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;lRange&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;HSLtoString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HSL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`hsl(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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="nx"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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="nx"&gt;hsl&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="s2"&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;Here is what the output looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F0gy3476ny1pgqiajxl9d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F0gy3476ny1pgqiajxl9d.png" alt="Avatar generator output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it!? &lt;/p&gt;



&lt;center&gt;.......&lt;/center&gt;

&lt;center&gt;.......&lt;/center&gt;

&lt;center&gt;.......&lt;/center&gt;



&lt;center&gt;_NO!NO!NO! Not so Fast_&lt;/center&gt;

&lt;p&gt;&lt;a href="https://media.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%2F99o6zzvhdeeo1enzrtx0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F99o6zzvhdeeo1enzrtx0.png" alt="Hold it"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you see this can generate colors that are too harsh (saturated), or just too grey. And can generate colors that are too white or just too dark.&lt;br&gt;
&lt;a href="https://media.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%2F2ka4sm2fzjoumdar67jg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F2ka4sm2fzjoumdar67jg.png" alt="Avatar Generated Colors range issue"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And this was the reason to use HSL.&lt;/strong&gt; In RGB, the individual values or r,g,b makes the illuminition (lightness) of a color, and it is little difficult to control.&lt;/p&gt;

&lt;p&gt;Just do this to get better color generation.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hRange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;360&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;sRange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;75&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;lRange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Now, play around with the below JsFiddle, and see how the saturation and lightness ranges affect the color generation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the light/dark theme to see which color ranges look good on respective theme.&lt;/li&gt;
&lt;li&gt;Drag the saturation to left, see how colors turn grey&lt;/li&gt;
&lt;li&gt;Drag the lightness to right, see how the colors become white (and reverse - black).&lt;/li&gt;
&lt;li&gt;Use range, to find out the best saturation and lightness for your brand.
&lt;iframe src="https://jsfiddle.net/piyushkmr/o1ryj82a//embedded/result//dark" width="100%" height="600"&gt;
&lt;/iframe&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Bonus tip
&lt;/h3&gt;

&lt;p&gt;Use the hue limiter to generate colors like all green tones, or all purple tones, to better match with your brand colors.&lt;/p&gt;
&lt;h4&gt;
  
  
  Next Time
&lt;/h4&gt;

&lt;p&gt;I am gonna write about how to generate User Avatars... NFT style.&lt;br&gt;
&lt;a href="https://media.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%2Flmk8afybm8fm0i54zmf7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Flmk8afybm8fm0i54zmf7.png" alt="NFT Avatar"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Read Next
&lt;/h2&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/admitkard" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1599%2F453d7113-cb78-421b-b2bd-feac2ac93109.jpg" alt="AdmitKard"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F130627%2F24150c90-bb4a-4f8e-a4b5-a378f9130cf2.jpg" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/admitkard/mobile-issue-with-100vh-height-100-100vh-3-solutions-3nae" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Mobile issue with 100vh | height: 100% !== 100vh [3 solutions]&lt;/h2&gt;
      &lt;h3&gt;Piyush Kumar Baliyan for AdmitKard ・ Feb 14 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#css&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#mobile&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#viewport&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>javascript</category>
      <category>css</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>RegExp Cheatsheet to speed up code editing and refactor</title>
      <dc:creator>Piyush Kumar Baliyan</dc:creator>
      <pubDate>Tue, 04 Jan 2022 07:30:00 +0000</pubDate>
      <link>https://forem.com/admitkard/regexp-cheatsheet-to-speed-up-code-editing-and-refactor-d2d</link>
      <guid>https://forem.com/admitkard/regexp-cheatsheet-to-speed-up-code-editing-and-refactor-d2d</guid>
      <description>&lt;p&gt;Have you ever asked yourself some of these questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do I find all the imports of a particular function?&lt;/li&gt;
&lt;li&gt;How do I replace all the variables of the old &lt;code&gt;Service&lt;/code&gt; implementation with &lt;code&gt;ServiceLegacy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;How do I fix the typo across all the files?&lt;/li&gt;
&lt;li&gt;Which files a particular API endpoint is being used?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If yes, you might find this article a little helpful for your future endeavors.&lt;/p&gt;

&lt;p&gt;For some of you, regex might be a mighty beast too difficult to conquer, for a few of the experts out there, my salute to you for mastering the regex magic.&lt;/p&gt;

&lt;p&gt;I myself am pretty average in areas of regex, but I know enough to make some of my tasks easy.&lt;/p&gt;

&lt;p&gt;I'll start with some regex basics, then move to some common patterns, and then discuss using the newfound regex knowledge (i.e. the topic, speed up code editing).&lt;/p&gt;

&lt;h2&gt;
  
  
  A little background
&lt;/h2&gt;

&lt;p&gt;Regex (or sometimes &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp" rel="noopener noreferrer"&gt;RegExp&lt;/a&gt; - as in JS), is a sequence of characters that specifies a search pattern.&lt;/p&gt;

&lt;p&gt;Perl was one of the modern languages to provide inbuilt support of regex (as Perl was used for text processing, regex support was a necessity), and many of today's tools and languages (including JS and grep) use Perl inspired regex engines.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

^([A-Za-z0-9_.]+)@([A-Za-z0-9-]+)\.([A-Za-z]{2,15})$


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

&lt;/div&gt;
&lt;p&gt;&lt;small&gt;&lt;a href="https://stackoverflow.com/questions/46155/whats-the-best-way-to-validate-an-email-address-in-javascript" rel="noopener noreferrer"&gt;Simple email regex&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Regex Basics
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symbol&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;.&lt;/td&gt;
&lt;td&gt;any character except newline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;Match 0 or more characters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;+&lt;/td&gt;
&lt;td&gt;Match 1 or more characters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;?&lt;/td&gt;
&lt;td&gt;Match 0 or 1 characters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[abc]&lt;/td&gt;
&lt;td&gt;Any of a,b or c&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[^abc]&lt;/td&gt;
&lt;td&gt;not a,b or c&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[a-z]&lt;/td&gt;
&lt;td&gt;Any of a to z&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;^$&lt;/td&gt;
&lt;td&gt;Start and end of string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\w\d\s&lt;/td&gt;
&lt;td&gt;word, digit, whitespace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\W\D\S&lt;/td&gt;
&lt;td&gt;not word, digit, whitespace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;a{5}a{2,}&lt;/td&gt;
&lt;td&gt;exactly five, two or more&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;a{1,3}&lt;/td&gt;
&lt;td&gt;between one &amp;amp; three&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Find the cheatsheet here &lt;a href="https://cheatography.com/davechild/cheat-sheets/regular-expressions/pdf/" rel="noopener noreferrer"&gt;Regular Expression Cheatsheet&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;.*&lt;/code&gt; Match anything (Will match if the string is empty)&lt;br&gt;
&lt;code&gt;.+&lt;/code&gt; Match anything (will not match if the string is empty)&lt;br&gt;
&lt;code&gt;^[a-z]+$&lt;/code&gt; Start and end tokens are there, [a-z]+ will match a string containing characters between a-z and &lt;code&gt;+&lt;/code&gt; will match if there is at least 1 character. So the expression will match any alphabetical string.&lt;/p&gt;

&lt;p&gt;You can learn more here &lt;a href="https://regexone.com/" rel="noopener noreferrer"&gt;Regexone&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating Regex
&lt;/h2&gt;

&lt;p&gt;Now let's try making some regex&lt;/p&gt;
&lt;h4&gt;
  
  
  1. Valid CSS Color
&lt;/h4&gt;

&lt;p&gt;This is simple, should be a hexadecimal string of format RRGGBB.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;^$&lt;/code&gt; - We don't want any stray ending or starting characters, without this, this will match if any random string contains the hexadecimal string.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;^[a-f0-9]+$&lt;/code&gt; - match a-f, 0-9, this is now a valid hexadecimal string, but not valid css color&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;^[a-f0-9]{6}$&lt;/code&gt; - exact length of 6&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;^[a-fA-F0-9]{6}$&lt;/code&gt; - case insensitive match&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  2. Mobile Number
&lt;/h4&gt;

&lt;p&gt;The condition is, should start with +, then 91 (India), then 10 digits.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;^$&lt;/code&gt; - We want number, and not string containing number.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;^\+91.*$&lt;/code&gt;, starts with +91, then .* will match anything (&lt;code&gt;+&lt;/code&gt; is special character, so its escaped with &lt;code&gt;\&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;^\+91[0-9]{10}$&lt;/code&gt;, replace &lt;code&gt;.*&lt;/code&gt; with [0-9]{10} exact 10 occurrences of 0-9 digits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's add another condition, in my country, the number starts with 6,7,8,9, then random 9 digits.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;^\+91[6789][0-9]{9}$&lt;/code&gt; - This will do it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use the &lt;a href="https://regexr.com/" rel="noopener noreferrer"&gt;RegExr playground&lt;/a&gt; to test my Regex.&lt;/p&gt;
&lt;h2&gt;
  
  
  Find and replace in JS
&lt;/h2&gt;

&lt;p&gt;In JS RegExp, we can have something called capture groups, with which we can group parts of our regex and use them in string manipulation using regex.&lt;/p&gt;

&lt;p&gt;A simple example, in the string &lt;code&gt;aabbcc&lt;/code&gt;, replace all &lt;code&gt;c&lt;/code&gt; with &lt;code&gt;a&lt;/code&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;// This will replace first occurrence of all `c`s in the string&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aabbcc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/c*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// OR better&lt;/span&gt;
&lt;span class="c1"&gt;// this will replace all `c`s with a&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aabbcc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/c/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Here &lt;code&gt;/g&lt;/code&gt; is a modifier for global search in regex. Other modifiers are &lt;code&gt;/i&lt;/code&gt; (case insensitive search), &lt;code&gt;/m&lt;/code&gt;, for multiline search.&lt;/p&gt;
&lt;h2&gt;
  
  
  VSCode find and replace
&lt;/h2&gt;

&lt;p&gt;Let's say you have a typo in your code, and you named your type as &lt;code&gt;ButonProps&lt;/code&gt;. And you want to replace it with &lt;code&gt;ButtonProps&lt;/code&gt;.&lt;br&gt;
Simple Find and replace in VSCode lets you do that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fv6jye2lnso89kj0qbggi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fv6jye2lnso89kj0qbggi.png" alt="VSCode Find and replace"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just put the required strings in each input box&lt;br&gt;
&lt;a href="https://media.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%2Fmb005ld7jvn24erbpi09.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fmb005ld7jvn24erbpi09.png" alt="Find and replace typo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Find Regex in vscode
&lt;/h3&gt;

&lt;p&gt;Now let's say you want to find all the occurrences of &lt;code&gt;ButtonProps&lt;/code&gt; import. The syntax will look something like this&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ButtonProps&lt;/span&gt;&lt;span class="p"&gt;}&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;Button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;But it can be something more complex:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ButtonProps&lt;/span&gt;&lt;span class="p"&gt;}&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;Button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;//OR&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ButtonProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ButtonColor&lt;/span&gt;&lt;span class="p"&gt;}&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;Button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Now comes our time to use regex in VSCode.&lt;br&gt;
&lt;a href="https://media.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%2Fckdnkwefow6bq6ak66gy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fckdnkwefow6bq6ak66gy.png" alt="Regex in VSCode"&gt;&lt;/a&gt;&lt;br&gt;
The little button &lt;code&gt;.*&lt;/code&gt; in the search input box is the regex button toggler.&lt;br&gt;
With regex on, we can now use regex in VSCode search.&lt;/p&gt;

&lt;p&gt;So now let's search, and create our regex.&lt;br&gt;
We will first start simple, and then narrow down our search by adding more regex symbols.&lt;br&gt;
Our import statement looks like&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import something ButtonProps something from button;


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

&lt;/div&gt;
&lt;p&gt;so our regex will be (replace something with &lt;code&gt;.*&lt;/code&gt;&lt;br&gt;
&lt;code&gt;import .*ButtonProps.*from '.*Button';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F7di21k50koe9fskanj4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F7di21k50koe9fskanj4b.png" alt="Find ButtonProps"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But there is some noise, we are also getting IconButtonProps. Let's remove that.&lt;br&gt;
What we don't want is ButtonProps to be prefixed by any alphabets.&lt;br&gt;
&lt;code&gt;import .*[^a-zA-Z]ButtonProps.*from '.*Button';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now our search is only showing ButtonProps without any noise.&lt;/p&gt;
&lt;h3&gt;
  
  
  Replace regex in VSCode
&lt;/h3&gt;

&lt;p&gt;Now let's say you want to rename the &lt;code&gt;Button&lt;/code&gt; component to &lt;code&gt;Btn&lt;/code&gt;.&lt;br&gt;
We will need to replace these three occurrences:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;imports (&lt;code&gt;import Button from 'Button'&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Usage (&lt;code&gt;&amp;lt;Button &amp;gt;&amp;lt;/Button&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Assignments (&lt;code&gt;const MyComponent = Button&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;



&lt;center&gt;Lets start.&lt;/center&gt;


&lt;h4&gt;
  
  
  1. imports
&lt;/h4&gt;

&lt;p&gt;Here the &lt;code&gt;()&lt;/code&gt; are capture groups that we will access using $1, $2 respectively.&lt;br&gt;
&lt;a href="https://media.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%2F5jitl0bj7tx98445etln.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5jitl0bj7tx98445etln.png" alt="Find and replace imports"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what VSCode will show you:&lt;br&gt;
&lt;a href="https://media.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%2Fk5r76valt3jq7muye57x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fk5r76valt3jq7muye57x.png" alt="VSCode rename component"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What we have done here is select everything between &lt;code&gt;import&lt;/code&gt; and &lt;code&gt;Button&lt;/code&gt; by first capture group, then everything between &lt;code&gt;Button&lt;/code&gt; and &lt;code&gt;from&lt;/code&gt; by second capture group, and so on.&lt;/li&gt;
&lt;li&gt;Then we carefully want to replace only Button with Btn.&lt;/li&gt;
&lt;li&gt;So we replaced the first capture group with itself ($1), the second one with $2, the third one with $3.&lt;/li&gt;
&lt;li&gt;Hence we get our replacement string &lt;code&gt;import$1Button$2from '$3Button';&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Now change &lt;code&gt;Button&lt;/code&gt; to &lt;code&gt;Btn&lt;/code&gt;, and we get &lt;code&gt;import$1Btn$2from '$3Button';&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And your button imports are now renamed.&lt;/p&gt;
&lt;h4&gt;
  
  
  2. Usage
&lt;/h4&gt;

&lt;p&gt;Continuing on above.&lt;br&gt;
&lt;a href="https://media.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%2Fcsy0ymhf011lddkq1xgo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fcsy0ymhf011lddkq1xgo.png" alt="Find and replace usage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Find &lt;code&gt;&amp;lt;Button&lt;/code&gt; that does not have trailing alphabets (to omit something like &lt;code&gt;&amp;lt;ButtonGroup&lt;/code&gt; and maybe have a trailing newline. then replace all of them with &lt;code&gt;&amp;lt;Btn$1&lt;/code&gt; i.e. using $1, replace &lt;code&gt;space&lt;/code&gt; with space, newline with a newline.&lt;/p&gt;

&lt;p&gt;End bracket now&lt;br&gt;
&lt;a href="https://media.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%2Fkecpog2hqxf105r6zeop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fkecpog2hqxf105r6zeop.png" alt="Find and replace end bracket"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is pretty easy, but why &lt;code&gt;*&lt;/code&gt;. Since &lt;code&gt;&amp;lt;/Button&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;/ Button&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;/Button &amp;gt;&lt;/code&gt; all are valid JSX.&lt;br&gt;
But why not $1, or $2. Since this will also clean up the code and replace all the above with clean &lt;code&gt;&amp;lt;Btn&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  3. Assignments
&lt;/h4&gt;

&lt;p&gt;This one should not be that much in your code, and you can directly search for &lt;code&gt;Button&lt;/code&gt; now.&lt;br&gt;
Find - &lt;code&gt;Button[^']&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But what is &lt;code&gt;[^']&lt;/code&gt; for? To exclude all the occurrences of &lt;code&gt;import.*from 'Button';&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;With this, all our occurrences of Button are now Btn. And we now understand Regex a little better and use it to make our work easy.&lt;/p&gt;

&lt;p&gt;In the future, I'll also try to write some articles highlighting more use-cases of regex to make your life easier.&lt;/p&gt;


&lt;h2&gt;
  
  
  Read Next
&lt;/h2&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/admitkard" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1599%2F453d7113-cb78-421b-b2bd-feac2ac93109.jpg" alt="AdmitKard"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F130627%2F24150c90-bb4a-4f8e-a4b5-a378f9130cf2.jpg" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/admitkard/enforce-git-messages-format-without-throwing-everyone-off-552" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Enforce git commit messages automatically&lt;/h2&gt;
      &lt;h3&gt;Piyush Kumar Baliyan for AdmitKard ・ Jul 2 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#git&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#bash&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#github&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>vscode</category>
      <category>regex</category>
      <category>webdev</category>
    </item>
    <item>
      <title>React Storybook Controls - The easy way</title>
      <dc:creator>Piyush Kumar Baliyan</dc:creator>
      <pubDate>Sun, 12 Sep 2021 07:16:32 +0000</pubDate>
      <link>https://forem.com/admitkard/storybook-controls-the-easy-way-5g4p</link>
      <guid>https://forem.com/admitkard/storybook-controls-the-easy-way-5g4p</guid>
      <description>&lt;p&gt;Storybook is an open source tool for building UI components and pages in isolation. It streamlines UI development, testing, and documentation.&lt;/p&gt;

&lt;p&gt;Storybook for React offers functionality to control props from a very pretty ui.&lt;br&gt;
&lt;a href="https://media.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%2Fbtvpda8b7lo5s7lly7mo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbtvpda8b7lo5s7lly7mo.png" alt="Storybook Controls"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will explore these things in this post:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Knobs vs Controls&lt;/li&gt;
&lt;li&gt;The good - React-docgen&lt;/li&gt;
&lt;li&gt;The bad - More words to type&lt;/li&gt;
&lt;li&gt;The solution&lt;/li&gt;
&lt;li&gt;Bonus - Snippets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Till storybook v5, this was achieved using a community plugin &lt;code&gt;Knobs&lt;/code&gt;, which is very popular with around ~1m downloads weekly.&lt;br&gt;
&lt;a href="https://media.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%2Fy49sx31g4uovzk84d2wp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fy49sx31g4uovzk84d2wp.png" alt="Knobs weekly downloads"&gt;&lt;/a&gt;&lt;/p&gt;
Knobs weekly downloads


 

&lt;p&gt;In Storybook v6, the team released Essentials addons:&lt;br&gt;
&lt;a href="https://media.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%2F1gilnw2cbmie30zqxhqi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F1gilnw2cbmie30zqxhqi.png" alt="Storybook essentials"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was in alignment with &lt;a href="https://storybook.js.org/blog/zero-config-storybook/" rel="noopener noreferrer"&gt;Storybook's Zero-config initiative&lt;/a&gt; (which included out-of-box TS support, essentials addons, and extended support of more frameworks).&lt;/p&gt;
&lt;h2&gt;
  
  
  Knobs vs Controls
&lt;/h2&gt;

&lt;p&gt;With this storybook migrated from Knobs in v5 to Controls in v5&lt;/p&gt;
&lt;h4&gt;
  
  
  Knobs
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.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%2F40p7di4qvc3i5scmml13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F40p7di4qvc3i5scmml13.png" alt="Knobs in v5"&gt;&lt;/a&gt;&lt;/p&gt;
Knobs in v5




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withAButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Disabled&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Label&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;Hello Storybook&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Controls
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5g9frllxivnvss10ch1w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5g9frllxivnvss10ch1w.png" alt="Controls in v6"&gt;&lt;/a&gt;&lt;/p&gt;
Controls in v6




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;argTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;options&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;primary&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;secondary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;radio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  The good
&lt;/h3&gt;

&lt;p&gt;With the controls, storybook can automatically detect props using react doc-gen, and can automatically generate all the controls for you.&lt;br&gt;
&lt;a href="https://media.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%2Fbkpm41ffjoolqe5u7m3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbkpm41ffjoolqe5u7m3d.png" alt="React docgen"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The bad
&lt;/h3&gt;

&lt;p&gt;For me, some of the controls were not automatically generated due to some of HOCs that we were using (I know, fixing HOCs can fix react docgen as well).&lt;/p&gt;

&lt;p&gt;Also, in-case I want to add custom controls, or want to define controls on my own, then the syntax is a little bit more typing over Knobs syntax.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;Given the new controls syntax, and the ease of use of old Knobs functions, I ended up creating my own wrappers over new controls.&lt;/p&gt;
&lt;h3&gt;
  
  
  Wrappers
&lt;/h3&gt;

&lt;p&gt;The approach looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;select&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ArgProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;allProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ReturnedArg&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createControlFromProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;select&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;allProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaultValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defaultValue&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="nx"&gt;allProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;allProps&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;So basically, I took input in knobs format, and returned in controls format.&lt;/p&gt;

&lt;p&gt;Here is the full file with these controls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;select&lt;/li&gt;
&lt;li&gt;boolean&lt;/li&gt;
&lt;li&gt;text&lt;/li&gt;
&lt;li&gt;number&lt;/li&gt;
&lt;li&gt;obj&lt;/li&gt;
&lt;li&gt;action&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;

&lt;p&gt;With this, the usage looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;argTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getArgs&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InputProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;small&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;medium&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;large&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="na"&gt;fullWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;boolean &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="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&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;Here is the full code with Input Stories:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Bonus - Snippets
&lt;/h3&gt;

&lt;p&gt;An added bonus will be, create a snippet for a story, and next time have a story ready to be served with few key-strokes.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


</description>
      <category>react</category>
      <category>storybook</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Create PR Builder in bitbucket, DangerJS and Jenkins</title>
      <dc:creator>Piyush Kumar Baliyan</dc:creator>
      <pubDate>Sat, 23 Jan 2021 04:48:41 +0000</pubDate>
      <link>https://forem.com/admitkard/how-to-integrate-dangerjs-with-jenkins-and-bitbucket-cloud-2kh2</link>
      <guid>https://forem.com/admitkard/how-to-integrate-dangerjs-with-jenkins-and-bitbucket-cloud-2kh2</guid>
      <description>&lt;h2&gt;
  
  
  AKA Making a pull request builder for bitbucket [baby-steps]
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is DangerJS?
&lt;/h3&gt;

&lt;p&gt;From official website&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Danger runs during your CI process, and gives teams the chance to automate common code review chores.&lt;br&gt;
This happens by Danger leaving messages inside your PRs based on rules that you create with JavaScript or TypeScript.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdanger.systems%2Fimages%2Fdangerjs-screenshot-2e2a9281.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdanger.systems%2Fimages%2Fdangerjs-screenshot-2e2a9281.png" alt="Danger Preview from Danger website"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We (at Admitkard) also recently decided to integrate DangerJS with our React + TS setup to get us messages on our Pull requests in Bitbucket.&lt;/p&gt;

&lt;p&gt;We are using Bitbucket and there are very few articles on the web around Bitbucket+DangerJS (as Github is more popular choice). So I decided to write an article to help you through.&lt;/p&gt;

&lt;p&gt;Let's get started.&lt;/p&gt;

&lt;p&gt;There are four big parts of this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your repo&lt;/li&gt;
&lt;li&gt;Local testing&lt;/li&gt;
&lt;li&gt;Bitbucket&lt;/li&gt;
&lt;li&gt;Jenkins.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Changes in Repo
&lt;/h2&gt;

&lt;p&gt;Here are the step-by-step guides that we did in our (React +TS) repo. You can follow the official guide here: &lt;a href="https://danger.systems/js/guides/getting_started.html" rel="noopener noreferrer"&gt;https://danger.systems/js/guides/getting_started.html&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Install DangerJS into your REPO&lt;br&gt;
&lt;code&gt;yarn add danger --dev&lt;/code&gt;&lt;br&gt;
OR&lt;br&gt;
&lt;code&gt;npm install --save-dev danger&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a dangerfile&lt;br&gt;
Create a new file &lt;code&gt;dangerfile.js&lt;/code&gt; or &lt;code&gt;dangerfile.ts&lt;/code&gt;&lt;br&gt;
Add following code to &lt;code&gt;dangerfile&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;danger&lt;/span&gt; &lt;span class="p"&gt;}&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;danger&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;exec&lt;/span&gt; &lt;span class="p"&gt;}&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;child_process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;path&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;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// TSLint&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;runTSLint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modifiedFiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;danger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;git&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modified_files&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;ts&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;x&lt;/span&gt;&lt;span class="se"&gt;]?&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tsLintExec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.bin&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;tslint&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tslintCommand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tsLintExec&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="nx"&gt;modifiedFiles&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; -t prose --project tsconfig.json`&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;tslintOut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tslintCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nf"&gt;runTSLint&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;danger.git.modified_files&lt;/code&gt; is danger API for giving us modified files in the PR attached to a particular build (you can also use git API, but you will have to fiddle through finding commits in current PR).&lt;br&gt;
&lt;code&gt;tsLintExec&lt;/code&gt; is our local installation of &lt;code&gt;tslint&lt;/code&gt; through packages&lt;br&gt;
&lt;code&gt;exec&lt;/code&gt; executes our command for &lt;code&gt;tslint&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;tslint&lt;/code&gt; will fail if there are tslint errors, hence we will get &lt;code&gt;error&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;warn&lt;/code&gt; will tell dangerJS to post a warning on our pull-request.&lt;/p&gt;
&lt;h4&gt;
  
  
  Modify package.json for dangerJS
&lt;/h4&gt;

&lt;p&gt;This step is optional but it will make it easier for us to run dangerjs.&lt;br&gt;
add script in your &lt;code&gt;package.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="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;"danger"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"danger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is all that is needed in your repo.&lt;/p&gt;

&lt;p&gt;To test your changes locally, you will need to setup access tokens in your bitbucket repo. So, we’ll first move to Bitbucket part&lt;/p&gt;




&lt;h2&gt;
  
  
  Changes in Bitbucket for DangerJS
&lt;/h2&gt;

&lt;p&gt;This article is for the bitbucket cloud, but steps should be similar for the bitbucket server as well.&lt;/p&gt;

&lt;h4&gt;
  
  
  Get Bitbucket UUID
&lt;/h4&gt;

&lt;p&gt;Get UUID of the user which DangerJS will use to post these comments (it is recommended to create a bot user for such tasks).&lt;/p&gt;

&lt;p&gt;In bitbucket, go to your profile. Your URL will change to &lt;code&gt;https://bitbucket.org/%7B&amp;lt;uuid&amp;gt;%7D/&lt;/code&gt;&lt;br&gt;
This &lt;code&gt;&amp;lt;uuid&amp;gt;&lt;/code&gt; is what we need.&lt;/p&gt;

&lt;p&gt;Get Bitbucket OAuth key and secret&lt;br&gt;
Now we need to set up an OAuth client for danger (so that it can post comments on your PR).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to bitbucket settings [Profile Icon &amp;gt; Bitbucket Settings]&lt;/li&gt;
&lt;li&gt;Go to OAuth&lt;/li&gt;
&lt;li&gt;Add Consumer&lt;/li&gt;
&lt;li&gt;Give it a Name&lt;/li&gt;
&lt;li&gt;Give it these permissions:

&lt;ol&gt;
&lt;li&gt;Repositories

&lt;ol&gt;
&lt;li&gt;Read&lt;/li&gt;
&lt;li&gt;Write&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Pull requests

&lt;ol&gt;
&lt;li&gt;Read&lt;/li&gt;
&lt;li&gt;Write&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You will get a OAuth &lt;code&gt;key&lt;/code&gt; and OAuth &lt;code&gt;secret&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Thats it for now, but since we are at it. Let’s do one more change in bitbucket that we’ll need later.&lt;/p&gt;
&lt;h4&gt;
  
  
  Add Webhook to bitbucket
&lt;/h4&gt;

&lt;p&gt;We need to add webhook so that we can trigger our jenkins jobs remotely using this webhook.&lt;/p&gt;

&lt;p&gt;For this go to your repo&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to Settings &amp;gt; Webhooks&lt;/li&gt;
&lt;li&gt;Add Webhook&lt;/li&gt;
&lt;li&gt;Give it a title&lt;/li&gt;
&lt;li&gt;Give it URL &lt;code&gt;https://&amp;lt;JENKINS_URL&amp;gt;/generic-webhook-trigger/invoke?token=&amp;lt;TOKEN&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Triggers &amp;gt; Choose from a full list of triggers

&lt;ol&gt;
&lt;li&gt;Pull Request

&lt;ol&gt;
&lt;li&gt;Created&lt;/li&gt;
&lt;li&gt;Updated&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it for bitbucket.&lt;br&gt;
Now let’s test this on our local repo.&lt;/p&gt;


&lt;h2&gt;
  
  
  Testing DangerJS on local terminal
&lt;/h2&gt;

&lt;p&gt;First, we need to configure some env variables for dangerJS. These variables basically are the bitbucket credentials that we need to provide to dangerJS.&lt;/p&gt;

&lt;p&gt;Setting Environment Variables for DangerJS for Bitbucket&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="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DANGER_BITBUCKETCLOUD_OAUTH_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;OauthKey&amp;gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DANGER_BITBUCKETCLOUD_OAUTH_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;OauthSecret&amp;gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DANGER_BITBUCKETCLOUD_UUID&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;&amp;lt;uuid&amp;gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can test run dangerJS on a PR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    yarn danger &lt;span class="nb"&gt;pr &lt;/span&gt;https://bitbucket.org/&amp;lt;org&amp;gt;/&amp;lt;repo&amp;gt;/pull-requests/&amp;lt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see dangerJS output in your terminal with warnings.&lt;/p&gt;

&lt;p&gt;To actually test how this will behave when it will integrated in your CI pipeline, an additional step will need to be done. (This step is optional)&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="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DANGER_FAKE_CI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"YEP"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DANGER_TEST_REPO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;org&amp;gt;/&amp;lt;repo&amp;gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run &lt;code&gt;DANGER_TEST_PR='&amp;lt;PRid&amp;gt;' npm run danger ci&lt;/code&gt;&lt;br&gt;
Danger will run and this will actually post comment on your PR&lt;/p&gt;



&lt;p&gt;With local testing done, now its time to integrate it with Jenkins.&lt;/p&gt;
&lt;h2&gt;
  
  
  Integration of Jenkins with DangerJS and bitbucket
&lt;/h2&gt;
&lt;h4&gt;
  
  
  Installing required plugins
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;a href="https://plugins.jenkins.io/generic-webhook-trigger" rel="noopener noreferrer"&gt;https://plugins.jenkins.io/generic-webhook-trigger&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now making a Jenkins job for our Pull Request Builder&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new Freestyle project in Jenkins&lt;/li&gt;
&lt;li&gt;Go to Source Code Management and choose git as SCM&lt;/li&gt;
&lt;li&gt;Add repo URL and credentials (SSH or username password)&lt;/li&gt;
&lt;li&gt;Now move to Build Triggers, and choose Generic Webhook Trigger &lt;/li&gt;
&lt;li&gt;Under Post content parameters, Add a parameter

&lt;ol&gt;
&lt;li&gt;Parameter

&lt;ol&gt;
&lt;li&gt;Variable: &lt;code&gt;branchName&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Expression: &lt;code&gt;$.pullrequest.source.branch.name&lt;/code&gt; JSONPath&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Parameter

&lt;ol&gt;
&lt;li&gt;Variable: &lt;code&gt;pullRequestId&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Expression &lt;code&gt;$.pullrequest.id&lt;/code&gt; JSONPath&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Token: &lt;code&gt;&amp;lt;Token&amp;gt;&lt;/code&gt; (this token has to be same as we configured in our webhook&lt;/li&gt;
&lt;li&gt;Cause: Reason for trigger (you can use Env variables and the Post Content Parameters that we configured above)&lt;/li&gt;
&lt;li&gt;Now to go Bindings

&lt;ol&gt;
&lt;li&gt;Add your bitbucket credentials &lt;code&gt;bitbucketDangerJSOauthKey&lt;/code&gt; and &lt;code&gt;bitbucketDangerJSOauthSecret&lt;/code&gt; to jenkins credential store&lt;/li&gt;
&lt;li&gt;Also add &lt;code&gt;bitbucketUserUUID&lt;/code&gt; to jenkins as well&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Go to Build&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Under build add this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ghprbGhRepository&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;org&amp;gt;/&amp;lt;repo&amp;gt;"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ghprbPullId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$pullRequestId&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DANGER_BITBUCKETCLOUD_UUID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$bitbucketUserUUID&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DANGER_BITBUCKETCLOUD_OAUTH_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$bitbucketDangerJSOauthKey&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DANGER_BITBUCKETCLOUD_OAUTH_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$bitbucketDangerJSOauthSecret&lt;/span&gt;
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run danger ci
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;ghprbGhRepository&lt;/code&gt; is your repo URL&lt;br&gt;
&lt;code&gt;ghprbPullId&lt;/code&gt; is our PR id that we extracted from webhook&lt;br&gt;
rest are Variables that we did in our repo.&lt;/p&gt;

&lt;p&gt;Note Jenkins might give you error &lt;code&gt;Skipping Danger due to this run not executing on a PR.&lt;/code&gt;. This is due to missing variables.&lt;/p&gt;

&lt;p&gt;
  Why the variables are named like so even for Bitbucket?
  &lt;br&gt;
Now &lt;code&gt;ghprbGhRepository&lt;/code&gt; and &lt;code&gt;ghprbPullId&lt;/code&gt;, sounds like they will be required for github-pull-request-builder only, but this is not the case.

&lt;p&gt;Take a look here: &lt;a href="https://github.com/danger/danger-js/blob/master/source/ci_source/providers/Jenkins.ts" rel="noopener noreferrer"&gt;https://github.com/danger/danger-js/blob/master/source/ci_source/providers/Jenkins.ts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see under &lt;code&gt;isPR&lt;/code&gt;, it checks for these variables (for bitbucket as well). I am going to raise a PR with dangerJS to get these variables fixed to something generic like &lt;code&gt;DANGER_PR_REPO&lt;/code&gt; and &lt;code&gt;DANGER_PR_ID&lt;/code&gt;.&lt;/p&gt;

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




&lt;/p&gt;
&lt;p&gt;With this, your PR will trigger Jenkins jobs and post comments on your PR if anything fails in TSLint.&lt;br&gt;
You can easily extend DangerJS to post other comments as well and can control your Jenkins pipeline output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Words
&lt;/h2&gt;

&lt;p&gt;DangerJS provides an easy way to make it easy for the reviewer and the developer to get notified of issues in their code that can be configured with build tools.&lt;br&gt;
In words of Danger&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Stop saying "you forgot to …" in code review&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>devops</category>
      <category>codequality</category>
      <category>javascript</category>
      <category>git</category>
    </item>
    <item>
      <title>Enforce git commit messages automatically</title>
      <dc:creator>Piyush Kumar Baliyan</dc:creator>
      <pubDate>Thu, 02 Jul 2020 09:30:10 +0000</pubDate>
      <link>https://forem.com/admitkard/enforce-git-messages-format-without-throwing-everyone-off-552</link>
      <guid>https://forem.com/admitkard/enforce-git-messages-format-without-throwing-everyone-off-552</guid>
      <description>&lt;h3&gt;
  
  
  TLDR;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;You can enforce git messages by using custom git shortcuts in shell/bash script.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Backdrop and motivation
&lt;/h2&gt;

&lt;p&gt;So, we use JIRA and bitbucket, and the good thing with them is that they integrate very well with each other, e.g.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it links JIRA issues in your Bitbucket PRs&lt;/li&gt;
&lt;li&gt;you can change Jira status from within Bitbucket&lt;/li&gt;
&lt;li&gt;you can create development branches from inside JIRA issue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But this needs some effort to ensure the consistency in your git messages and branch names, plus if you can follow a certain pattern, it becomes for everyone to collaborate since everyone is following the same set of rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rules we follow
&lt;/h3&gt;

&lt;p&gt;So here are a couple of rules that we follow for branch management and commit messages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;git branch name &lt;code&gt;&amp;lt;username&amp;gt;-JIRA-1234[-hotfix|-patch]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;commit message &lt;code&gt;JIRA-1234 some actually useful commit message&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;set a ticket &lt;code&gt;In Progress&lt;/code&gt; once you start working on it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are pretty straight forward, and I believe some of you are also following these rules (or at least some variation of it). But sometimes you forget to actually follow these, and this gets caught in PR reviews, or sometimes get merged.&lt;/p&gt;

&lt;h1&gt;
  
  
  3 solutions
&lt;/h1&gt;

&lt;p&gt;3. Use git aliases&lt;br&gt;
2. Use bash aliases (Easiest)&lt;br&gt;
1. Use own implementation of bash functions (Most powerful &amp;amp; coolest)&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Git Aliases
&lt;/h2&gt;

&lt;p&gt;Git aliases are cool, and you can create your own shortcuts for common tasks&lt;br&gt;
e.g. Use &lt;code&gt;git co&lt;/code&gt; instead of &lt;code&gt;git checkout&lt;/code&gt;&lt;br&gt;
And here is how you can do it yourself.&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="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.co checkout
&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.br branch
&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.ci commit
&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.st status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;OR&lt;br&gt;
You can use config files to manage aliases e.g. &lt;code&gt;.gitconfig&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
co &lt;span class="o"&gt;=&lt;/span&gt; checkout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can read more about it here&lt;br&gt;
&lt;a href="https://www.atlassian.com/git/tutorials/git-alias"&gt;https://www.atlassian.com/git/tutorials/git-alias&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Bash Aliases
&lt;/h2&gt;

&lt;p&gt;Bash aliases are another approach similar to creating your own shortcuts (that are even shorter than the above approach).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open &lt;code&gt;~/.bashrc&lt;/code&gt; using &lt;code&gt;vim&lt;/code&gt; or any other text editor&lt;/li&gt;
&lt;li&gt;Add this to bottom of your file
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gco&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"checkout"&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gbr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"branch"&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gci&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"commit"&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gst&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Save it&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;source ~/.bashrc&lt;/code&gt; OR restart terminal&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;gco master&lt;/code&gt; and you will see that you are now on master and our command is working.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can have a look at common aliases here&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  1. Custom bash functions (Most powerful)
&lt;/h2&gt;

&lt;p&gt;This is the most tricky, but most powerful approach. With this, you can do cool things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;auto add JIRA id to commit message&lt;/li&gt;
&lt;li&gt;get JIRA status in your bash terminal
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PVcV3Vmh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/iavoyoizl43rbi4o40yi.png" alt="JIRA status in bash" width="497" height="63"&gt;
&lt;/li&gt;
&lt;li&gt;Directly open PR URL of your current branch in your browser&lt;/li&gt;
&lt;li&gt;and many more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The way I do is, define some env variables like your username, jirapassword, etc, and do a curl request to get status.&lt;br&gt;
You can also append the JIRA ticket number automatically to commit messages using bash functions.&lt;/p&gt;

&lt;p&gt;Here is the gist for the same:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download this file &lt;code&gt;wget https://gist.githubusercontent.com/piyushkmr/fe64a2c6dde0b42c0d95f945dbf96fc2/raw/devhelp.sh&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Source it in &lt;code&gt;~/.bashrc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;gh&lt;/code&gt; to get a list of available commands
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcof JIRA-1234 &lt;span class="c"&gt;# create a branch with username piyush-JIRA-1234&lt;/span&gt;
gpoh &lt;span class="c"&gt;# push changes at HEAD right now&lt;/span&gt;
gopr &lt;span class="c"&gt;# Open the new PR link for your current branch&lt;/span&gt;
jira &lt;span class="c"&gt;# show Jira status of the current branch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  0. BONUS Tip
&lt;/h3&gt;

&lt;p&gt;Use custom bash prompt to get some more space with those big directory names, and show current git branch, like this&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qX4g-kv9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h1ooddhf7vkfca6vs90x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qX4g-kv9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h1ooddhf7vkfca6vs90x.png" alt="Custom bash prompt" width="290" height="40"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cool, huh!!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Do the same here as you did above for &lt;code&gt;devhelp.sh&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Read Next
&lt;/h4&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/admitkard" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LJVB9XmZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--kLM1tRbK--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/organization/profile_image/1599/453d7113-cb78-421b-b2bd-feac2ac93109.jpg" alt="AdmitKard" width="150" height="150"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XRuspDA4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--lrsh4H4L--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/130627/24150c90-bb4a-4f8e-a4b5-a378f9130cf2.jpg" alt="" width="150" height="150"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/admitkard/mobile-issue-with-100vh-height-100-100vh-3-solutions-3nae" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Mobile issue with 100vh | height: 100% !== 100vh [3 solutions]&lt;/h2&gt;
      &lt;h3&gt;Piyush Kumar Baliyan for AdmitKard ・ Feb 14 '20 ・ 3 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#css&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#mobile&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#viewport&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>git</category>
      <category>bash</category>
      <category>github</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Mobile issue with 100vh | height: 100% !== 100vh [3 solutions]</title>
      <dc:creator>Piyush Kumar Baliyan</dc:creator>
      <pubDate>Fri, 14 Feb 2020 15:32:19 +0000</pubDate>
      <link>https://forem.com/admitkard/mobile-issue-with-100vh-height-100-100vh-3-solutions-3nae</link>
      <guid>https://forem.com/admitkard/mobile-issue-with-100vh-height-100-100vh-3-solutions-3nae</guid>
      <description>&lt;p&gt;So there are various ways to size any element on a webpage.&lt;br&gt;
We are familiar with common CSS units px, em, pt (and uncommon one cm, mm, in) with support from the first version of CSS (&lt;a href="https://www.w3.org/TR/REC-CSS1/#units" rel="noopener noreferrer"&gt;https://www.w3.org/TR/REC-CSS1/#units&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;With newer viewport units, first support came in 2013 with FF and Chrome being the first ones quickly followed by Safari and Opera. (yes, IE used to suck even in those days).&lt;/p&gt;

&lt;p&gt;Now with newer viewport units and a ton on mobile devices, the browser communities don’t seem to agree on how to implement them in mobile devices.&lt;/p&gt;

&lt;p&gt;In mobile, vh seems to consider the address bar as part of the viewport (IDK why is it named as ‘view’port then).&lt;/p&gt;
&lt;h3&gt;
  
  
  On mobile 100vh !== 100%
&lt;/h3&gt;

&lt;p&gt;This creates weird issues with mobile viewport heights like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Fye8aGeo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Fye8aGeo.png" alt="Mobile on 100vh is cut"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now this is an issue and indeed a very frustrating one, but we’ll discuss a couple of solutions one by one.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Use 100% instead of 100vh - “DOM tree nightmare”
&lt;/h2&gt;

&lt;p&gt;Now the quickest, and most CSS way is to use 100% in your page for the whole DOM tree till your target element:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FBMzwYp2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FBMzwYp2.png" alt="100% height through dom tree"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will work correctly on both mobile and desktop websites. However it is very difficult to propagate 100% through every DOM node in the branch of your element, especially if it is buried deep in the tree (however, you might not come across too many use cases like this).&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Use JS window.innerHeight for your element - “JS hack”
&lt;/h2&gt;

&lt;p&gt;The second way is to use window.innerHeight for your target element, as on mobile, it will always give you the viewable height of the viewport, but again, this again creates a problem as you will have to write this tiny JS for each of your use cases.&lt;/p&gt;

&lt;p&gt;So can there be an easy solution, which can give you the best of both worlds?&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Use custom vh (CSS variable) - best of both worlds
&lt;/h2&gt;

&lt;p&gt;So the solution, (you might find very few solutions floating around for this &lt;code&gt;typeof&lt;/code&gt; fix).&lt;br&gt;
Before proceeding with this solution, let's see what are the cons to this. This solution involves using CSS variables (custom properties) and here &lt;a href="https://caniuse.com/#search=css%20var" rel="noopener noreferrer"&gt;https://caniuse.com/#search=css%20var&lt;/a&gt;, you can see that support for CSS variables came in early 2017 for major browsers, so you might need to think if you want to use this.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;So here we’ll be creating something like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FdPTZYDg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FdPTZYDg.png" alt="--vh in root html"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now what we have to do is set CSS variable --vh using &lt;code&gt;window.innerHeight&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

window.addEventListener('resize', () =&amp;gt; { 
  document.querySelector(':root').style
    .setProperty('--vh', window.innerHeight/100 + 'px');
})


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

&lt;/div&gt;
&lt;p&gt;Now you will have &lt;code&gt;--vh&lt;/code&gt; available in your whole app.&lt;/p&gt;

&lt;p&gt;Here comes the second step of this&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;You can now use this variable anywhere in your code&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

height: calc(100 * var(--vh));


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

&lt;/div&gt;
&lt;p&gt;This works like vh (with a little too verbose representation).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100vh - &lt;code&gt;height: calc(100 * var(--vh));&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;10vh - &lt;code&gt;height: calc(10 * var(--vh));&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;1vh - &lt;code&gt;height: calc(1 * var(--vh));&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you can use it anywhere in your CSS code.&lt;/p&gt;


&lt;h2&gt;
  
  
  Read Next
&lt;/h2&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/admitkard" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1599%2F453d7113-cb78-421b-b2bd-feac2ac93109.jpg" alt="AdmitKard"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F130627%2F24150c90-bb4a-4f8e-a4b5-a378f9130cf2.jpg" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/admitkard/regexp-cheatsheet-to-speed-up-code-editing-and-refactor-d2d" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;RegExp Cheatsheet to speed up code editing and refactor&lt;/h2&gt;
      &lt;h3&gt;Piyush Kumar Baliyan for AdmitKard ・ Jan 4 '22&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#vscode&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#regex&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>css</category>
      <category>mobile</category>
      <category>viewport</category>
    </item>
    <item>
      <title>Verdaccio: Hosting your own Private NPM Registry</title>
      <dc:creator>Piyush Kumar Baliyan</dc:creator>
      <pubDate>Wed, 04 Dec 2019 05:33:56 +0000</pubDate>
      <link>https://forem.com/admitkard/verdaccio-hosting-your-own-private-npm-registry-48f5</link>
      <guid>https://forem.com/admitkard/verdaccio-hosting-your-own-private-npm-registry-48f5</guid>
      <description>&lt;h1&gt;
  
  
  What is a Private NPM registry?
&lt;/h1&gt;

&lt;p&gt;Sometimes you need to publish a npm package to use within your org or team. There are many services online that provide solutions to this problem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F3714%2F1%2Aga6ZjSVp_tLrAOLyEJEDnQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F3714%2F1%2Aga6ZjSVp_tLrAOLyEJEDnQ.png" alt="own Private NPM package registry"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can subscribe for &lt;a href="https://www.npmjs.com/products/orgs" rel="noopener noreferrer"&gt;Npm Orgs&lt;/a&gt; or &lt;a href="https://gemfury.com" rel="noopener noreferrer"&gt;GemFury&lt;/a&gt; and services like these.&lt;/p&gt;

&lt;p&gt;But sometimes you want a quick and cheap solution to test things out, or to start with things. Here is when &lt;a href="https://verdaccio.org/docs/en/what-is-verdaccio.html" rel="noopener noreferrer"&gt;Verdaccio&lt;/a&gt; helps you to start.&lt;/p&gt;

&lt;p&gt;How it looks:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F3196%2F1%2Au5inBThejTtOCPAIFcFrTA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F3196%2F1%2Au5inBThejTtOCPAIFcFrTA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Installation
&lt;/h1&gt;

&lt;p&gt;Verdaccio is available as a npm package and can be downloaded. Install it as a global package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install — global verdaccio
yarn global add verdaccio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To give it a quick trial run this now&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;verdaccio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Running Server
&lt;/h1&gt;

&lt;p&gt;You can run verdaccio via many service managers, pm2 is fairly simple to set up and use.&lt;/p&gt;

&lt;p&gt;Just install it globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g pm2
yarn global add pm2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run verdaccio with pm2&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pm2 start verdaccio — — listen 0.0.0.0:4001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now access verdaccio on &lt;a href="http://localhost:4001" rel="noopener noreferrer"&gt;http://localhost:4001&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Public Access
&lt;/h1&gt;

&lt;p&gt;We need to expose our &lt;code&gt;0.0.0.0:4001&lt;/code&gt; to some domain on port 80 (or 443 for https).&lt;/p&gt;

&lt;p&gt;It can be done via any web-server &lt;a href="https://httpd.apache.org/docs/trunk/vhosts/examples.html" rel="noopener noreferrer"&gt;Apache&lt;/a&gt;, &lt;a href="https://serverfault.com/questions/536576/nginx-how-do-i-forward-a-http-request-to-another-port" rel="noopener noreferrer"&gt;Nginx&lt;/a&gt;, etc.&lt;/p&gt;

&lt;p&gt;Once you install Nginx, and it is running and listening on port 80, you can start forwarding your requests to the verdaccio server.&lt;/p&gt;

&lt;p&gt;Create and edit Nginx verdaccio.conf&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vim /etc/nginx/sites-available/verdaccio.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this to your conf:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
  listen 80;
  server_name npm.company.net;
  location / {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_pass [http://localhost:4001/;](http://localhost:4001/;)
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this file to the list of Nginx &lt;code&gt;available-sites&lt;/code&gt;. (Nginx recommends to add conf to sites-available and create a symlink in sites-enabled).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ln /etc/nginx/sites-available/verdaccio.conf /etc/nginx/sites-enabled/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Restart Nginx&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo service restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Configuring Domain and DNS
&lt;/h1&gt;

&lt;p&gt;Add your server IP to your DNS to access via a domain. You can do this by adding &lt;strong&gt;A Name&lt;/strong&gt; to your DNS manager.&lt;/p&gt;

&lt;p&gt;A Name | npm.company.net | xxx.xxx.xxx.xxx | TTL&lt;/p&gt;

&lt;p&gt;Refresh your cache and your registry is now hosted on &lt;code&gt;[http://npm.company.net](http://npm.company.net.)&lt;/code&gt;&lt;a href="http://npm.company.net." rel="noopener noreferrer"&gt;.&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Publish Packages
&lt;/h1&gt;

&lt;p&gt;Verdaccio requires authentication for publishing, thus we need to log in. First, you need to add yourself to the npm registry to publish any package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm adduser --registry http://npm.company.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you are logged, you can now publish.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm publish --registry http://npm.company.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Install packages
&lt;/h1&gt;

&lt;p&gt;npm or yarn will use the default registry for installing packages. But you can override for one package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @scope/package --registry http://npm.company.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or to avoid using this again and again there is an intelligent way.&lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;.npmrc&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// .npmrc
@scope:registry=http://npm.company.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or in .yarnrc&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// .yarnrc
"@scope:registry" "http://npm.company.net"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this your normal packages like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;npm install -g typescript&lt;/code&gt; will be installed from default registry&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;npm install @scope/pkg&lt;/code&gt; will be installed from your private registry&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;So you can set up your registry very quickly, on your infra. As long as your needs are limited and you don’t need very customized scoping and roles management, verdaccio will be able to handle your requirements.&lt;/p&gt;

&lt;p&gt;A quick hint if you need to think about scale (like 1000s of employees publishing 1000s of packages), you can look at &lt;a href="https://www.sonatype.com/product-nexus-repository" rel="noopener noreferrer"&gt;Nexus Repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Drop a comment if you have some suggestions, need more info or help around this.&lt;/p&gt;




&lt;p&gt;Find more awesome stuff that &lt;a href="https://admitkard.com" rel="noopener noreferrer"&gt;AdmitKard&lt;/a&gt; is doing here: &lt;a href="https://dev.to/admitkard"&gt;https://dev.to/admitkard&lt;/a&gt;&lt;/p&gt;

</description>
      <category>verdaccio</category>
      <category>npm</category>
      <category>registry</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
