<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alan W. Smith</title>
    <description>The latest articles on DEV Community by Alan W. Smith (@alanwsmith).</description>
    <link>https://dev.to/alanwsmith</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%2F182045%2F1059ec29-6904-4391-a97b-0d50059352a3.jpeg</url>
      <title>DEV Community: Alan W. Smith</title>
      <link>https://dev.to/alanwsmith</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alanwsmith"/>
    <language>en</language>
    <item>
      <title>Add Line Numbers to Prismjs Code Blocks in a Next.js Project</title>
      <dc:creator>Alan W. Smith</dc:creator>
      <pubDate>Mon, 10 Jan 2022 20:57:41 +0000</pubDate>
      <link>https://dev.to/alanwsmith/add-line-numbers-to-prismjs-code-blocks-in-a-nextjs-project-50g1</link>
      <guid>https://dev.to/alanwsmith/add-line-numbers-to-prismjs-code-blocks-in-a-nextjs-project-50g1</guid>
      <description>&lt;p&gt;(&lt;em&gt;The original version of this post is on &lt;a href="https://www.alanwsmith.com/posts/23qrlwhb8tam--add-line-numbers-to-prismjs-code-blocks-in-a-nextjs-project"&gt;my site&lt;/a&gt; if you'd like to read it there&lt;/em&gt;)&lt;/p&gt;




&lt;p&gt;None of the posts I found on the &lt;a href="https://prismjs.com/"&gt;Prism syntax highlighter&lt;/a&gt; show how to turn on line numbers in a &lt;a href="https://nextjs.org/"&gt;Next.js&lt;/a&gt; project. &lt;/p&gt;

&lt;p&gt;In the spirit of sharing so others don't have to hack around like I did, here's how to do it:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Install
&lt;/h2&gt;

&lt;p&gt;Assuming you already have your Next.js project setup and ready, install Prism with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;prismjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. The Full Code Example
&lt;/h2&gt;

&lt;p&gt;Next up, the code. Here's a fully functional example you can use in a file (e.g. 'pages/prism-example.js'). It includes a theme (okaidia), a language (jsx), and line numbering. (Details further below.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;useEffect&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Prism&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;prismjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prismjs/themes/prism-okaidia.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prismjs/components/prism-jsx.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prismjs/plugins/line-numbers/prism-line-numbers.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prismjs/plugins/line-numbers/prism-line-numbers.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;useEffect&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;Prism&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;highlightAll&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;codeSample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;div className="example"&amp;gt;
  {Math.random()}
&amp;lt;/div&amp;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="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"line-numbers"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"language-jsx"&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;codeSample&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;code&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&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;Using that will output a highlighted and numbered code snippet that &lt;a href="https://scratchpad.alanwsmith.com/prism-minimal-example-with-line-numbers-and-theme"&gt;looks like this&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The Details
&lt;/h2&gt;

&lt;p&gt;Here's how it all works:&lt;/p&gt;

&lt;p&gt;Prism is made available with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Prism&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;prismjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;The theme comes from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prismjs/themes/prism-okaidia.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is one of the default themes Prism ships with. The others are located in the project's 'node_modules/prismjs/themes' directory. They are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://scratchpad.alanwsmith.com/prism-default-theme-examples/prism"&gt;prism.css&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://scratchpad.alanwsmith.com/prism-default-theme-examples/coy"&gt;prism-coy.css&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://scratchpad.alanwsmith.com/prism-default-theme-examples/dark"&gt;prism-dark.css&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://scratchpad.alanwsmith.com/prism-default-theme-examples/funky"&gt;prism-funky.css&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://scratchpad.alanwsmith.com/prism-default-theme-examples/okaidia"&gt;prism-okaidia.css&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://scratchpad.alanwsmith.com/prism-default-theme-examples/solarizedlight"&gt;prism-solarizedlight.css&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://scratchpad.alanwsmith.com/prism-default-theme-examples/tomorrow"&gt;prism-tomorrow.css&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://scratchpad.alanwsmith.com/prism-default-theme-examples/twilight"&gt;prism-twilight.css&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Switch out the &lt;code&gt;import&lt;/code&gt; call to point to whichever one you prefer.&lt;/p&gt;

&lt;p&gt;There are also ways to make and use custom themes as well. That's left as an exercise for the reader. &lt;/p&gt;




&lt;p&gt;Be default, Prism loads syntax highlighting for "markup, css, clike, and javascript". Other languages need to be imported explicitly. In the example, I'm adding JSX with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prismjs/components/prism-jsx.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what lets us call the &lt;code&gt;language-jsx&lt;/code&gt; class in our &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;

&lt;p&gt;(Look in your project's 'node_modules/prismjs/components' directory for all the available languages.)&lt;/p&gt;




&lt;p&gt;Prepping to use the line numbers is done with these two import statements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prismjs/plugins/line-numbers/prism-line-numbers.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prismjs/plugins/line-numbers/prism-line-numbers.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a bunch of other plugins available in the project's 'node_modules/prismjs/plugins' like &lt;code&gt;copy-to-clipboard&lt;/code&gt;, &lt;code&gt;line-highlight&lt;/code&gt;, etc... that are worth looking at too.&lt;/p&gt;




&lt;p&gt;Actually getting Prism to do its thing is done with &lt;code&gt;Prism.highlightAll()&lt;/code&gt; in &lt;code&gt;useEffect()&lt;/code&gt; with these lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;useEffect&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;Prism&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;highlightAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;The last two parts that turn on the line numbers and set the language go hand in hand. They're done with &lt;code&gt;className="line-numbers"&lt;/code&gt; and &lt;code&gt;className="language-jsx"&lt;/code&gt; in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"line-numbers"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"language-jsx"&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;codeSample&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;code&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;One last note. I use &lt;a href="https://github.com/hashicorp/next-mdx-remote"&gt;next-mdx-remote&lt;/a&gt; for my site. I make code blocks with &lt;a href="https://docs.github.com/en/github/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks"&gt;code fences&lt;/a&gt; (i.e. three backticks in a row on the before and after the code). There's no way in the markdown to send a signal to turn on the line numbers in the &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; tag. I work around that by &lt;a href="https://github.com/hashicorp/next-mdx-remote#replacing-default-components"&gt;replacing the default components&lt;/a&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MDXRemote&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;pre&lt;/span&gt;&lt;span class="p"&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"line-numbers"&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;pre&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="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That adds the &lt;code&gt;className="line-numbers"&lt;/code&gt; call to all my &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; tags. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Review
&lt;/h2&gt;

&lt;p&gt;Now that you've seen the details, here's that code sample one more time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;useEffect&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Prism&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;prismjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prismjs/themes/prism-okaidia.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prismjs/components/prism-jsx.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prismjs/plugins/line-numbers/prism-line-numbers.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prismjs/plugins/line-numbers/prism-line-numbers.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;useEffect&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;Prism&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;highlightAll&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;codeSample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;div className="example"&amp;gt;
  {Math.random()}
&amp;lt;/div&amp;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="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"line-numbers"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;code&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"language-jsx"&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;codeSample&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;code&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&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;Prism also offers line highlighting. There isn't a way to use it with default markdown code blocks since the line numbers are dependent on the specific code snippets. Getting those in place (along with some of the other Prism plugins) requires making new, custom components. &lt;/p&gt;

&lt;p&gt;But, that's for another time. For now, syntax highlighting with line numbers has me taken care of.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Alan W. Smith runs &lt;a href="https://www.alanwsmith.com"&gt;his site&lt;/a&gt; and a &lt;a href="https://www.alanwsmith.com/podcast"&gt;podcast&lt;/a&gt;. He's also on &lt;a href="https://twitter.com/TheIdOfAlan"&gt;Twitter&lt;/a&gt; and &lt;a href="https://www.twitch.tv/theidofalan"&gt;Twitch&lt;/a&gt; from time to time playing around with &lt;a href="https://ideas.alanwsmith.com/"&gt;ideas.alanwsmith.com&lt;/a&gt;, &lt;a href="https://jacktorrance.blog/"&gt;jacktorrance.blog&lt;/a&gt;, &lt;a href="https://monocrack.alanwsmith.com/"&gt;Mono Crack&lt;/a&gt;, and &lt;a href="https://www.surftech.tv/"&gt;SurfTech.tv&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Practicing On The Small Stuff</title>
      <dc:creator>Alan W. Smith</dc:creator>
      <pubDate>Wed, 14 Oct 2020 15:51:31 +0000</pubDate>
      <link>https://dev.to/alanwsmith/practicing-on-the-small-stuff-cm6</link>
      <guid>https://dev.to/alanwsmith/practicing-on-the-small-stuff-cm6</guid>
      <description>&lt;p&gt;[&lt;em&gt;originally posted on &lt;a href="https://www.alanwsmith.com"&gt;alanwsmith.com&lt;/a&gt; by &lt;a href="https://twitter.com/TheIdOfAlan"&gt;@TheIdOfAlan&lt;/a&gt;&lt;/em&gt;]&lt;/p&gt;




&lt;p&gt;I spent a &lt;a href="https://www.alanwsmith.com/stream-notes-2020-10-13/"&gt;couple hours last night&lt;/a&gt; modifying a script to do the same thing it was already doing.&lt;/p&gt;

&lt;p&gt;Refactoring, but not really. I was trying something different. Trying to get better at test-driven development. Testing everything.&lt;/p&gt;

&lt;p&gt;The script is small. Just 100 lines. I could have written it in half that and been done in 20 minutes. Instead, I’ve spent hours on it. I’m not only okay with that, I’m embracing it. I’m practicing. Practicing on the small stuff so my skills are sharp when I get to the big stuff.&lt;/p&gt;

&lt;p&gt;I felt foolish at first, spending so much time on such a small script. But, I’m over that. It’s like a musician doing scales. It’s how you get the notes in your fingers and the chords in your head.&lt;/p&gt;

&lt;p&gt;It’s how you get better.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>testing</category>
    </item>
    <item>
      <title>Explicit Over Implicit: More Code Is Better</title>
      <dc:creator>Alan W. Smith</dc:creator>
      <pubDate>Mon, 12 Oct 2020 21:43:28 +0000</pubDate>
      <link>https://dev.to/alanwsmith/explicit-over-implicit-more-code-is-better-4fgh</link>
      <guid>https://dev.to/alanwsmith/explicit-over-implicit-more-code-is-better-4fgh</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted on &lt;a href="https://www.alanwsmith.com/"&gt;alanwsmith.com&lt;/a&gt; by &lt;a href="https://twitter.com/TheIdOfAlan"&gt;@TheIdOfAlan&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;I’m looking for examples to use as examples (e.g. “lists of names, lists of animals, simple math equations, etc.."). Turns out, it’s hard to look up sets of examples &lt;em&gt;for&lt;/em&gt; coding without getting examples &lt;em&gt;of&lt;/em&gt; coding&lt;sup&gt;1&lt;/sup&gt;. That’s fine, even if it’s a little meta.&lt;/p&gt;

&lt;p&gt;During my search I found &lt;a href="https://www.topcoder.com/coding-best-practices/"&gt;this post titled Coding Best Practices&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The bullet points make sense. Use consistent indentation, follow the DRY principle, etc… But, I side-eyed the “Keep The Code Simple” example&lt;sup&gt;2&lt;/sup&gt;. It says this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;numbers_are_in_range&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="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;c&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;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;should be written like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;numbers_are_in_range&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="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fewer lines? Sure.&lt;/p&gt;

&lt;p&gt;Simpler? Not so much.&lt;/p&gt;

&lt;p&gt;That code is harder to understand.&lt;/p&gt;

&lt;p&gt;Implicit returns (like the second snippet) take more brain power to deal with than explicit ones (like the first example)&lt;sup&gt;3&lt;/sup&gt;. In this case, you know at a glance that the first snippet will return one of two possible values: True or False. In the second snippet, you have to mentally walk through the formula to reason out what the possibilities are.&lt;/p&gt;

&lt;p&gt;You don’t notice the effort when you’re writing the initial code. The context is already in your head. It’s every other time we use it that we’ll feel the impact. We spend infinitely more time in the future working on our code than when we first write it. It’s in our best interest to make things as clear (and as explicit) as possible for our future selves.&lt;/p&gt;

&lt;p&gt;Equating fewer lines with simpler code is an easy mistake to make. But, it’s not always the case. Don’t be afraid of those extra lines when they add clarity. They’re your friends.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Footnotes&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I’ve realized that I can go to the wonderful exercism.io for examples of examples.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Yep. I translated the example into python functions. And, while I don’t want to get into it in this post, I wonder if there’s not be a cleaner way to code the conditional as well as.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don’t just take my word for it. The Zen of Python’s second line is literally:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Explicit is better than implicit.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>python</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Create an AWS IAM Policy That Lets Users Manage Their Own Credentials and MFA</title>
      <dc:creator>Alan W. Smith</dc:creator>
      <pubDate>Mon, 17 Jun 2019 20:32:12 +0000</pubDate>
      <link>https://dev.to/alanwsmith/create-an-aws-iam-policy-that-lets-users-manage-their-own-credentials-and-mfa-14ja</link>
      <guid>https://dev.to/alanwsmith/create-an-aws-iam-policy-that-lets-users-manage-their-own-credentials-and-mfa-14ja</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="http://alanwsmith.com/how-to-create-an-iam-policy-that-lets-users-manage-their-credentials"&gt;alanwsmith.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I've been digging into Amazon Web Services (AWS)&lt;sup&gt;1&lt;/sup&gt; user administration. One of my first goals was to create a user, send them their password, and let them manage the rest of their credentials without me. &lt;/p&gt;

&lt;p&gt;The various credential types are located under the "My Security Credentials&lt;sup&gt;2&lt;/sup&gt;" section for each user. They are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;IAM Password for console access&lt;/li&gt;
&lt;li&gt;Access keys for CLI, SDK, &amp;amp; API access&lt;/li&gt;
&lt;li&gt;Multi-factor authentication (MFA)&lt;/li&gt;
&lt;li&gt;X.509 certificate&lt;/li&gt;
&lt;li&gt;SSH Keys&lt;/li&gt;
&lt;li&gt;HTTPS Git credentials for AWS CodeCommit&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Amazon provides five built-in IAM policies that provide access to the credential sets. The first one, &lt;code&gt;IAMFullAccess&lt;/code&gt;, provides full admin control over the Identity and Access Management (IAM) service. Not only does it allow users to manage their own details, it allows them to create, delete, and otherwise mess with any other user, group, policy, role, etc... Not something to give a non-admin user. &lt;/p&gt;

&lt;p&gt;A second built-in AWS policy is &lt;code&gt;IAMReadOnlyAccess&lt;/code&gt;. It does just what it says on the tin, providing read-only access to the various parts of the IAM dashboard. So, no help there when it comes to letting users set their credentials. &lt;/p&gt;

&lt;p&gt;The last three built-in policies (and what they correspond to) are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;IAMSelfManageServiceSpecificCredentials&lt;/code&gt; - allows users to update their HTTPS Git credentials for AWS CodeCommit&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IAMUserChangePassword&lt;/code&gt; - allows users to update their IAM Password for console access&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IAMUserSSHKeys&lt;/code&gt; - allows users to update their SSH Keys&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Half way there, but we're still left without the ability to manage "Access keys for CLI, SDK, &amp;amp; API access", "Multi-factor authentication (MFA)", and "X.509 certificate". Since what I was looking for wasn't built-in, I went about building a custom policy myself. &lt;/p&gt;

&lt;p&gt;After referencing a half dozen web pages, IAM docs&lt;sup&gt;3&lt;/sup&gt; and just as many StackOverflow&lt;sup&gt;4&lt;/sup&gt; pages, I came up with the following policy definition. It provides users with control of all six sets of credentials. It also required Multi-Factor Authentication (MFA)&lt;sup&gt;5&lt;/sup&gt; and locks users out of all AWS services until it's set up. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["iam:ListVirtualMFADevices"],
      "Resource": "*"
    },
    {
      "Sid": "AllowUsersToManageCoreCredentials",
      "Effect": "Allow",
      "Action": [
        "iam:*AccessKey*",
        "iam:ChangePassword",
        "iam:GetUser",
        "iam:*ServiceSpecificCredential*",
        "iam:*SigningCertificate*"
      ],
      "Resource": ["arn:aws:iam::*:user/${aws:username}"]
    },
    {
      "Sid": "AllowIndividualUserToListOnlyTheirOwnMFA",
      "Effect": "Allow",
      "Action": ["iam:ListMFADevices"],
      "Resource": [
        "arn:aws:iam::*:mfa/*",
        "arn:aws:iam::*:user/${aws:username}"
      ]
    },
    {
      "Sid": "AllowIndividualUserToManageTheirOwnMFA",
      "Effect": "Allow",
      "Action": [
        "iam:CreateVirtualMFADevice",
        "iam:DeleteVirtualMFADevice",
        "iam:EnableMFADevice",
        "iam:ResyncMFADevice"
      ],
      "Resource": [
        "arn:aws:iam::*:mfa/${aws:username}",
        "arn:aws:iam::*:user/${aws:username}"
      ]
    },
    {
      "Sid": "AllowIndividualUserToDeactivateOnlyTheirOwnMFAOnlyWhenUsingMFA",
      "Effect": "Allow",
      "Action": ["iam:DeactivateMFADevice"],
      "Resource": [
        "arn:aws:iam::*:mfa/${aws:username}",
        "arn:aws:iam::*:user/${aws:username}"
      ],
      "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
    },
    {
      "Sid": "AllowIndividualUserToManageTheirSSHCredentials",
      "Effect": "Allow",
      "Action": [
        "iam:DeleteSSHPublicKey",
        "iam:GetSSHPublicKey",
        "iam:ListSSHPublicKeys",
        "iam:UpdateSSHPublicKey",
        "iam:UploadSSHPublicKey"
      ],
      "Resource": "arn:aws:iam::*:user/${aws:username}"
    },
    {
      "Sid": "BlockMostAccessUnlessSignedInWithMFA",
      "Effect": "Deny",
      "NotAction": [
        "iam:CreateVirtualMFADevice",
        "iam:EnableMFADevice",
        "iam:ListMFADevices",
        "iam:ListUsers",
        "iam:ListVirtualMFADevices",
        "iam:ResyncMFADevice"
      ],
      "Resource": "*",
      "Condition": {"BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}}
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Speaking of MFA, it's easy to use in the web console. Using it on the command line isn't as straight forward. For details on the basic process check out &lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/authenticate-mfa-cli/"&gt;this video from Amazon&lt;/a&gt;. (If you're like me, this looks like a prime opportunity to write a little script to help automate the process. That's left as an exercise for the reader.)&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Footnotes&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;One of the marvels of the modern world, &lt;a href="https://aws.amazon.com"&gt;Amazon Web Services&lt;/a&gt; is &lt;em&gt;the&lt;/em&gt; "&lt;a href="https://en.wikipedia.org/wiki/Cloud_computing"&gt;Cloud Computing&lt;/a&gt;" platform that's eating the software world.&lt;/li&gt;
&lt;li&gt;Every user has a &lt;a href="https://console.aws.amazon.com/iam/home?#/security_credentials"&gt;My Security Credentials&lt;/a&gt; section they can use to manage their various credentials, assuming they have permissions to do so. Which, of course, is what this post is all about.&lt;/li&gt;
&lt;li&gt;Amazon's documentation is some of the best I've ever seen. The &lt;a href="https://docs.aws.amazon.com/iam/index.html"&gt;IAM docs&lt;/a&gt; are no exception (despite not having the specific thing I was after).&lt;/li&gt;
&lt;li&gt;Another marvel of the modern world, &lt;a href="https://stackoverflow.com"&gt;StackOverflow&lt;/a&gt; is &lt;em&gt;the&lt;/em&gt; place to go for all your programming question wants and needs. (Though, again, they didn't have what I was looking for. At least, not until I post this there as well.)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Multi-factor_authentication"&gt;Multi-factor Authentication&lt;/a&gt; is &lt;em&gt;the&lt;/em&gt; way to go. The basic idea is that logging in requires "something you have and something you know". The thing you know is your password. The thing you have is some type of device (or app on your phone) that spits out random numbers every 30 seconds. If you don't have the proper numbers to go along with your password, you can't login. The reason this is important is if your password gets stolen, the bad guys can't get in but you still can with your MFA device. &lt;/li&gt;
&lt;/ol&gt;

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