Tanner Dolby's blog about web development and technology.I mostly write about front-end web development, but sometimes I'll write about other cool stuff too.2023-10-31T00:00:00Zhttps://tannerdolby.com/writing/Tanner Dolbytannercdolby@gmail.comGenerate Fibonacci Numbers2023-10-31T00:00:00Zhttps://tannerdolby.com/writing/generate-fibonacci-numbers/<p>The Fibonacci sequence is a series of numbers where each number in the sequence is the sum of the two preceding numbers, with the sequence beginning with 0 and 1. In mathematics, the Fibonacci numbers form the sequence, where numbers (n) are greater than 1 (n > 1).</p>
<p>To better understand how the fibonacci numbers are created in the sequence, view the below equation for generating any number in the <a href="https://en.wikipedia.org/wiki/Fibonacci_number">fibonacci sequence</a>.</p>
<blockquote>
<p>F<sub>n</sub> = F<sub>n-1</sub> + F<sub>n-2</sub></p>
</blockquote>
<h2 class="post-heading">Generate the Nth Fibonacci Number</h2>
<p>To calculate the F(N), we can reach for a simple to understand naive recursive algorithm which runs in O(2^n) time and O(n) space that can be optimzed to O(n) time and O(n) space using memoization. Last but not least, an iterative algorithm using dynamic programming for acheiving constant space complexity with O(n) time and O(1) space.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// O(2^n) time and O(n) space</span><br /><span class="token keyword">function</span> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token parameter">int n</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token keyword">return</span> n<span class="token punctuation">;</span><br /> <span class="token keyword">return</span> <span class="token function">fib</span><span class="token punctuation">(</span>n<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token function">fib</span><span class="token punctuation">(</span>n<span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Using a tree to better visualize how the recursive calls are happening when we attempt to call <code>fib(n)</code>, view the example below. At each root node, the algorithm requires two operations in order to compute the <code>fib(n-1)</code> and <code>fib(n-2)</code> values. That is, if there is <code>n</code> nodes in the tree, we will require <code>2^n</code> operations to compute each root nodes left and right child node.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// 2^n operations</span><br /><span class="token comment">// for example fib(2) is computed twice and fib(1) and fib(3) computed thrice</span><br /><br /> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><br /> <span class="token operator">/</span> \<br /> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><br /> <span class="token operator">/</span> \ <span class="token operator">/</span> \<br /> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><br /> <span class="token operator">/</span> \<br /> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><br /> <span class="token operator">/</span><br /> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span></code></pre>
<h3>Optimized Approaches</h3>
<p>To provide a more efficient algorithm than the naive recusive. We can take a dynamic programming approach and achieve linear time complexity as this problem is easily broken into smaller subproblems. Instead of recomputing values throughout the tree of recursive calls we can instead use memoization to compute the values once and store them in a hash table. That way, when we need to compute the value again, we instead return the stored value from table and greatly improve the time complexity of the recursive algorithm.</p>
<p>The recursive calls will still be added to the recursion stack, which occupies O(n) space in memory as the depth of the tree will determine the number of recursive calls on the stack at a given time.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// O(n) time and O(n) space</span><br /><span class="token keyword">function</span> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token parameter">n</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> memo <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span><br /> memo<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><br /> memo<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> <span class="token function">fibHelper</span><span class="token punctuation">(</span>n<span class="token punctuation">,</span> memo<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token keyword">function</span> <span class="token function">fibHelper</span><span class="token punctuation">(</span><span class="token parameter">n<span class="token punctuation">,</span> memo</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token keyword">return</span> n<span class="token punctuation">;</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>Object<span class="token punctuation">.</span><span class="token function">hasOwn</span><span class="token punctuation">(</span>memo<span class="token punctuation">,</span> n<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// F(n) value doesn't exist in table yet, </span><br /> <span class="token comment">// so we compute it and store it in the table</span><br /> memo<span class="token punctuation">[</span>n<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">fibHelper</span><span class="token punctuation">(</span>n<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> memo<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token function">fibHelper</span><span class="token punctuation">(</span>n<span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">,</span> memo<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token comment">// otherwise we have stored the value already in table</span><br /> <span class="token comment">// so simple return the stored value instead of recomputing</span><br /> <span class="token keyword">return</span> memo<span class="token punctuation">[</span>n<span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Recursion visualization:</p>
<pre class="language-js"><code class="language-js"> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><br /> <span class="token operator">/</span> \<br /> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span> m<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><br /> <span class="token operator">/</span> \ <span class="token operator">/</span> \<br /> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> m<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> m<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> m<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><br /> <span class="token operator">/</span> \<br /> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> m<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><br /> <span class="token operator">/</span><br /> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span></code></pre>
<p>If you're having trouble understanding the recursive algorithms, go ahead and watch <a href="https://www.youtube.com/watch?v=P8Xa2BitN3I">Algorithms: Memoization and Dynamic Programming</a> by the HackerRank channel on Youtube. Gayle Laakmann McDowell (author of Cracking the Coding Interview) does an incredible job of explaining recursion, dynamic programming and memoization.</p>
<p>If you need an algorithm with constant space complexity. Checkout this iterative dynamic programming approach which utilizes an array of length two and only keeps track of two fibonacci numbers at a time, swapping them into the two available array slots as we calculate the next Nth fib using the array.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// O(n) time and O(1) space</span><br /><span class="token keyword">function</span> <span class="token function">fib</span><span class="token punctuation">(</span><span class="token parameter">n</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token keyword">return</span> n<span class="token punctuation">;</span><br /> <span class="token keyword">const</span> dp <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">;</span> i <span class="token operator"><=</span> n<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> nthFib <span class="token operator">=</span> dp<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">+</span> dp<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> dp<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> dp<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> dp<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> nthFib<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token keyword">return</span> dp<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<h2 class="post-heading">Generate the Fibonacci sequence</h2>
<p>Now that the underlying mathematical equation is known for calculating Fibonacci numbers, let's write an iterative solution that generates an array containing the fibonacci sequence.</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// O(n) time and O(n) space</span><br /><span class="token keyword">function</span> <span class="token function">fibSequence</span><span class="token punctuation">(</span><span class="token parameter">n</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> nums <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">}</span><span class="token punctuation">;</span><br /> <span class="token keyword">for</span> <span class="token punctuation">(</span>int i <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span> i <span class="token operator"><=</span> n<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> nums<span class="token punctuation">[</span>i<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">+</span> nums<span class="token punctuation">[</span>i<span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token keyword">return</span> nums<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>The above function <code>fibSequence</code> accepts one parameter, the Nth fibonacci number where the sequence should end at and returns an array containing the fibonacci sequence from (0, n). For example, passing in <code>n = 7</code> will generate the following sequence:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> sequence <span class="token operator">=</span> <span class="token function">fibSequence</span><span class="token punctuation">(</span><span class="token number">7</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> lastFib <span class="token operator">=</span> sequence<span class="token punctuation">[</span><span class="token number">7</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">F(7) = </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>lastFib<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// F(7) = 13</span><br /><br /><span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> sequence<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>sequence<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">+</span> <span class="token string">" "</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><span class="token comment">// 0 1 1 2 3 5 8 13</span></code></pre>
<p>Using a recursive approach to generate the sequence:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">fibSequence</span><span class="token punctuation">(</span><span class="token parameter">n</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>n <span class="token operator"><</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> sequence <span class="token operator">=</span> <span class="token function">fibSequence</span><span class="token punctuation">(</span>n<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> sequence<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>sequence<span class="token punctuation">[</span>n<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">+</span> sequence<span class="token punctuation">[</span>n<span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> sequence<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
Solving the Diagonal Difference and Sum Problem2023-04-09T00:00:00Zhttps://tannerdolby.com/writing/solving-the-diagonal-difference-and-sum-problem/<p>This article will discuss how to calculate the diagonal difference and sum for a n x n square matrix. The diagonal difference problem can be found on <a href="https://www.hackerrank.com/challenges/diagonal-difference/problem">HackerRank</a> and the diagonal sum problem can be found on LeetCode <a href="https://leetcode.com/problems/matrix-diagonal-sum/">1572. Matrix Diagonal Sum</a>.</p>
<h2 class="post-heading">Getting Started</h2>
<p>To begin, we are given a n x n square matrix as input. We're asked to create a function that returns the diagonal difference or sum of the matrix. To understand what "diagonal" means in this context, think of a diagonal line starting from the top left corner running to the bottom right corner. This would be the "left diagonal" and the "right diagonal" would start at the top right corner and run to the bottom left, spanning each of the numbers in its path.</p>
<p>For a more visual representation, consider this 4 x 4 square matrix:</p>
<pre class="language-js"><code class="language-js"><span class="token number">2</span> <span class="token number">4</span> <span class="token number">5</span> <span class="token number">6</span><br /><span class="token number">8</span> <span class="token number">3</span> <span class="token number">1</span> <span class="token number">3</span><br /><span class="token number">7</span> <span class="token number">9</span> <span class="token number">4</span> <span class="token number">2</span><br /><span class="token number">5</span> <span class="token number">8</span> <span class="token number">3</span> <span class="token number">6</span></code></pre>
<p>If we start at the top left corner (first index of the first row) and move to the right one unit and down one unit we end up at <code>3</code>. Continuing along this "diagonal" path, we end up with the values (2, 3, 4, 6) for the left diagonal. Following the same logic to find the "right diagonal", we start in the right corner (last index of the first row) and move left one unit and down one unit. Repeating this movement until reaching the bottom left corner and we will have the values (6, 1, 9, 5) for the right diagonal.</p>
<h2 class="post-heading">Writing The Algorithms</h2>
<p>Now that it's clear how to find the "diagonal" values in a square matrix, let's write algorithms to calculate the diagonal difference or sum. To begin, the sample input will be a two-dimensional integer array. If your not familiar with 2D arrays, they look like this:</p>
<pre class="language-java"><code class="language-java"><span class="token punctuation">[</span><br /> <span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> <span class="token punctuation">[</span><span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> <span class="token punctuation">[</span><span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> <span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">]</span><br /><span class="token punctuation">]</span></code></pre>
<p>Where an outer array holds inner arrays within it, hence the "two-dimensional" array definition. If we were to write an iteration statement, like a <code>for</code> loop on the outer array. It would iterate over each of the "inner" arrays. Here is an example:</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span> arr <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">{</span><br /> <span class="token punctuation">{</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">{</span><span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">{</span><span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">{</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">}</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> arr<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token class-name">Arrays</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><span class="token comment">// [2, 4, 5, 6]</span><br /><span class="token comment">// [8, 3, 1, 3]</span><br /><span class="token comment">// [7, 9, 4, 2]</span><br /><span class="token comment">// [5, 8, 3, 6]</span></code></pre>
<p>To access the inner array values, we will need to use two index values, <code>arr[firstIndex][secondIndex]</code>. The <code>firstIndex</code> will access the inner array from the outer "parent" array and the <code>secondIndex</code> will be the index within the inner array that we retreive a value for.</p>
<p>To better understand working with 2D arrays, we can use another nested <code>for</code> loop to understand where the <code>secondIndex</code> comes into play.</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span> arr <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">{</span><br /> <span class="token punctuation">{</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">{</span><span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">{</span><span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">{</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">}</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">int</span> n <span class="token operator">=</span> arr<span class="token punctuation">.</span>length<span class="token punctuation">;</span><br /><br /><span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> n<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> j <span class="token operator"><</span> n<span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"("</span> <span class="token operator">+</span> i <span class="token operator">+</span> <span class="token string">","</span> <span class="token operator">+</span> j <span class="token operator">+</span> <span class="token string">") "</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>The above code will output each index of the 2D array.</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span> <span class="token comment">// [2, 4, 5, 6]</span><br /><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span> <span class="token comment">// [8, 3, 1, 3]</span><br /><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span> <span class="token comment">// [7, 9, 4, 2]</span><br /><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span> <span class="token comment">// [5, 8, 3, 6]</span></code></pre>
<p>Now that we have a good grasp of what the 2D array looks like in terms of array structure, let's write some logic to calculate the diagonal difference and sum. That is, the absolute value of the left diagonal minus the right diagonal <code>|(2 + 3 + 4 + 6) - (6 + 1 + 9 + 5)|</code> or the sum of the diagonals.</p>
<h2 class="post-heading">Calculate the Diagonal Difference</h2>
<p>If you study the above square matrix, you will notice the left diagonal values occur when the first index equals the second index. That is, when <code>i == j</code> (if you use i and j as loop control variables). Each value within the left diagonal occurs at (0, 0), (1, 1), (2, 2), (3, 3). Now that we have an idea of how to obtain each of the left diagonal values, let's move onto to finding the right diagonal.</p>
<blockquote>
<p>Remember this 4 x 4 square matrix is a 2D array and holds 4 inner arrays within the outer array.</p>
</blockquote>
<p>Therefore, the length of the outer array and each inner array is <code>4</code> due to the "square" nature of these matrices. If you look closely, each of the indexes in the right diagonal sum to 3 which is the length of the array minus one. Using a single control variable <code>i</code>, this can be simplified as we are simply moving forward a single row and column at each iteration.</p>
<p>To find the values within the right diagonal, we find the values where the sum of index i + j equals <code>array.length-1</code>. To write it out more clearly, using a single index <code>i</code>, we can find values along the right diagonal using <code>n-1-i</code>, where <code>n</code> equals <code>array.length</code>.</p>
<p>As we increment <code>i</code> by one while iterating the matrix, we first start at row zero where <code>i=0</code> so <code>n-1-i = 4-1-0 = 3</code> that is, the top-right corner at <code>(0,3)</code> which is represented by <code>(i, n-1-i)</code>. Following this logic we can move to the next row where <code>i=1</code> and see <code>n-1-1 = 4-1-1 = 2</code> which represents the cell one unit to the left and one unit down <code>(1, 2)</code>. Continuing along this path until reaching the bottom-left corner.</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">0</span> <span class="token operator">+</span> <span class="token number">3</span> <span class="token operator">=</span> <span class="token number">3</span><br /><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">1</span> <span class="token operator">+</span> <span class="token number">2</span> <span class="token operator">=</span> <span class="token number">3</span><br /><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">2</span> <span class="token operator">+</span> <span class="token number">1</span> <span class="token operator">=</span> <span class="token number">3</span><br /><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">=</span> <span class="token number">3</span> <span class="token operator">+</span> <span class="token number">0</span> <span class="token operator">=</span> <span class="token number">3</span></code></pre>
<p>After summing both diagonals, the function can return the absolute difference of the diagonals to reach our desired solution. The logic below passes the HackerRank test cases.</p>
<div class="filename-title"><span>Filename</span>: <em>Matrix.java</em></div>
<pre class="language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Matrix</span> <span class="token punctuation">{</span><br /> <span class="token comment">// O(n) time | O(1) space</span><br /> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">int</span> <span class="token function">diagonalDiff</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span> arr<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">int</span> n <span class="token operator">=</span> arr<span class="token punctuation">.</span>length<span class="token punctuation">;</span><br /> <span class="token keyword">int</span> leftDiagonal <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> rightDiagonal <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><br /> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> n<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> leftDiagonal <span class="token operator">+=</span> arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span><br /> rightDiagonal <span class="token operator">+=</span> array<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>n<span class="token operator">-</span><span class="token number">1</span><span class="token operator">-</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token keyword">return</span> <span class="token class-name">Math</span><span class="token punctuation">.</span><span class="token function">abs</span><span class="token punctuation">(</span>leftDiag <span class="token operator">-</span> rightDiag<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<p>The question could also use a <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html"><code>List</code></a> interface to maintain the sequence of integers. The function signature would look different as it will use <code>List<List<Integer>> arr</code> and accessing elements in a 2D list looks like: <code>arr.get(i).get(j)</code>. The same algorithm can be used, its just a slightly different data structure than <code>int[][]</code> to hold the input matrix.</p>
<h2 class="post-heading">Calculate the Diagonal Sum</h2>
<p>Given a square matrix, return the sum of the matrix diagonals.</p>
<p>Only include the sum of all the elements on the primary diagonal and all the elements on the secondary diagonal that are not part of the primary diagonal.</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Matrix</span> <span class="token punctuation">{</span><br /> <span class="token comment">// O(n) time | O(1) space</span><br /> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">int</span> <span class="token function">diagonalSum</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span> arr<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">int</span> n <span class="token operator">=</span> arr<span class="token punctuation">.</span>length<span class="token punctuation">;</span><br /> <span class="token keyword">int</span> sum <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><br /> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> n<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// if the indexes are equal, only add the value from one diagonal</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>i <span class="token operator">==</span> n<span class="token operator">-</span><span class="token number">1</span><span class="token operator">-</span>i<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> sum <span class="token operator">+=</span> arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span><br /> sum <span class="token operator">+=</span> arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">+</span> arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>n<span class="token operator">-</span><span class="token number">1</span><span class="token operator">-</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><br /> <span class="token keyword">return</span> sum<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<h3 class="post-heading">Outro
<p>This article should prepare you for finding the diagonals of any square matrix and calculating the diagonal difference or sum. Thanks for reading!</p>
<blockquote>
<p>Linear algebra 101: When a square matrix has its left diagonal values equaling <code>1</code> and the other values (everything but the left diagonal) equaling <code>0</code>, the matrix is said to be Linearly Independent. To obtain only 1s and 0s in your square matrix, you will need to perform row-reduction which is outside the scope of this article but food for thought!</p>
</blockquote>
</h3>Searching in a Binary Search Tree2023-01-04T00:00:00Zhttps://tannerdolby.com/writing/searching-in-a-bst/<p>Finding a value in a BST can be done iteratively or recursively in logarithmic time on average because of the properties of a BST.</p>
<p>The <a href="https://en.wikipedia.org/wiki/Tree_(data_structure)">Tree</a> data structure is commonly used to represent hierarchical data. A tree can have up to <code>n</code> child nodes, where in a <a href="https://en.wikipedia.org/wiki/Binary_tree">Binary Tree</a> the maximum number of children is two. Building on this, a <a href="https://en.wikipedia.org/wiki/Binary_search_tree">Binary Search Tree</a> has the following properties:</p>
<ol>
<li>All of the nodes in the left subtree must be strictly less than the root node.</li>
<li>All of the nodes in the right subtree must be greater than or equal to the root node.</li>
</ol>
<p>Example BST:</p>
<pre class="language-txt"><code class="language-txt"> 4<br /> / \<br /> 2 6<br /> / \ / \<br /> 1 3 5 8 </code></pre>
<p>Since we will be searching for a value in Binary Search Tree, I thought the above information would be useful if your not familiar with trees, binary trees, and BST's.</p>
<h2 class="post-heading">Searching in a BST</h2>
<p>Given we are provided a BST, searching for a value can be done in O(log(N)) time and O(log(N)) space on average because at each root node we can compare the value to our target value and eliminate half of the tree each time. Using the following BST shown below with a search target of 13:</p>
<pre class="language-txt"><code class="language-txt"> 18<br /> / \<br /> 10 21<br /> / \ / \<br /> 5 13 16 35 </code></pre>
<p>The first step to begin searching for the target value of 13 would be to compare our search value to the root node as we traverse the tree. Since were searching for 13, we would check if the target is less than the root nodes value of 18 i.e. <code>if (target < root->val)</code>, and if true we can eliminate the right subtree and only traverse the left subtree because all values in the right subtree are greater than or equal to the root node meaning its not possible for a value less than the root to exist in the right subtree. Repeating this same logic for check if we traverse the right subtree i.e. <code>else if (target >= root->val)</code>, if the target is gte to the root value we will eliminate the left subtree and only traverse the right subtree as all values in the left subtree are strictly less than the root node. Repeating this process throughout the traversal until we find the search target or don't find it which will result in NULL</p>
<p>This algorithm on average will eliminate half of the tree at each step, resulting in a logarithmic runtime of O(log(N)) and O(N) in the worst case. Assuming nodes in the tree have the following structure:</p>
<pre class="language-cpp"><code class="language-cpp"><span class="token keyword">struct</span> <span class="token class-name">TreeNode</span> <span class="token punctuation">{</span><br /> <span class="token keyword">int</span> val<span class="token punctuation">;</span><br /> TreeNode <span class="token operator">*</span>left<span class="token punctuation">;</span><br /> TreeNode <span class="token operator">*</span>right<span class="token punctuation">;</span><br /> <span class="token function">TreeNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">val</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">left</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">right</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><br /> <span class="token function">TreeNode</span><span class="token punctuation">(</span><span class="token keyword">int</span> x<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">val</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">left</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">right</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<h3 class="post-heading">Recursive</h3>
<p>A Depth-first Search (DFS) algorithm to traverse the tree searching for a target value. This approach does add frames to the recursion stack which needs to be kept in mind when working with extremely large BSTs, as you need to make sure the frames on the stack don't result in a stack overflow. The iterative approach would be preferred for larger inputs as it runs in O(1) constant space and doesn't add calls to the recursion stack.</p>
<pre class="language-cpp"><code class="language-cpp"><span class="token comment">// Average: O(log(N)) time and O(log(N)) space</span><br /><span class="token comment">// Worst: O(N) time and O(N) space</span><br />TreeNode <span class="token operator">*</span><span class="token function">searchBST</span><span class="token punctuation">(</span>TreeNode <span class="token operator">*</span>root<span class="token punctuation">,</span> <span class="token keyword">int</span> target<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token function">dfs</span><span class="token punctuation">(</span>root<span class="token punctuation">,</span> target<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br />TreeNode <span class="token operator">*</span><span class="token function">dfs</span><span class="token punctuation">(</span>TreeNode <span class="token operator">*</span>root<span class="token punctuation">,</span> <span class="token keyword">int</span> target<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>root <span class="token operator">==</span> <span class="token constant">NULL</span> <span class="token operator">||</span> root<span class="token operator">-></span>val <span class="token operator">==</span> target<span class="token punctuation">)</span> <span class="token keyword">return</span> root<span class="token punctuation">;</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>target <span class="token operator"><</span> root<span class="token operator">-></span>val<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token function">dfs</span><span class="token punctuation">(</span>root<span class="token operator">-></span>left<span class="token punctuation">,</span> target<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>target <span class="token operator">>=</span> root<span class="token operator">-></span>val<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token function">dfs</span><span class="token punctuation">(</span>root<span class="token operator">-></span>right<span class="token punctuation">,</span> target<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token keyword">return</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<h3 class="post-heading">Iterative</h3>
<p>This approach is similiar to the recursive logic as it runs in O(log(N)) time, but we only consume constant O(1) space which might make this algorithm the preferred choice when working with extremely large inputs.</p>
<pre class="language-cpp"><code class="language-cpp"><span class="token comment">// Average: O(log(N)) time and O(1) space</span><br /><span class="token comment">// Worst: O(N) time and O(1) space</span><br />TreeNode <span class="token operator">*</span><span class="token function">searchBST</span><span class="token punctuation">(</span>TreeNode <span class="token operator">*</span>root<span class="token punctuation">,</span> <span class="token keyword">int</span> target<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">while</span> <span class="token punctuation">(</span>root <span class="token operator">!=</span> <span class="token constant">NULL</span> <span class="token operator">&&</span> root<span class="token operator">-></span>val <span class="token operator">!=</span> target<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>target <span class="token operator">==</span> root<span class="token operator">-></span>val<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> root<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>target <span class="token operator"><</span> root<span class="token operator">-></span>val<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> root <span class="token operator">=</span> root<span class="token operator">-></span>left<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span><br /> root <span class="token operator">=</span> root<span class="token operator">-></span>right<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><br /> <span class="token keyword">return</span> root<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<h3 class="post-heading">Notes</h3>
<p>For practice, have a look at <a href="https://leetcode.com/problems/search-in-a-binary-search-tree/">700. Search in a Binary Search Tree</a> on LeetCode, and to better understand how we traverse the BST when searching for the target value, checkout <a href="https://www.youtube.com/watch?v=YEZo8n2y2v4">Applied CS Skills - Binary Search Tree</a> by the Google Students channel on YouTube.</p>
How transform-style made links unreachable on my website2022-02-18T00:00:00Zhttps://tannerdolby.com/writing/how-transform-style-made-links-unreachable-on-my-website/<p>I discovered some nested links weren't working on my site. After sifting through each page, I finally noticed that there was a CSS rule applying transform-style: preserve-3d to the entire home page instead of only the element that needed it, which caused unexpected rendering of nested links.</p>
<h2 class="post-heading">How to spot this?</h2>
<p>I only noticed this behavior happening on Firefox, but the warning signs could probably be applied to all browsers.</p>
<ul>
<li>nested links not being hoverable or clickable</li>
<li>inspecting an element in DevTools and being directed to the parent container for which your link is nested inside instead of taking you directly to the corresponding element</li>
</ul>
<p>Why did this happen? Essentially, I had applied <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-style"><code>transform-style</code></a> to all the elements on the page with:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">*,<br />*::before,<br />*::after</span> <span class="token punctuation">{</span><br /> <span class="token property">-webkit-transform-style</span><span class="token punctuation">:</span> preserve-3d<span class="token punctuation">;</span><br /> <span class="token property">transform-style</span><span class="token punctuation">:</span> preserve-3d<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>and this caused nested content to be rendered in a way where the top-level parent container appeared "above" or at the top of some stacking context (not z-index, but how nested elements are rendered in 3D space). Thus covering and essentially rendering the nested links useless as they couldn't be interacted with.</p>
<p>I'd recommend not applying <code>transform-style</code> to the whole page like I mistakenly had done, unless you are keeping track or defining how all nested elements are rendered in 3D space.</p>
<h2 class="post-heading">The Fix</h2>
<p>The resolution was simply applying the <code>transform-style</code> to only the elements on the page that needed it, instead of applying it to the whole page. In my case, there was a single element (3D cube CSS drawing) that required <code>transform-style: preserved-3d;</code>, after updating the selectors to only target the cube drawing, all my nested links started working again.</p>
<p>If you ever find yourself in a situation where nested links aren't rendering in the browser as expected, try looking for a <code>transform-style</code> declaration in the CSS as that could be what's causing rendering issues with nested links.</p>
Calculating the size of an array in C++ using the sizeof operator2022-02-05T00:00:00Zhttps://tannerdolby.com/writing/calculating-the-size-of-an-array-in-c++-using-the-sizeof-operator/<p>For a fixed-size array (non-dynamic), calculating the size can seem complicated but it's really quite simple when we think about how the sizeof operator works.</p>
<p>The <a href="https://en.cppreference.com/w/cpp/language/sizeof">sizeof</a> will yield the size in bytes of a variable or data structure. Given the fact that arrays are linear data structures for sequentially storing elements of the same type, we can get the size of the underlying array data structure and then divide it by the size of a single element in the array.</p>
<h2 class="post-heading">Why does this work?</h2>
<p>The reason we can do this is quite simple and was intended. To break things down lets take the following code:</p>
<pre class="language-cpp"><code class="language-cpp"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><iostream></span></span><br /><span class="token keyword">int</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// declare an integer array of size 6</span><br /> <span class="token keyword">int</span> arr<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token number">6</span><span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Since we are not working with a dynamic array which has variable size, the size of the integer array <code>arr</code> must be specified at initialization. To avoid simply remebering that number, we can utilize <code>sizeof()</code> to calculate the arrays size. For context, typically in computer architecture a <code>byte</code> equals 8 or more <code>bit</code>'s.</p>
<p>In C++, and when working on a 32/64 bit machine. An <code>int</code> is "usually" a fixed-width (32-bit) integer which is represented as 4 bytes. Any fixed-width integer value can have its size broken down into bytes and bits based on the definition of a <code>byte</code> for your computers architecture.</p>
<pre class="language-text"><code class="language-text">fixedWidth = numBytes * byteSize</code></pre>
<p>Therefore <code>32 = numBytes * byteSize</code> and we know a byte equals 8 bits so the equation becomes:</p>
<pre class="language-text"><code class="language-text">32 = numBytes * 8 </code></pre>
<p>Solving for the number of bytes <code>numBytes</code>, we can conclude <code>numBytes = 32 / 8</code> which equals 4 bytes. For another common fixed-width integer, the 64-bit integer, it would be represented as 8 bytes. Now let's get back to the code and calculate the size of the array to iterate all of the elements:</p>
<pre class="language-cpp"><code class="language-cpp"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span> <span class="token string"><iostream></span></span><br /><span class="token keyword">using</span> <span class="token keyword">namespace</span> std<span class="token punctuation">;</span><br /><span class="token keyword">int</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// declare an integer array of size 6</span><br /> <span class="token keyword">int</span> arr<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token number">6</span><span class="token punctuation">}</span><span class="token punctuation">;</span><br /> <span class="token comment">// n = 24 bytes / 4 bytes = 6</span><br /> <span class="token keyword">int</span> n <span class="token operator">=</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> n<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> cout <span class="token operator"><<</span> arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator"><<</span> <span class="token string">" "</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> cout <span class="token operator"><<</span> endl<span class="token punctuation">;</span><br /> <span class="token comment">// 1 2 3 4 5 6</span><br /> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Because <code>sizeof</code> yields the number of bytes a data structure represents, when we use <code>sizeof(arr)</code> we get 24 bytes since the array stores 6 values with <code>int</code> data type which occupy 4 bytes each. The size we initialized the array with is 6, so that means we have 6 * 4 = 24 bytes represented by <code>arr</code> in memory.</p>
<p>Next, using <code>sizeof(arr[0])</code> we can get the size of a given element in the array which will represent the number of bytes each element is represented by (since all the elements are the same data type). I usually grab the first element in the array <code>arr[0]</code> but any element would do, or using a pointer to <code>arr</code> like <code>sizeof(*arr)</code> would also accomplish the same task.</p>
<h3 class="post-heading">Calculating size</h3>
<pre class="language-cpp"><code class="language-cpp"><span class="token keyword">int</span> arr<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token number">6</span><span class="token punctuation">}</span><span class="token punctuation">;</span><br /><span class="token comment">// option 1</span><br /><span class="token keyword">int</span> size <span class="token operator">=</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// option 2</span><br /><span class="token keyword">int</span> n <span class="token operator">=</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span><span class="token operator">*</span>arr<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
Using index files when working with Sass and @use rules2021-08-22T00:00:00Zhttps://tannerdolby.com/writing/using-index-files-in-sass/<p>With @import at-rules slowly being phased out of the main implementation of Sass (dart-sass) and eventually deprecated, its time to learn how to use @use rules and the neat features that come along with it.</p>
<p>The main implementation of <a href="https://sass-lang.com/">Sass</a> is <a href="https://sass-lang.com/dart-sass"><code>dart-sass</code></a> and for the sake of this article, I will be using the <code>dart-sass</code> implementation as it gets new features before any of the other implementations. Before jumping into the details of <a href="https://sass-lang.com/documentation/at-rules/use"><code>@use</code></a> and <a href="https://sass-lang.com/documentation/at-rules/import#index-files">index files</a>. The <code>@import</code> at-rules in Sass are slowly being phased out and will eventually be deprecated in the next few years.</p>
<p>The Sass team discourages the continued use of the <a href="https://sass-lang.com/documentation/at-rules/import">@import</a> rule. Sass will gradually phase it out over the next few years, and eventually remove it from the language entirely. Prefer the <a href="https://sass-lang.com/documentation/at-rules/use">@use</a> rule instead.</p>
<blockquote>
<p>Only Dart Sass currently supports @use. Users of other implementations must use the @import rule instead.</p>
</blockquote>
<p>On GitHub, I <a href="https://github.com/mdn/mdn-minimalist/pull/712">helped drive</a> the transition from <code>@import</code> to <code>@use</code> at-rules for <a href="https://github.com/mdn/mdn-minimalist"><code>mdn/mdn-minimalist</code></a> which is the base Sass that powers <a href="https://developer.mozilla.org/en-US/">MDN Web Docs</a>. This conversion required me to study the Sass docs for transitioning from @import to @use and the details in this article are things I think are important when getting started with using <code>@use</code> and or working towards replacing your <code>@import</code> at-rules.</p>
<h2 class="post-heading">A new way to import</h2>
<p>Before the <code>@use</code> at-rule was introduced to Sass, we relied on importing things (mixins, variables, stylesheets) with the <code>@import</code> at-rule. Unfortunately, the <code>@import</code> rules introduced many serious issues that can be described on the Sass <a href="https://sass-lang.com/documentation">docs</a>. A few are:</p>
<ul>
<li>@import makes all variables, mixins, and functions globally accessible. This makes it very difficult for people (or tools) to tell where anything is defined.</li>
<li>Because everything’s global, libraries must prefix to all their members to avoid naming collisions.</li>
<li>Each stylesheet is executed and its CSS emitted every time it’s @imported, which increases compilation time and produces bloated output.</li>
</ul>
<p>Due to all of these flaws, the Sass team introduced a brand new and improved way to import your Sass stylesheets (mixins, functions, and variables) with <code>@use</code>. And honestly, it is so darn good. The old <code>@import</code> usage made everything globally accessible and now with <code>@use</code> the default namespace is the last component of the URL unless otherwise specified.</p>
<h3 class="post-heading">Using @import</h3>
<p>Before <code>@use</code> was introduced in <code>dart-sass</code>, if we had a directory of partial files containing some mixins like this:</p>
<div class="filename-title"><span>Filename</span>: <em>./mixins/_sr-only.scss</em></div>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@mixin</span> <span class="token function">screen-reader-only</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> ...<br /><span class="token punctuation">}</span></code></pre>
<div class="filename-title"><span>Filename</span>: <em>./mixins/_invert.scss</em></div>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@mixin</span> <span class="token function">invert</span><span class="token punctuation">(</span><span class="token variable">$c</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token property">filter</span><span class="token punctuation">:</span> <span class="token function">invert</span><span class="token punctuation">(</span><span class="token variable">#{$c}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <br /><span class="token punctuation">}</span></code></pre>
<div class="filename-title"><span>Filename</span>: <em>./mixins/_square.scss</em></div>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@mixin</span> <span class="token function">square</span><span class="token punctuation">(</span><span class="token variable">$x</span><span class="token punctuation">,</span> <span class="token variable">$y</span><span class="token punctuation">,</span> <span class="token variable">$c</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token property">width</span><span class="token punctuation">:</span> <span class="token variable">$x</span><span class="token punctuation">;</span><br /> <span class="token property">height</span><span class="token punctuation">:</span> <span class="token variable">$y</span><span class="token punctuation">;</span><br /> <span class="token property">background</span><span class="token punctuation">:</span> <span class="token variable">$c</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>We would have to import each file by using numerous <code>@import</code> at-rules and one by one import the partial files to our main file for usage and eventually compilation.</p>
<div class="filename-title"><span>Filename</span>: <em>style.scss</em></div>
<pre class="language-scss"><code class="language-scss"><span class="token comment">/* Import the mixins */</span><br /><span class="token keyword">@import</span> <span class="token string">"./mixins/sr-only"</span><span class="token punctuation">;</span><br /><span class="token keyword">@import</span> <span class="token string">"./mixins/invert"</span><span class="token punctuation">;</span><br /><span class="token keyword">@import</span> <span class="token string">"./mixins/square"</span><span class="token punctuation">;</span><br /><br /><span class="token selector">.hidden </span><span class="token punctuation">{</span><br /> <span class="token keyword">@include</span> <span class="token function">sr-only</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span> <br /><br /><span class="token selector">.demo </span><span class="token punctuation">{</span><br /> <span class="token keyword">@include</span> <span class="token function">invert</span><span class="token punctuation">(</span>0.30<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">@include</span> <span class="token function">square</span><span class="token punctuation">(</span>20px<span class="token punctuation">,</span> 20px<span class="token punctuation">,</span> #f06<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>If you only had a few mixins or files to import, this implementation wouldn't be that all bad. But if the <code>mixins</code> directory had 50 or more <a href="https://sass-lang.com/documentation/at-rules/use#partials">partial files</a>, then writing each <code>@import</code> line-by-line would start to be overwhelming in large codebases.</p>
<h3 class="post-heading">The power of @use at-rules</h3>
<p>With the introduction of <code>@use</code> at-rules, we have the ability to use <a href="https://sass-lang.com/documentation/at-rules/use#index-files">index files</a>. Using these index files allow us to use <a href="https://sass-lang.com/documentation/at-rules/forward"><code>@forward</code></a> rules in a <code>_index.scss</code> file so that when we load the URL of the directory <code>./mixins/</code>, all of the partial files will be loaded with it. Giving us access to an entire directory of sass files with a single <code>@use</code> at-rule. Below is an example of using <code>@forward</code> to load stylesheets inside an index file.</p>
<div class="filename-title"><span>Filename</span>: <em>./mixins/_index.scss</em></div>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@forward</span> <span class="token string">"./mixins/sr-only"</span><span class="token punctuation">;</span><br /><span class="token keyword">@forward</span> <span class="token string">"./mixins/invert"</span><span class="token punctuation">;</span><br /><span class="token keyword">@forward</span> <span class="token string">"./mixins/square"</span><span class="token punctuation">;</span></code></pre>
<p>Now instead of writing three separate <code>@import</code> or <code>@use</code> rules to load the URLs of the mixins we need. Simply load the URL representing the directory of partial files with a defined index file. In our case, the <code>mixins</code> directory can be loaded to make all of the forwarded stylesheets available with a single <code>@use</code> rule. Not only is this usage super clean and maintainable but saves quite a bit of time when many partial files need to be loaded.</p>
<p>Note: The <code>@use</code> at-rules must be placed at the top of the file, before any other content.</p>
<div class="filename-title"><span>Filename</span>: <em>style.scss</em></div>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@use</span> <span class="token string">"./mixins/"</span><span class="token punctuation">;</span><br /><br /><span class="token selector">.hidden </span><span class="token punctuation">{</span><br /> <span class="token keyword">@include</span> mixins.<span class="token function">sr-only</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.demo </span><span class="token punctuation">{</span><br /> <span class="token keyword">@include</span> mixins.<span class="token function">invert</span><span class="token punctuation">(</span>0.30<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">@include</span> mixins.<span class="token function">invert</span><span class="token punctuation">(</span>20px<span class="token punctuation">,</span> 20px<span class="token punctuation">,</span> #f06<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Voila! One thing to note is that the "generic" <code>@use</code> at-rule usage will define a default namespace for the loaded content as the final component of the URL. So in our case, the namespace for this <code>@use</code> rule will be <code>mixins</code>. And accessing the loaded members within the directory will simply require you to reference the namespace and use dot notation like <code>mixins.foo()</code>.</p>
<p>Sometimes you don't want to have a namespace attached to the loaded folder. Sass gives us the flexibility to define a custom namespace with <code>@use "<URL>" as <namespace>;</code></p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@use</span> <span class="token string">"./mixins/"</span> <span class="token module-modifier keyword">as</span> m<span class="token punctuation">;</span><br /><br /><span class="token selector">.hidden </span><span class="token punctuation">{</span><br /> <span class="token keyword">@include</span> m.<span class="token function">sr-only</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.demo </span><span class="token punctuation">{</span><br /> <span class="token keyword">@include</span> m.<span class="token function">invert</span><span class="token punctuation">(</span>0.30<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">@include</span> m.<span class="token function">invert</span><span class="token punctuation">(</span>20px<span class="token punctuation">,</span> 20px<span class="token punctuation">,</span> #f06<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Or completely disregard a namespace by not defining one with <code>@use "<URL>" as *;</code>. This makes it so you can reference loaded members without a namespace and without using dot notation, just as you would if they were defined in the same file.</p>
<p>Only do this if you know there won't be any naming conflicts with other loaded members.</p>
<pre class="language-scss"><code class="language-scss"><span class="token keyword">@use</span> <span class="token string">"./mixins/"</span> <span class="token module-modifier keyword">as</span> *<span class="token punctuation">;</span><br /><br /><span class="token selector">.hidden </span><span class="token punctuation">{</span><br /> <span class="token keyword">@include</span> <span class="token function">sr-only</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.demo </span><span class="token punctuation">{</span><br /> <span class="token keyword">@include</span> <span class="token function">invert</span><span class="token punctuation">(</span>0.30<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">@include</span> <span class="token function">invert</span><span class="token punctuation">(</span>20px<span class="token punctuation">,</span> 20px<span class="token punctuation">,</span> #f06<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>There is more to discuss but this should cover the basics of <code>@use</code> at-rules. I'm hoping the information and examples in this article can provide Sass users a quick walkthrough of <code>@use</code> and index files. While also helping people in converting their projects from <code>@import</code> to <code>@use</code> since Sass will be phasing out <code>@import</code> over the next few years.</p>
Build a minimal HTTP server with Node2021-08-14T00:00:00Zhttps://tannerdolby.com/writing/build-a-minimal-http-server-with-node/<p>To create a Node.js application, you need a web server, a request, a router, and request handlers. Frameworks like Express.js speed up development by providing a robust set of features to build web applications and APIs.</p>
<p>Developing applications with Node.js doesn't have to be intimidating. Sure, large apps will have much greater complexity than a simple API but the underlying logic of how they work won't change much. You need a web server to allow web clients to send requests, a view or page to display the servers response, a router to route specific requests, and lastly request handlers to handle requests sent to the server which have been routed by the router.</p>
<h2 class="post-heading">What is a Node.js app?</h2>
<p>The first thing you need to implement in a Node.js application, is a server. The web server will allow users to make requests. The HTTP protocol is used for handling transmission of data on the Web (ie client/server model). This means that information exchange between the client and server is half-duplex. Since the HTTP protocol is half-duplex, it can only allow one way information exchange. For example, if a web client makes a request to the server, the server cannot send back a response until that request is received and "completed". Below is a small example of how information is sent using the HTTP protocol.</p>
<pre class="language-text"><code class="language-text"> (Request)<br />|--------| ------------> |--------|<br />| Client | | Server |<br />|--------| <------------ |--------|<br /> (Response) </code></pre>
<h2 class="post-heading h2-5">Setup a basic server using the HTTP module</h2>
<p>Creating a basic HTTP server only takes a few steps. Require the HTTP module and then call the <code>createServer</code> function on the HTTP module to create the server. This function returns a <code>Server</code> object which has a method called <code>listen</code> that allows us to specify the port which the server should listen to requests on.</p>
<p>The <code>createServer</code> function takes one argument, an anonymous or "named" function that handles requests and responses. This callback function allows us to utilize the asynchronous event driven model in Node by handling requests when they arrive and continue executing other code when waiting for a request in a non-blocking fashion.</p>
<p>Why use callbacks? Well, we don't want the web server to be started and then pause or stop executing in between requests. When multiple requests come, we also don't want the server to wait to execute the second request until the first is complete in a blocking way. The idea of the callback function helps us to avoid these synchronous and blocking scenarios and really utilize the async event driven paradigm in Node.</p>
<div class="filename-title"><span>Filename</span>: <em>server.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> http <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'http'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> port <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">PORT</span> <span class="token operator">||</span> <span class="token number">8000</span><span class="token punctuation">;</span><br /><br />http<span class="token punctuation">.</span><span class="token function">createServer</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token string">"Content-Type"</span><span class="token operator">:</span> <span class="token string">"text/plain"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token string">"Hello, world!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span>port<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">App is running on port </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>port<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The above code will create an HTTP server listening on port 8000 and define the response for any incoming requests. The <code>req</code> object has a property <code>url</code> that holds the request URL value, e.g. a request on <a href="http://localhost:8000/">http://localhost:8000</a> would have a <code>req.url = "/"</code>. The <code>writeHead</code> method on the response object defines an HTTP status code and headers for a response.</p>
<p>Next, we send some HTML in the response and finally end the response with <code>res.end()</code>. Since we haven't defined a router, all requests on <code>http://localhost:8000/*</code> will be handled the same way and send the <code>text/plain</code> response:</p>
<pre class="language-html"><code class="language-html">Hello, world!</code></pre>
<p>You can verify the response is being received on the client by checking if the response data is on the webpage, or by going into Developer tools and looking at the "Network" tab to make sure the "Preview" or "Response" tab holds the expected response payload.</p>
<img class="demo-img" src="https://tannerdolby.com/images/dev-tools-response-prev.png" alt="Network tab of Developer tools" />
<p>Having a look at the "Headers" tab, we can see an HTTP <code>GET</code> request is being made to <code>http://localhost:8000</code>. The request was sent and processed successfully by the server and returned an HTTP response status code <code>200</code> (OK). The <code>Content-Type</code> header we specified for the response with <code>res.writeHead()</code> is correctly shown as <code>text/plain</code>. If you can't see the string "Hello, world!" on your webpage, then navigate to the Network tab or look for an error being thrown.</p>
<img class="demo-img" src="https://tannerdolby.com/images/dev-tools-response-two.png" alt="Response subtab of Network in Dev tools" />
<h2 class="post-heading">Displaying the Response</h2>
<p>Instead of sending plain text to the root URL (<code>http://localhost:8000</code>) ie the <code>/</code> endpoint, let's send static HTML in the response. For testing and local development, its fine to create a template literal string containing the HTML you want to send. That can be accomplished like this:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> http <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"http"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> port <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">PORT</span> <span class="token operator">||</span> <span class="token number">8000</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> html <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string"><header><h1>Hello, World!</h1></header></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span><br /><br />http<span class="token punctuation">.</span><span class="token function">createServer</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token string">'Content-Type'</span><span class="token operator">:</span> <span class="token string">'text/html'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span>port<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">App running on port </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>port<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The expected response would be the HTML contained in the template literal <code>html</code>. Although this is a quick way to serve some HTML. The recommended way of serving static files is by reading the file contents and then sending that data in the response ie serving it. Using the <code>fs</code> file system module, we can quickly read the contents of a HTML file <code>index.html</code> and send it wherever. There are many ways to read a files contents. Node docs recommend the async <code>fs.readFile()</code> method, but a <code>ReadableStream</code> would also work. Below is an example of serving a static HTML file at the root URL of our basic HTTP server:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> http <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"http"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"fs"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> port <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">PORT</span> <span class="token operator">||</span> <span class="token number">8000</span><span class="token punctuation">;</span><br /><br />http<span class="token punctuation">.</span><span class="token function">createServer</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Request received for '</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>req<span class="token punctuation">.</span>url<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">'</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> fs<span class="token punctuation">.</span><span class="token function">readFile</span><span class="token punctuation">(</span>__dirname <span class="token operator">+</span> <span class="token string">"/index.html"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> data</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token string">'Content-Type'</span><span class="token operator">:</span> <span class="token string">'text/html'</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span>port<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Listening on port </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>port<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The above example will serve a file called <code>index.html</code> from the current directory. If you haven't used <code>__dirname</code> before, it is an environment variable that tells you the absolute path of the directory containing the currently executing file.</p>
<p>The docs use <code>res.end()</code> to send data in the response body, but using <code>res.send(data)</code> or <code>res.write(data)</code> followed by <code>res.end()</code> would accomplish the same goal. The <code>.send()</code> method will send the HTTP response and looks like <code>.send([body])</code>, where the <code>body</code> parameter can be a Buffer object, a String, an object, or an Array. The <code>.end()</code> method will end the response process.</p>
<p><em>Note: Read more about the difference between <code>res.end()</code> and <code>res.send()</code> on <a href="https://stackoverflow.com/questions/29555290/what-is-the-difference-between-res-end-and-res-send">StackOverflow</a></em></p>
<div class="filename-title"><span>Filename</span>: <em>index.html</em></div>
<pre class="language-html"><code class="language-html"><span class="token doctype"><span class="token punctuation"><!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>width=device-width, initial-scale=1.0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">http-equiv</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>X-UA-Compatible<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>ie=edge<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>title</span><span class="token punctuation">></span></span>Home page<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>title</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>Write a message!<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span> <span class="token attr-name">action</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/message<span class="token punctuation">"</span></span> <span class="token attr-name">method</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>POST<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span> <span class="token property">flex-direction</span><span class="token punctuation">:</span> column<span class="token punctuation">;</span> <span class="token property">max-width</span><span class="token punctuation">:</span> 30ch<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Name<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>name<span class="token punctuation">"</span></span> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Enter name...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>br</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>message<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Message<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>textarea</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>message<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>message<span class="token punctuation">"</span></span> <span class="token attr-name">rows</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>40<span class="token punctuation">"</span></span> <span class="token attr-name">cols</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">resize</span><span class="token punctuation">:</span> vertical<span class="token punctuation">;</span> <span class="token property">height</span><span class="token punctuation">:</span> 8rem<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Enter message...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>textarea</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>br</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>submit<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Submit<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span></code></pre>
<p>When you make a request to the <code>/</code> route on the HTTP server we have created, you will be served the HTML page above as the response. Since we haven't setup any routing, every route requested on the server will be returning the same response. That means if I make a request to the <code>/blog</code> route, the response will be the same since there isn't a router in place to route requests to a specific handler.</p>
<img src="https://tannerdolby.com/images/node-demo-mkp.png" alt="Demo image of a HTML page served by Node" class="demo-img" />
<h2 class="post-heading">Create Request Handlers</h2>
<p>All of this articles code could be written in a single JavaScript file but to keep things organized, reusable and readable. We will be separating the functionality into modules and requiring them in the entrypoint to our application <code>app.js</code>. There will be two API endpoints in this article:</p>
<ul>
<li>The home page: <code>/</code></li>
<li>The message submitted by form: <code>/message</code></li>
</ul>
<p>To start writing the request handlers, create a file called <code>handlers.js</code> in your root directory. We will define two functions, <code>home</code> and <code>message</code> to handle the request for each respective route and send back a response. The home page serves a static file <code>index.html</code> and the <code>/message</code> page will display JSON with the form submission contents. Also, define a route handler object <code>handlerObj</code> with properties which match the available routes. Each route is a property in the object and will store its corresponding request handler function. Lastly, make the file a module by using <code>module.exports</code> to export the object and handler functions.</p>
<div class="filename-title"><span>Filename</span>: <em>handlers.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> handlerObj <span class="token operator">=</span> <span class="token punctuation">{</span><br /> <span class="token string">"/"</span><span class="token operator">:</span> home<span class="token punctuation">,</span><br /> <span class="token string">"/message"</span><span class="token operator">:</span> message<br /><span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">function</span> <span class="token function">home</span><span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Executing 'home' handler"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> fs<span class="token punctuation">.</span><span class="token function">readFile</span><span class="token punctuation">(</span>__dirname <span class="token operator">+</span> <span class="token string">"/index.html"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> data</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token string">'Content-Type'</span><span class="token operator">:</span> <span class="token string">'text/html'</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /><span class="token punctuation">}</span><br /><br /><span class="token keyword">function</span> <span class="token function">message</span><span class="token punctuation">(</span><span class="token parameter">res<span class="token punctuation">,</span> payload</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Executing 'message' handler"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">let</span> query <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">URLSearchParams</span><span class="token punctuation">(</span>payload<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">let</span> data <span class="token operator">=</span> <span class="token punctuation">{</span><br /> name<span class="token operator">:</span> query<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"name"</span><span class="token punctuation">)</span><span class="token punctuation">,</span><br /> message<span class="token operator">:</span> query<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"message"</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token string">'Content-Type'</span><span class="token operator">:</span> <span class="token string">'application/json'</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span><br /><span class="token punctuation">}</span><br /><br />module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span><br /> handlerObj<span class="token punctuation">,</span><br /> home<span class="token punctuation">,</span><br /> message<br /><span class="token punctuation">}</span></code></pre>
<p>The <code>home</code> function is the same implementation for reading a files contents and serving it as shown in <a href="https://tannerdolby.com/writing/build-a-minimal-http-server-with-node/#displaying-the-response">displaying the response</a>. The <code>message</code> function represents an endpoint that receives a <code>POST</code> request from the home pages form submission and displays the form submission on <code>/message</code>. The form elements <code>action</code> attribute equals <code>/message</code> which means the form is submitted, the page is redirected to <code>http://localhost:8000/message</code>.</p>
<p>When the form is submitted, the query string representing the form data is sent to the server as the post body. This is what's stored inside <code>payload</code>, the second argument to the <code>message</code> function. There are many ways to parse a query string, you could use the npm package <a href="https://www.npmjs.com/package/querystring">querystring</a> or something already available to us for working with a query string of a URL like the <a href="https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams">URLSearchParams</a> interface.</p>
<p>I chose to use the Web API <code>URLSearchParams</code> to keep things in-house. Using the constuctor <code>new URLSearchParams()</code>, we create a new instance of the interface and pass in the query string received by the server when our "Write a message" form is submitted. Now the <code>URLSearchParams</code> interface is available so we can use <a href="https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/get"><code>URLSearchParams.get()</code></a> to grab the values from the query string. Lastly, send an object with the <code>name</code> and <code>message</code> in response.</p>
<h2 class="post-heading">How does the Router work?</h2>
<p>Up until now, the Node application is listening for requests on port 8000 and serving a static HTML file as the response to all requests. Since we have a functional server that is processing requests and returning a response. It is time to add some routing.</p>
<p>The routers main job is to 'route' requests to a specific handler which then will send a response. To better understand what exactly a router will do, have a look at the following makeshift router example:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> http <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"http"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> port <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">PORT</span> <span class="token operator">||</span> <span class="token number">8000</span><span class="token punctuation">;</span><br /><br />http<span class="token punctuation">.</span><span class="token function">createServer</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>req<span class="token punctuation">.</span>url <span class="token operator">==</span> <span class="token string">'/blog'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token string">'Content-Type'</span><span class="token operator">:</span> <span class="token string">'text/html'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token string">"<h1>My Blog</h1>"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span><br /> res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token string">'Content-Type'</span><span class="token operator">:</span> <span class="token string">'text/plain'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token string">"Hello, world!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span>port<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Listening on port </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>port<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>If a request is made to the <code>/blog</code> route, then we will return an HTML response with a heading element. Otherwise, for any other route on the server that isn't <code>/blog</code>, we will send the <code>Hello, world!</code> plain text response. This is a really basic example of what exactly the router will be doing. It 'routes' requests to a specific handler so the API endpoints like <code>/blog</code> or <code>/messages</code> return the appropriate response.</p>
<h3 class="post-heading">Setup a Router</h3>
<p>To setup a router, first create a file named <code>router.js</code>. For this article, imagine that all files are at the root directory of the project. So far, we have the <code>server.js</code> file which holds our HTTP server code and the newly created router file. The router will be a function named <code>route</code> that we will export and use in our server code.</p>
<div class="filename-title"><span>Filename</span>: <em>router.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">failed</span><span class="token punctuation">(</span><span class="token parameter">path<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> res<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> res<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">No handler found for '</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>path<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">'</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token keyword">function</span> <span class="token function">route</span><span class="token punctuation">(</span><span class="token parameter">path<span class="token punctuation">,</span> res<span class="token punctuation">,</span> handlerObj<span class="token punctuation">,</span> payload</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Routing request for '</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>path<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">'</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">let</span> routeFound <span class="token operator">=</span> <span class="token keyword">typeof</span> handlerObj<span class="token punctuation">[</span>path<span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token string">'function'</span> <span class="token operator">&&</span> handlerObj<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">return</span> routeFound <span class="token operator">?</span> handlerObj<span class="token punctuation">[</span>path<span class="token punctuation">]</span><span class="token punctuation">(</span>res<span class="token punctuation">,</span> payload<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">failed</span><span class="token punctuation">(</span>path<span class="token punctuation">,</span> res<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br />module<span class="token punctuation">.</span>exports <span class="token operator">=</span> route<span class="token punctuation">;</span></code></pre>
<p>The <code>route</code> function simply checks to see if the given <code>path</code> is a property of the <code>handlerObj</code> object and if the type of that property is indeed a function. Also performing a check to see if the <code>handlerObj</code> has a property with the given route in <code>path</code>. If <code>routeFound</code> is true then execute the request handler function for that given path, otherwise send an error message with a 404 status.</p>
<h2 class="post-heading">Updating the Server code</h2>
<p>Let's refactor the <code>server.js</code> code a bit so we can export a <code>startServer</code> function to be used in <code>app.js</code>. In the process, placing all of the current <code>http.createServer</code> code into a start server function and giving it two arguments. One for the router and another for the handler object which will come from our entrypoint. The first argument to <code>.createServer()</code> is a callback function so we will break that out into its own named function for the heck of it.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> http <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"http"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> port <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">PORT</span> <span class="token operator">||</span> <span class="token number">8000</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">function</span> <span class="token function">startServer</span><span class="token punctuation">(</span><span class="token parameter">route<span class="token punctuation">,</span> handlerObj</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">function</span> <span class="token function">handleReq</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> path <span class="token operator">=</span> req<span class="token punctuation">.</span>url<span class="token punctuation">;</span><br /> <span class="token keyword">let</span> payload <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">;</span><br /><br /> req<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"data"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">chunk</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> payload <span class="token operator">+=</span> chunk<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> req<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"end"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token function">route</span><span class="token punctuation">(</span>path<span class="token punctuation">,</span> res<span class="token punctuation">,</span> handlerObj<span class="token punctuation">,</span> payload<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> http<span class="token punctuation">.</span><span class="token function">createServer</span><span class="token punctuation">(</span>handleReq<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span>port<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">App running on port </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>port<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br />module<span class="token punctuation">.</span>exports <span class="token operator">=</span> startServer<span class="token punctuation">;</span></code></pre>
<p>Not a whole lot changes in the server code, except for the addition of a <code>startServer</code> function and a named function <code>handleReq</code>. Aside from the new functions and organization, we begin listening for <code>data</code> events on the <code>req</code> object and assign the value of that <code>POST</code> data to a variable <code>payload</code> which is passed to the router.</p>
<h2 class="post-heading">Setup an Entrypoint</h2>
<p>The entrypoint for the application, ie where the HTTP server is started will be <code>app.js</code>. The filename isn't important, but understanding this is the script that starts the server is. Up until this point we would run our node app with <code>node server.js</code> but with the entrypoint becoming <code>app.js</code>, the command for starting up the server would be <code>node app.js</code>.</p>
<p>It's time to require all of the modules we have created so far:</p>
<div class="filename-title"><span>Filename</span>: <em>app.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> startServer <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./server"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./router"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> <span class="token punctuation">{</span> handlerObj <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./handlers"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token function">startServer</span><span class="token punctuation">(</span>router<span class="token punctuation">,</span> handlerObj<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This is one of the reasons modules are so great. We can abstract away all of the nitty gritty implementation of our server into separate modules. This keeps things organized and reusable, instead of putting all of the code into a single file which would quickly become unmaintainable.</p>
<p>When we run <code>node app.js</code> the <code>startServer</code> function will execute and our HTTP server will begin listening for requests on the specified port.</p>
<pre class="language-text"><code class="language-text">Listening on port 8000<br />Request received for '/'<br />Routing request for '/'<br />Executing 'home' handler</code></pre>
<img src="https://tannerdolby.com/images/node-demo-ffr.png" alt="Demo image of homepage with form" class="demo-img" />
<p>After hitting the submit button, we are redirected to the <code>/message</code> route and the data from the form submission is sent to the server in a <code>POST</code> request. Have a look at the Network tab in Developer Tools to verify the response.</p>
<pre class="language-text"><code class="language-text">Request received for '/message'<br />Routing request for '/message'<br />Executing 'message' handler</code></pre>
<img src="https://tannerdolby.com/images/node-demo-ffzz.png" alt="Demo image of data posted to server" class="demo-img" />
<p>If you read this far, you should have a solid understanding of setting up a basic HTTP server with Node.js. Now go forth and build cool stuff with Node! You can view the <a href="https://github.com/tannerdolby/basic-node-server">source code</a> for this demo over on GitHub. Oh ya, don't forget to go give <a href="https://expressjs.com/">Express.js</a> a try!</p>
Should I define a type as 'any' in TypeScript?2021-08-12T00:00:00Zhttps://tannerdolby.com/writing/writing-safe-code-with-typescript/<p>The 'any' type isn't something I use very often in my own development. But I have seen it occasionally used out in the wild. A good rule is, if your unsure of a data type for a variable, its best to let TypeScript infer the variables type for you through <a href="https://www.typescriptlang.org/docs/handbook/type-inference.html">type inference</a> rather than using type <code>any</code>. Only resort to using <code>any</code> if you absolutely have to.</p>
<p>When you can, try using a type annotation to explicitly tell the compiler what data type to expect. But when your not sure what the data type will be ahead of time, this is where type inference is quite nice.</p>
<blockquote>
<p>What can I replace 'any' with while declaring an object type in Typescript? <a href="https://stackoverflow.com/questions/66594670/what-can-i-replace-any-with-while-declaring-an-object-type-in-typescript/66595023#66595023">StackOverflow</a></p>
</blockquote>
<h2 class="post-heading">When in doubt, don't reach for any</h2>
<p>Type inference is a great feature of TypeScript, but it's also perfectly fine to explictly define types if you know they will be one of the primitive types:</p>
<ul>
<li>string</li>
<li>number</li>
<li>boolean</li>
<li>symbol</li>
</ul>
<p>If you can't use one of the primitive types, then it's time to define some <a href="https://www.typescriptlang.org/docs/handbook/2/objects.html">object types</a> with an interface, a <code>type</code> or <a href="https://www.typescriptlang.org/docs/handbook/2/generics.html">generics</a> to better let TypeScript understand the "allowed" values for a certain variable, function etc.</p>
<h2 class="post-heading">Do's and Dont's</h2>
<p>Hopefully it's clear that using the <code>any</code> type in TypeScript sort of defeats the purpose of writing TS code in the first place. When we use <code>any</code>, the TypeScript compiler allows for the type to literally be any data type, which is not "safe" and can lead to unexpected values if you aren't careful. The idea of TypeScript is to provide "strictly-typed" JS code so that its durable and safer than plain ole JS which is "loosely-typed".</p>
<p>A few examples of writing type annotations with the primitive types:</p>
<div class="filename-title"><span>Filename</span>: <em>types.ts</em></div>
<pre class="language-ts"><code class="language-ts"><span class="token keyword">const</span> s<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token operator">=</span> <span class="token string">"Yo"</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> n<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> dec<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">=</span> <span class="token number">2.32</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> choice<span class="token operator">:</span> <span class="token builtin">boolean</span> <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> strArr<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"A"</span><span class="token punctuation">,</span> <span class="token string">"B"</span><span class="token punctuation">,</span> <span class="token string">"C"</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> numArr<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> boolArr<span class="token operator">:</span> <span class="token builtin">boolean</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// You might also see strArr and numArr written this way</span><br /><span class="token comment">// using the non-primitive Object Types</span><br /><span class="token keyword">const</span> strArr2<span class="token operator">:</span> <span class="token builtin">Array</span><span class="token operator"><</span><span class="token builtin">string</span><span class="token operator">></span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"A"</span><span class="token punctuation">,</span> <span class="token string">"B"</span><span class="token punctuation">,</span> <span class="token string">"C"</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> numArr2<span class="token operator">:</span> <span class="token builtin">Array</span><span class="token operator"><</span><span class="token builtin">number</span><span class="token operator">></span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> boolArr2<span class="token operator">:</span> <span class="token builtin">Array</span><span class="token operator"><</span><span class="token builtin">boolean</span><span class="token operator">></span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">]</span><span class="token punctuation">;</span></code></pre>
<p>You might also need to write a type annotation for a 2D array, that could be done like this:</p>
<pre class="language-ts"><code class="language-ts"><span class="token keyword">const</span> nums<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> words <span class="token operator">=</span> <span class="token builtin">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"a"</span><span class="token punctuation">,</span> <span class="token string">"b"</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">"c"</span><span class="token punctuation">,</span> <span class="token string">"d"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> bools <span class="token operator">=</span> <span class="token builtin">boolean</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">;</span></code></pre>
<p>Now that we know how to use primitive types and explicitly let TypeScript know the type of a variable through type annotations. Let's look at a bad example which uses <code>any</code> and how we can fix it by defining object types using an interface:</p>
<pre class="language-ts"><code class="language-ts"><span class="token comment">// BAD</span><br /><span class="token keyword">const</span> obj<span class="token operator">:</span> <span class="token builtin">any</span> <span class="token operator">=</span> <span class="token punctuation">{</span><br /> colors<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"#f06"</span><span class="token punctuation">,</span> <span class="token string">"#000"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> lengths<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> name<span class="token operator">:</span> <span class="token string">"Foobar"</span><br /><span class="token punctuation">}</span></code></pre>
<p>Using <code>any</code> to define the object type for this <code>obj</code> variable is just downright bad practice (unless you need it to not have any type checks, which may sometimes happen). If were going to loosely type an object like this, there really isn't a point in writing it in TypeScript to begin with. Now lets fix this by getting rid of the <code>any</code> type and define a more appropriate object type using an interface. This will make our code much safer as TypeScript knows what data types each value is "allowed" and the compile-time checks will be much stricter.</p>
<div class="filename-title"><span>Filename</span>: <em>types.ts</em></div>
<pre class="language-ts"><code class="language-ts"><span class="token keyword">interface</span> <span class="token class-name">MyObj</span> <span class="token punctuation">{</span><br /> colors<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> lengths<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">// or using a type annotation</span><br /><span class="token keyword">type</span> <span class="token class-name">MyObject</span> <span class="token operator">=</span> <span class="token punctuation">{</span><br /> colors<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> lengths<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">// safe</span><br /><span class="token keyword">const</span> obj<span class="token operator">:</span> MyObj <span class="token operator">=</span> <span class="token punctuation">{</span><br /> colors<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"#f06"</span><span class="token punctuation">,</span> <span class="token string">"#000"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> lengths<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> name<span class="token operator">:</span> <span class="token string">"Foobar"</span><br /><span class="token punctuation">}</span></code></pre>
<pre class="language-ts"><code class="language-ts"><span class="token comment">// also safe</span><br /><span class="token keyword">const</span> myObj<span class="token operator">:</span> <span class="token punctuation">{</span><br /> colors<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> lengths<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token punctuation">{</span><br /> colors<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"#f06"</span><span class="token punctuation">,</span> <span class="token string">"#000"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> lengths<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> name<span class="token operator">:</span> <span class="token string">"Foobar"</span><br /><span class="token punctuation">}</span></code></pre>
<p>If I wanted to write a type annotation for an array of <code>MyObj</code> types. It could be done like this:</p>
<pre class="language-ts"><code class="language-ts"><span class="token keyword">const</span> objArr<span class="token operator">:</span> MyObj<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><br /> <span class="token punctuation">{</span><br /> colors<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"#f06"</span><span class="token punctuation">,</span> <span class="token string">"#fff"</span><span class="token punctuation">,</span> <span class="token string">"#000"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> lengths<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> name<span class="token operator">:</span> <span class="token string">"Foobar"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">{</span><br /> colors<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"#f06"</span><span class="token punctuation">,</span> <span class="token string">"#000"</span><span class="token punctuation">,</span> <span class="token string">"#333"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> lengths<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token number">6</span><span class="token punctuation">]</span><span class="token punctuation">,</span><br /> name<span class="token operator">:</span> <span class="token string">"Foobar"</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">]</span></code></pre>
<h2 class="post-heading">Closing thoughts</h2>
<p>I usually tend to define an interface or use a <code>type</code> annotation anytime there is a variable or function that could benefit from explicit type definitions. Another option outside of interfaces, is using generics. If you programmed in Java, you might be familiar with generics. They are super powerful and really help us to write safe code. If you want to read more about using Generic Types, head over to the generics <a href="https://www.typescriptlang.org/docs/handbook/2/generics.html">documentation</a>.</p>
<p>If anything were to stick with you from this article, I hope that it will be: Please try not to use type <code>any</code> in TypeScript unless its absolutely required (which doesn't happen that often). I like to say, when in doubt, don't reach for <code>any</code> but instead let TypeScript infer the type for you through type inference or if you require object types, define an interface or type annotation so TypeScript better understands what types to expect when it compiles the TS code to plain JavaScript.</p>
Generate Page Content From a Global Data File Using Eleventy2021-07-29T00:00:00Zhttps://tannerdolby.com/writing/generate-page-content-from-a-global-data-file-using-eleventy/<p>There are many great features to choose from when building websites with Eleventy. One feature in particular that I find very useful is the ability to iterate over a global data file and generate page content using a templating language of your choice.</p>
<p>You can create <a href="https://www.11ty.dev/docs/data-global/">global data files</a> in 11ty by placing them inside the <code>_data</code> directory. Global data files can be stored as JSON <code>.json</code> or as data from <code>module.exports</code> in a <code>.js</code> custom data file. The data files can then be accessed by any template in the project structure. If you need to do any complex computation outside of your <code>.eleventy.js</code> logic, the possibilites with global data files are endless.</p>
<h2 class="post-heading">Use Cases</h2>
<p>I think its safe to say when building a website, you might be faced with creating a large grid of repeating card elements (with different data) or a long listing column of values. This could be menu items on a restaurant menu, profiles on a main page, the list goes on and on. CSS grid provides a way to style nice looking grids, but the underlying HTML still needs to be added one way or another.</p>
<p>Why sit there and type out 100+ different <code>.card</code> containers when you can store each card elements data inside a global data file. To then iterate over that global card data and generate multiple elements from only one card containers markup. This could be data fetched from an API and stored in a <code>.js</code> file or by simply typing in the data needed by hand into a <code>_data/*.json</code> file.</p>
<h2 id="cascade-note" class="post-heading">The Data Cascade</h2>
<p>Before going any further, I should mention that when building webpages using the Static Site Generator (SSG) Eleventy. Data is being merged from multiple sources before making its way to the template file that gets rendered in the site output directory <code>_site</code>. This is what Eleventy calls the <a href="https://www.11ty.dev/docs/data-cascade/">Data Cascade</a> and its really neat.</p>
<h2 id="data-sources" class="post-heading">Data Sources</h2>
<p>One of my favorite things about Eleventy is the fact that there isn't a prescribed way of merging data within the cascade. There is an <a href="https://www.11ty.dev/docs/data-cascade/#sources-of-data">order of priority</a> for sources of data in the cascade but that data can defined however you would like.</p>
<p>Here are a few options for data sources:</p>
<ul>
<li><a href="https://www.11ty.dev/docs/data-global/">Global data files</a></li>
<li><a href="https://www.11ty.dev/docs/data-computed/">Computed Data</a></li>
<li><a href="https://www.11ty.dev/docs/data-frontmatter/">Front Matter Data</a></li>
<li><a href="https://www.11ty.dev/docs/data-template-dir/">Template and Directory</a></li>
</ul>
<h2 id="create-global-data" class="post-heading">Creating a Global Data File</h2>
<p>The global data folder in Eleventy is decided by the <a href="https://www.11ty.dev/docs/config/#directory-for-global-data-files">dir.data</a> configuration. For this article I will only focus on <code>.json</code> global data but you can read more about <a href="https://www.11ty.dev/docs/data-global/">other global data</a> available to templates if you'd like. The example below creates an array of objects inside the <code>cards.json</code> global data file. Each employee object in the array has some filler data to mimic a large page of profile cards or something of that nature.</p>
<p>Let's say company XYZ has 500+ employees and you don't want to sequentially write out the HTML for each employee profile card. If there was an internal data source or API endpoint that contained the data, you could populate a global data file <code>cards.js</code> with some JavaScript code to fetch data and export it to be used just as you would <code>.json</code> data file. Otherwise, manually inserting data to <code>cards.json</code> without performing any data fetching or computing will work just as well.</p>
<p>Next, we need a place where all this employee data can be utilized and rendered. You can create a layout <code>profiles.njk</code> inside a new directory called <code>_includes/layouts/</code> and begin iterating over the array of card objects in cards.json. You could also just create a <code>profiles.html</code> file to iterate over the global data and not use any <code>.md</code> files, as the templates are being transformed to HTML at build time.</p>
<h3 class="post-heading">JavaScript files</h3>
<p>When using <code>.js</code> global data files, you have the option to export an object or a function using <code>module.exports</code>. If you have worked with modules before or have exposed the public API of a Node package on npm, your probably familiar with exporting. Whatever is exported from a <code>.js</code> global data file is globally accessible anywhere in your project just as it would with JSON. Here is a short example:</p>
<div class="filename-title"><span>Filename</span>: <em>card.js</em></div>
<pre class="language-js"><code class="language-js">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span><br /> name<span class="token operator">:</span> <span class="token string">"11ty Fan Club"</span><span class="token punctuation">,</span><br /> labels<span class="token operator">:</span> <span class="token punctuation">[</span><br /> <span class="token string">"11ty"</span><span class="token punctuation">,</span><br /> <span class="token string">"is"</span><span class="token punctuation">,</span><br /> <span class="token string">"cool"</span><br /> <span class="token punctuation">]</span><span class="token punctuation">,</span><br /> members<span class="token operator">:</span> <span class="token number">11</span><br /><span class="token punctuation">}</span></code></pre>
<p>The data exported from <code>card.js</code> would then have the following template usage. Using the global data filename and accessing properties within the exported object using dot notation:</p>
<div class="filename-title"><span>Filename</span>: <em>index.njk</em></div>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>{{ card.name }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Current members: {{ card.members }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span><br /> {% for label in card.labels %}<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>{{ label }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> {% endfor %}<br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span></code></pre>
<p>If you wanted more freedom to pull in data from another source, or compute it. Then using a custom <code>.js</code> global data file will be what you want. Any data that is exported using <code>module.exports</code> will be available in the same fashion as data from a <code>.json</code> global data file. Below is a basic example of creating a custom global data file for use in templates.</p>
<div class="filename-title"><span>Filename</span>: <em>customData.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> fetch <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"node-fetch"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Fetch some data from the GitHub API</span><br /><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getData</span><span class="token punctuation">(</span><span class="token parameter">url</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">try</span> <span class="token punctuation">{</span><br /> repo <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">data</span> <span class="token operator">=></span> data<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> <span class="token punctuation">{</span><br /> <span class="token operator">...</span>repo<span class="token punctuation">,</span><br /> title<span class="token operator">:</span> repo<span class="token punctuation">.</span>name<span class="token punctuation">,</span><br /> desc<span class="token operator">:</span> repo<span class="token punctuation">.</span>description<span class="token punctuation">,</span><br /> stars<span class="token operator">:</span> repo<span class="token punctuation">.</span>stargazers_count<span class="token punctuation">,</span><br /> issues<span class="token operator">:</span> repo<span class="token punctuation">.</span>open_issues<br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><br /><br /><span class="token keyword">function</span> <span class="token function">random</span><span class="token punctuation">(</span><span class="token parameter">min<span class="token punctuation">,</span> max</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> min <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">ceil</span><span class="token punctuation">(</span>min<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> max <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>max<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token punctuation">(</span>max <span class="token operator">-</span> min<span class="token punctuation">)</span> <span class="token operator">+</span> min<span class="token punctuation">)</span><br /><span class="token punctuation">}</span></code></pre>
<p>Then at the end of the file, you can either export an object like <code>module.exports = {}</code> or export a function and return the object or data you wish to use globally.</p>
<pre class="language-js"><code class="language-js">module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">try</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> apiData <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">getData</span><span class="token punctuation">(</span><span class="token string">"https://api.github.com/repos/tannerdolby/eleventy-photo-gallery"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> <span class="token punctuation">{</span><br /> title<span class="token operator">:</span> <span class="token string">"My custom blog post"</span><span class="token punctuation">,</span><br /> metadata<span class="token operator">:</span> <span class="token punctuation">{</span><br /> date<span class="token operator">:</span> <span class="token string">"2021-03-16"</span><span class="token punctuation">,</span><br /> tags<span class="token operator">:</span> <span class="token punctuation">[</span><br /> <span class="token string">"11ty"</span><span class="token punctuation">,</span><br /> <span class="token string">"JavaScript"</span><br /> <span class="token punctuation">]</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> trending<span class="token operator">:</span> <span class="token function">random</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">7</span> <span class="token operator">?</span> <span class="token boolean">true</span> <span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br /> repo<span class="token operator">:</span> apiData<br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<p>This is a contrived example, but the sky is the limit with global data files. They provide a blank "data" canvas for you to do whatever you want with your data, which is another reason why 11ty is really cool. You can use the custom global data universally in your project either in a template or markdown file just as you would with a <code>.json</code> data file. By using the global data filename like <code>{{ customData }}</code> and then accessing the object properties as necessary.</p>
<details>
<summary>Using Nunjucks in Markdown Files</summary>
<pre class="language-yml"><code class="language-yml"><span class="token punctuation">---</span><br /><span class="token key atrule">title</span><span class="token punctuation">:</span> Some title<br /><span class="token key atrule">date</span><span class="token punctuation">:</span> <span class="token datetime number">2021-07-08</span><br /><span class="token key atrule">templateEngineOverride</span><span class="token punctuation">:</span> njk<span class="token punctuation">,</span> md<br /><span class="token key atrule">items</span><span class="token punctuation">:</span><br /> <span class="token punctuation">-</span> <span class="token number">1</span><br /> <span class="token punctuation">-</span> <span class="token number">2</span><br /> <span class="token punctuation">-</span> <span class="token number">3</span><br /><span class="token punctuation">---</span><br /><br /><span class="token punctuation">{</span><span class="token punctuation">{</span> title <span class="token punctuation">}</span><span class="token punctuation">}</span><br /><br />Now using a shortcode in Markdown like this is fine<br /><br /><span class="token punctuation">{</span>% someShortCode "11ty is fast" %<span class="token punctuation">}</span><br /><br />or using an iteration statement<br /><br /><span class="token punctuation">{</span>% for item in items %<span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token punctuation">{</span> item <span class="token punctuation">}</span><span class="token punctuation">}</span><br /><span class="token punctuation">{</span>% endfor %<span class="token punctuation">}</span></code></pre>
<p>Anything you can do in a template like <code>.html</code>, <code>.njk</code>, <code>.liquid</code> files, can be done in Markdown once you add the <code>templateEngineOverride</code> field in frontmatter.</p>
<p>If you intend on using templating language syntax like liquid or nunjucks in a Markdown file, make sure to set <code>templateEngineOverride: njk, md</code> in front matter to allow nunjucks to be handled first then markdown.</p>
</details>
<h3 class="post-heading">JSON files</h3>
<p>If you wanted to only use JSON in your global data file, you could do something like:</p>
<div class="filename-title"><span>Filename</span>: <em>cards.json</em></div>
<pre class="language-json"><code class="language-json"><span class="token punctuation">[</span><br /> <span class="token punctuation">{</span><br /> <span class="token property">"title"</span><span class="token operator">:</span> <span class="token string">"Card One"</span><span class="token punctuation">,</span><br /> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"Larry"</span><span class="token punctuation">,</span><br /> <span class="token property">"id"</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span><br /> <span class="token property">"posititon"</span><span class="token operator">:</span> <span class="token string">"Systems"</span><span class="token punctuation">,</span><br /> <span class="token property">"scheduled"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token property">"monday"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span><br /> <span class="token property">"tuesday"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span><br /> <span class="token property">"wednesday"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span><br /> <span class="token property">"thursday"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span><br /> <span class="token property">"friday"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br /> <span class="token property">"saturday"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br /> <span class="token property">"sunday"</span><span class="token operator">:</span> <span class="token boolean">false</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token property">"interests"</span><span class="token operator">:</span> <span class="token punctuation">[</span><br /> <span class="token string">"Some rad stuff"</span><span class="token punctuation">,</span><br /> <span class="token string">"reading rad blog posts"</span><span class="token punctuation">,</span><br /> <span class="token string">"eleventy"</span><br /> <span class="token punctuation">]</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">]</span></code></pre>
<p>and using the data in a template would look like this:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>{{ customData.title }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>{{ customData.metadata.date }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span><br /> {% for tag in customData.metadata.tags %}<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>{{ tag }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> {% endfor %}<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>{{ customData.trending }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>github<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>GitHub Repostory: {{ customData.repo.name }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Stars: {{ customData.repo.stars }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Issues: {{ customData.repo.issues }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span></code></pre>
<h2 id="using-global-data" class="post-heading">Iterating Global Data</h2>
<p>Below is an example of the <code>for</code> loop syntax in Nunjucks.</p>
<pre class="language-html"><code class="language-html">{% for item in sequence %}<br /> {{ item }} <br />{% endfor %}</code></pre>
<p>Using an iteration statement like the <code>for</code> loop, you only have to write a small amount of template HTML for one profile container. Allowing the loop to generate the rest of the card containers markup from your global data. I'm using <a href="https://mozilla.github.io/nunjucks/">Nunjucks</a> as the templating language for examples in this article, but everything could be done in a <code>.liquid</code> template as well.</p>
<blockquote>
<p>Liquid is the default templating engine in Eleventy.</p>
</blockquote>
<p>To create a loop or conditional statement in <a href="https://mozilla.github.io/nunjucks/">Nunjucks</a> use <code>{% code %}</code>. If you simply want to access data from front matter or in global data, use <code>{{ variable }}</code>.</p>
<pre class="language-html"><code class="language-html">{% for card in cards %}<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>{{ card.title }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Hi, my name is {{ card.name }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br />{% endfor %}</code></pre>
<p>You can access global data files in a markdown file or within a template by using the filename without its file extension. When you have a global data file thats an object, you can access the content by using <code>{{ cards.title }}</code> without any <code>for</code> loop.</p>
<p>If you wanted to iterate over the array of card objects in <code>_data/cards.json</code> and generate HTML for a nice grid of employee cards. You can inject global data into a template file using <code>{{ item }}</code> and access the objects we have defined in global data.</p>
<div class="filename-title"><span>Filename</span>: <em>profiles.njk</em></div>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>main</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>card-grid<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />{% for card in cards %}<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>card<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>{{ card.title }} - #{{ card.id }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Hi, I'm {{ card.name }} and I work in {{ card.position }}.<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h3</span><span class="token punctuation">></span></span>Interests<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h3</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span><br /> {% for interest in card.interests %}<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span>{{ interest }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> {% endfor %}<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h3</span><span class="token punctuation">></span></span>Schedule<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h3</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>On call: {{ card.on-call }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br />{% endfor %}<br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>main</span><span class="token punctuation">></span></span></code></pre>
<h2 id="using-markdown" class="post-heading">Using Markdown</h2>
<p>Let's say you wanted to write an introduction paragraph in markdown underneath the main page title. To start, you would create a <code>.md</code> file and add some <a href="https://www.11ty.dev/docs/data-frontmatter/">front matter data</a> at the top of <code>cardBanner.md</code> inside the opening and closing document separators, <code>---</code>.</p>
<p>Front matter in 11ty uses <a href="https://yaml.org/spec/1.2/spec.html">YAML</a> syntax. The <code>permalink</code> is called a <a href="https://yaml.org/spec/1.2/spec.html#id2760844">quoted scalar</a> where the <code>title</code> and <code>layout</code> are scalars in the plain style. All the content outside of the document separators within a <code>.md</code> file are rendered as regular Markdown.</p>
<p>Including a <a href="https://www.11ty.dev/docs/permalinks/">permalink</a> in front matter data when using 11ty allows for URIs to leave out filename extensions. The page <code>cardBanner.md</code> will be written to the sites output as <code>/employees-page/index.html</code> and accessible from the <code>/employees-page/</code> URI.</p>
<div class="filename-title"><span>Filename</span>: <em>cardBanner.md</em></div>
<pre class="language-yaml"><code class="language-yaml"><span class="token punctuation">---</span><br /><span class="token key atrule">title</span><span class="token punctuation">:</span> XYZ Company Employee Profile Page<br /><span class="token key atrule">layout</span><span class="token punctuation">:</span> layouts/profiles.njk<br /><span class="token key atrule">permalink</span><span class="token punctuation">:</span> <span class="token string">"/employees-page/"</span><br /><span class="token punctuation">---</span><br /><br />Welcome to the employee home page for company XYZ.<br /><br /><span class="token key atrule">The employee cards contain the data fields</span><span class="token punctuation">:</span> <br /> <span class="token punctuation">-</span> name<br /> <span class="token punctuation">-</span> position <br /> <span class="token punctuation">-</span> interests<br /> <span class="token punctuation">-</span> weekly schedule<br /></code></pre>
<p>To include the markdown in <code>cardBanner.md</code> within the layout file <code>global-data-demo.njk</code>, we can reference it inside the template file <code>profiles.njk</code> using <code>{{ content }}</code> and the <code>safe</code> filter.</p>
<div class="filename-title"><span>Filename</span>: <em>profiles.njk</em></div>
<pre class="language-liquid"><code class="language-liquid"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>main</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span><span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> title <span class="token delimiter punctuation">}}</span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span><br /> <span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> content <span class="token operator">|</span> <span class="token function filter">safe</span> <span class="token delimiter punctuation">}}</span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>card-grid<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token liquid language-liquid"><span class="token delimiter punctuation">{%</span> <span class="token keyword">for</span> card <span class="token keyword">in</span> cards <span class="token delimiter punctuation">%}</span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>card<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span><span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> card<span class="token punctuation">.</span>title <span class="token delimiter punctuation">}}</span></span> - #<span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> card<span class="token punctuation">.</span>id <span class="token delimiter punctuation">}}</span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Hi, I'm <span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> card<span class="token punctuation">.</span>name <span class="token delimiter punctuation">}}</span></span> and I work in <span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> card<span class="token punctuation">.</span>position <span class="token delimiter punctuation">}}</span></span>.<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h3</span><span class="token punctuation">></span></span>Interests<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h3</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span><span class="token punctuation">></span></span><br /> <span class="token liquid language-liquid"><span class="token delimiter punctuation">{%</span> <span class="token keyword">for</span> interest <span class="token keyword">in</span> card<span class="token punctuation">.</span>interests <span class="token delimiter punctuation">%}</span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span><span class="token liquid language-liquid"><span class="token delimiter punctuation">{{</span> interest <span class="token delimiter punctuation">}}</span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br /> <span class="token liquid language-liquid"><span class="token delimiter punctuation">{%</span> <span class="token keyword">endfor</span> <span class="token delimiter punctuation">%}</span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h3</span><span class="token punctuation">></span></span>Schedule<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h3</span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- Extra: Index the card.scheduled days --></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token liquid language-liquid"><span class="token delimiter punctuation">{%</span> <span class="token keyword">endfor</span> <span class="token delimiter punctuation">%}</span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>main</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span></code></pre>
<p>Now that everything is setup, build with <code>eleventy</code> and then serve the app locally using <code>eleventy --serve</code>. The employee grid should look like this:</p>
<picture>
<source type="image/webp" srcSet="/images/profile-grid-demo-1024.webp 1024w, /images/profile-grid-demo-640.webp 640w, /images/profile-grid-demo-480.webp 480w, /images/profile-grid-demo-320.webp 320w" sizes="(max-width: 400px) 33.3vw, 100vw" />
<img srcSet="/images/profile-grid-demo-1024.jpeg 1024w, /images/profile-grid-demo-640.jpeg 640w, /images/profile-grid-demo-480.jpeg 480w, /images/profile-grid-demo-320.jpeg 320w" sizes="(max-width: 400px) 33.3vw, 100vw" src="https://tannerdolby.com/images/profile-grid-demo-1024.jpeg" alt="Employee Grid demo page" loading="lazy" class="demo-img" width="640" height="400" />
</picture>
<h2 id="conclusion" class="post-heading">Conclusion</h2>
<p>This is just one method of merging data in Eleventy and if you'd like to learn more, I suggest taking a look at some of the great features Eleventy has to offer such as <a href="https://www.11ty.dev/docs/collections/">Collections</a>, <a href="https://www.11ty.dev/docs/pagination/">Pagination</a> and <a href="https://www.11ty.dev/docs/pages-from-data/">Pages from Data</a>. The sky is the limit with global data files.</p>
<p>Here is a link to <a href="https://tannerdolby.com/writing/generate-page-content-from-a-global-data-file-using-eleventy/demo/">the live demo</a></p>
<details>
<summary>View the Source Code</summary>
<ul>
<li><a href="https://github.com/tannerdolby/tannerdolby.com/blob/master/src/_data/cards.json">cards.json</a> (Global data file)</li>
<li><a href="https://github.com/tannerdolby/tannerdolby.com/blob/master/src/_data/testData.js">customData.js</a> (Custom global data file)</li>
<li><a href="https://github.com/tannerdolby/tannerdolby.com/blob/master/src/iterate-global-data-demo.md">cardBanner.md</a> (Markdown)</li>
<li><a href="https://github.com/tannerdolby/tannerdolby.com/blob/master/src/_includes/layouts/global-data-demo.njk">profiles.njk</a> (Layout)</li>
</ul>
</details>Expressions and operator precedence in Python2021-07-25T00:00:00Zhttps://tannerdolby.com/writing/operator-precedence-python/<p>The order of operations in an expression is very important to understand. With more complex expressions, operator precedence isn't always straightforward and if not used correctly leads to unexpected values. Understanding which operators and groups take the highest precedence in an expression will help tremendously.</p>
<p>As someone with a background in mathematics, the acronym "PEMDAS" was spoken quite often. Not as much in my higher level math studies (Differential Equations & Linear Algebra) as we were expected to have memorized or fully understood which operations would "happen first" in complex algebraic expressions. Understanding which operators take the highest precedence in an expression is extremely important regardless of the level of math.</p>
<p>Some basic mathematical operators are:</p>
<ul>
<li>Addition: <code>+</code></li>
<li>Subtraction: <code>-</code></li>
<li>Multiplication: <code>*</code></li>
<li>Division: <code>/</code></li>
<li>Modulus: <code>%</code></li>
</ul>
<p>and specific to Python:</p>
<ul>
<li>Power of: <code>**</code></li>
<li>Floor division: <code>//</code></li>
</ul>
<h2 class="post-heading">Operator Precedence Table</h2>
<p>The PEMDAS acronynm has a common mnemonic device to help remember the acronymn: <strong>P</strong>lease <strong>E</strong>xcuse <strong>M</strong>y <strong>D</strong>ear <strong>A</strong>unt <strong>S</strong>ally.</p>
<blockquote>
<p>When two operators share an operand, the operator with the higher precedence goes first.</p>
</blockquote>
<p>The order of operations can be described by the table below. Where the operator precedence goes from highest (parentheses) to lowest (addition & subtraction). If you have to compare two operators in the same group, the precedence goes from left (highest) to right (lowest). This is called left-to-right associativity. For the exponents group, the associativity is right-to-left. All precedence rules can be overridden by explicitly placing parentheses around a part of the expression.</p>
<p>When two operators share an operand like <code>2 - 5 * 3</code>, the operator with the highest precedence will take place first. Therefore, <code>2 - 5 * 3</code> could be rewritten as <code>2 - (5 * 3)</code> where the parentheses now take highest precedence and <code>5 * 3</code> occurs first leaving us with <code>2 - 15 = -13</code>.</p>
<p>Something to keep in mind. When a division operator appears before multiplication, division goes first.</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Operator(s)</th>
<th>Mnemonic</th>
</tr>
</thead>
<tbody>
<tr>
<td>Parentheses</td>
<td><code>(expression)</code></td>
<td><strong>P</strong>lease</td>
</tr>
<tr>
<td>Exponents</td>
<td><code>**</code></td>
<td><strong>E</strong>xcuse</td>
</tr>
<tr>
<td>Multiplication & Division</td>
<td><code>*</code>, <code>/</code>, <code>//</code>, <code>%</code></td>
<td><strong>M</strong>y <strong>D</strong>ear</td>
</tr>
<tr>
<td>Addition & Subtraction</td>
<td><code>+</code>, <code>-</code></td>
<td><strong>A</strong>unt <strong>S</strong>ally</td>
</tr>
</tbody>
</table>
<h3 class="post-heading">Basic examples</h3>
<p>Now that we have the above table to reference and <a href="https://docs.python.org/3/reference/expressions.html">Python docs</a>, lets look at a few expressions. I will start off with a few "basic" expressions where the order of operations is straightforward, then the difficulty will increase and it will take a moment to scan the expression and make a note of which operations will occur first.</p>
<blockquote>
<p>Note: An expression can be represented as <code>2 + 5 - 2</code> where the operators are <code>+</code>, <code>-</code> and the operands (or values) are <code>2</code>, <code>5</code>, <code>2</code>.</p>
</blockquote>
<pre class="language-python"><code class="language-python">a <span class="token operator">=</span> <span class="token number">5</span> <span class="token operator">+</span> <span class="token number">4</span> <span class="token operator">-</span> <span class="token number">3</span> <span class="token operator">+</span> <span class="token number">2</span> <span class="token operator">+</span> <span class="token number">1</span><br /><span class="token keyword">print</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> <span class="token comment"># 9</span></code></pre>
<p>Since two operators share an operand like <code>+ 4 -</code> where 4 is surrounded by two operators, addition and subtraction. We can apply parentheses to the operator that takes the highest precedence (addition here) and continue evaluating the expression. Therefore, <code>5 + 4 - 3</code> can be written as <code>(5 + 4) - 3</code> which equals <code>9 - 3 = 6</code>.</p>
<p>This can be verified by checking the table above and seeing the <code>+</code> is the leftmost operator in the Addition & Subtraction group and when comparing operators in the same group, the operator closest to the left has the higher precedence.</p>
<p>Now for something a bit more involved:</p>
<pre class="language-python"><code class="language-python">b <span class="token operator">=</span> <span class="token number">30</span> <span class="token operator">/</span> <span class="token number">2</span> <span class="token operator">*</span> <span class="token number">5</span> <span class="token operator">+</span> <span class="token punctuation">(</span><span class="token number">10</span> <span class="token operator">+</span> <span class="token number">5</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">3</span></code></pre>
<details>
<summary>Show explanation</summary>
<pre class="language-python"><code class="language-python"><span class="token keyword">print</span>(b) <span class="token comment"># 87</span></code></pre>
<div>
<ol>
<li> Parentheses first (10 + 5) = 15 where the expression is rewritten as <code>30 / 2 * 5 + 15 - 3</code></li>
<li>Next, we can see the operand <code>2</code> shares two operators, multiplication takes the highest precedence but since the division comes before the multiplication the division goes first so <code>30 / 2 * 5</code> can be rewritten as <code>(30 / 2) * 5</code>. Which evaluates to <code>15 * 5 = 75</code>. The initial expression is now <code>75 + 15 - 3</code></li>
<li>Lastly do addition and subtraction, since the operand 15 shares two operators <code>+ 15 -</code> the addition goes first and can be rewritten as <code>(75 + 15) - 3 = 90 - 3 = 87</code></li>
</ol>
</div>
</details>
<h3 class="post-heading">Complex expressions</h3>
<p>Ok, so the above examples used parentheses, multiplication, division, addition, and subtraction. Lets do one more example that utilizes exponents to fully understand the order of operations in more complex expressions.</p>
<pre class="language-python"><code class="language-python">c <span class="token operator">=</span> <span class="token number">2</span> <span class="token operator">**</span> <span class="token number">4</span> <span class="token operator">+</span> <span class="token number">11</span> <span class="token operator">%</span> <span class="token number">5</span> <span class="token operator">-</span> <span class="token punctuation">(</span><span class="token number">20</span> <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">13</span> <span class="token operator">//</span> <span class="token number">2</span> <span class="token operator">*</span> <span class="token number">3</span><br /><span class="token keyword">print</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token comment"># 25</span></code></pre>
<p>There is alot going in the above expression. Lets break down the order of operations:</p>
<ol>
<li>Parentheses first: <code>(20 / 2) = 10</code> where the expression is rewritten as <code>2 ** 4 + 11 % 5 - 10 + 13 // 2 * 3</code></li>
<li>Exponents next: The exponents take the next highest precedence so <code>2 ** 4 = 16</code> and the initial expression will be <code>16 + 11 % 5 - 10 + 13 // 2 * 3</code></li>
<li>Now we look at the <code>2</code> operand which shares two operators <code>// 2 *</code>, the multiplication operator has higher precedence but if division occurs before multiplication the division comes first (<a href="https://tannerdolby.com/writing/operator-precedence-python/#operator-precedence-table">see above</a>). So we can rewrite <code>13 // 2 * 3</code> as <code>(13 // 2) * 3</code> which equals <code>6 * 3 = 18</code>. Now the original expression can be written as <code>16 + 11 % 5 - 10 + 18</code>.</li>
<li>The operand 5 shares two operators <code>% 5 -</code> and the modulo operator takes higher precedence so things can be rewritten as <code>(11 % 5) - 10</code> which equals <code>1 - 10 = -9</code>. Updating the original expression to be <code>16 - 9 + 18</code></li>
<li>Lastly handle the addition and subtraction, the operand <code>9</code> shares two operators and the subtraction appears first in the expression (even though addition takes higher precedence) so we can write <code>(16 - 9) + 18</code> which equals <code>7 + 18 = 25</code></li>
</ol>
<blockquote>
<p>Note: Typically, in everyday programming you won't encounter such expressions but they could potentially show up from time to time.</p>
</blockquote>
<h2 class="post-heading">Conclusion</h2>
<p>I hope the few examples shown within this article help you to better understand the order of operations in Python. Feel free to make up your own expressions and quiz yourself to see if you calculate the expected final answer after performing the correct order of operations. The expressions can be verified by entering them into REPL, Jupyter Notebook or a text editor of your choosing.</p>
<p>After practicing with a few expressions, you will start to become more comfortable with complex expressions and determining the order of operations will become second-nature.</p>
Rounding floating point numbers with Python2021-07-13T00:00:00Zhttps://tannerdolby.com/writing/rounding-in-python/<p>Rounding numbers in Python is quite common. There might be a situation where values must only be rounded to 3 decimals or some arbitrary number. Using the built-in function round() is handy but changes the original value.</p>
<p>During chemistry class in college, I frequently heard and used the term "significant figures". Which essentially referred to rounding off a large decimal number so that we only include the most relevant digits.</p>
<blockquote>
<p>Significant figures of a number in positional notation are digits in the number that are reliable and absolutely neccessary to indicate the quantity of something. <a href="https://en.wikipedia.org/wiki/Significant_figures">Wikipedia</a></p>
</blockquote>
<p>Outside of "sig figs", rounding decimal values to a certain precision and determining the type of rounding that occurs is quite important for extremely precise calculations like those in banking/financial software.</p>
<h2 class="post-heading h2-5">How does Python handle floating point numbers?</h2>
<p>Python at the lowest level, is built on top of C. That means that when floating point values undergo operations, the values that are being calculated by C (for Python) are converted to binary fractions and not floating point numbers. Unfortunately, the fractions are not as accurate as floating point numbers. When you see a floating point value, remember it is indeed a fraction (or two).</p>
<p>Somewhere within the calculations done by C, we realize that some floating points are being lost, which is not ideal for highly accurate financial software or other applications. Python gives us the built-in <code>round()</code> function to round floating point numbers (but this does change the original value and is not the most accurate). For ultimate accuracy, we can use packages like <a href="https://docs.python.org/3/library/decimal.html">decimal</a> to ensure floating point numbers are extremely precise.</p>
<p>One way to quickly test this for yourself, is to try performing some operations on two decimal value literals. Jump into REPL or your favorite text editor to follow along.</p>
<pre class="language-python"><code class="language-python"><span class="token operator">>></span><span class="token operator">></span> <span class="token number">4.6</span> <span class="token operator">+</span> <span class="token number">3.3</span><br /><span class="token number">7.8999999999999995</span></code></pre>
<p>As we would expect, the type of <code>value</code> is indeed a <code>float</code>. But what is intriguing is that instead of 7.9 being calculated, somewhere along the way when C calculates the binary fractions, we lose roughly 5 points and are given the value <code>7.8999999999999995</code>.</p>
<details>
<summary>Basic Terminology</summary>
<ul>
<li>4.6 + 3.3 is an expression</li>
<li>4.6 and 3.3 are float literals (operands)</li>
<li><code>/</code> is the division operator</li>
</ul>
</details>
<p>Using the built-in <a href="https://docs.python.org/3/library/functions.html#round"><code>round()</code></a> function, we can make sure the value is rounded to <code>n</code> decimals. Remeber this is not extremely accurate and does change the original value, so the floating points truncated are no longer stored in <code>value</code> and the new value is <code>7.9</code>.</p>
<pre class="language-python"><code class="language-python"><span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">round</span><span class="token punctuation">(</span><span class="token number">4.6</span> <span class="token operator">+</span> <span class="token number">3.3</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><br /><span class="token number">7.9</span></code></pre>
<h2 class="post-heading h2-5">Rounding without changing original value</h2>
<p>If we don't want to change the original value with <code>round()</code>, a great alternative for formatting output is <a href="https://docs.python.org/3/library/functions.html#format"><code>format()</code></a>. It allows us to format the output string without changing the original floating point number like <code>round()</code> does. This is handy when you just need to display the decimal output rounded to <code>n</code> decimal places without altering the original value.</p>
<blockquote>
<p>Note: Read more about rounding/formatting decimals on <a href="https://stackoverflow.com/questions/20457038/how-to-round-to-2-decimals-with-python">StackOverflow</a></p>
</blockquote>
<p>This example demonstrates how to display the rounded/formatted decimal number output:</p>
<div class="filename-title"><span>Filename</span>: <em>formatting.py</em></div>
<pre class="language-python"><code class="language-python">value <span class="token operator">=</span> <span class="token number">4.652</span> <span class="token operator">+</span> <span class="token number">3.321</span><br /><span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'The formatted/rounded value is {:0.2f}'</span><span class="token punctuation">.</span><span class="token builtin">format</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span><br /><span class="token comment"># The formatted/rounded value is 7.97</span></code></pre>
<p>You could also use <a href="https://realpython.com/python-f-strings/">f-strings</a> which is a much quicker way to format strings as an alternative to the longhand <code>format()</code> usage. Simply place the letter <code>f</code> before your string and use curly braces <code>{}</code> to interpolate variables inside a string just as we would do with backticks and string interpolation syntax <code>${}</code> in JavaScript.</p>
<pre class="language-python"><code class="language-python">name <span class="token operator">=</span> <span class="token string">"Root"</span><br />size <span class="token operator">=</span> <span class="token number">250</span><br /><span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string-interpolation"><span class="token string">f"I am </span><span class="token interpolation"><span class="token punctuation">{</span>name<span class="token punctuation">}</span></span><span class="token string">. I have </span><span class="token interpolation"><span class="token punctuation">{</span>size<span class="token punctuation">}</span></span><span class="token string">GB of storage."</span></span><span class="token punctuation">)</span><br /><span class="token comment"># I am Root. I have 250GB of storage.</span></code></pre>
<h2 class="post-heading h2-5">Extreme precision rounding</h2>
<p>If your building a complex financial system or application that requires very precise calculations, using the <a href="https://docs.python.org/3/library/decimal.html">decmimal</a> module will be the recommended course of action. The Python docs provide a great quick start example for anyone interested in using this module for precise floating point calculations.</p>
<pre class="language-python"><code class="language-python"><span class="token keyword">from</span> decimal <span class="token keyword">import</span> <span class="token operator">*</span><br /><br /><span class="token comment"># View the current context</span><br />ctx <span class="token operator">=</span> getcontext<span class="token punctuation">(</span><span class="token punctuation">)</span><br /><span class="token keyword">print</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span> <span class="token comment"># Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[Overflow, DivisionByZero, InvalidOperation])</span><br /><br /><span class="token comment"># Alter precision</span><br />ctx<span class="token punctuation">.</span>prec <span class="token operator">=</span> <span class="token number">10</span><br /><br /><span class="token comment"># Construct some new decimal objects</span><br />a <span class="token operator">=</span> Decimal<span class="token punctuation">(</span><span class="token number">3.14</span><span class="token punctuation">)</span><br /><span class="token keyword">print</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> <span class="token comment"># 3.140000000000000124344978758017532527446746826171875</span><br /><br />b <span class="token operator">=</span> Decimal<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br /><span class="token keyword">print</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> <span class="token comment"># 5.15</span></code></pre>
<p>The significance of a new Decimal is determined solely by the number of digits input. Context precision and rounding only come into play during arithmetic operations.</p>
<p>Keep the above in mind when setting specific <code>prec</code> values for the decimal module context <code>getcontext()</code>. We create new <code>Decimal</code> values in the code snippet above and the significance is determined by the number digits used as input. When arithmetic operations are performed, the context precision and rounding come into play.</p>
<pre class="language-python"><code class="language-python"><span class="token comment"># Arithmetic operations (where precision and rounding come into play)</span><br />val <span class="token operator">=</span> Decimal<span class="token punctuation">(</span><span class="token number">5.05362</span><span class="token punctuation">)</span> <span class="token operator">+</span> Decimal<span class="token punctuation">(</span><span class="token number">2.61589</span><span class="token punctuation">)</span><br /><span class="token keyword">print</span><span class="token punctuation">(</span>val<span class="token punctuation">)</span> <span class="token comment"># 7.66951</span><br /><br /><span class="token comment"># Change rounding in context to round up (from default ROUND_HALF_EVEN)</span><br />ctx<span class="token punctuation">.</span>rounding <span class="token operator">=</span> ROUND_DOWN<br />val <span class="token operator">=</span> Decimal<span class="token punctuation">(</span><span class="token number">5.05362</span><span class="token punctuation">)</span> <span class="token operator">+</span> Decimal<span class="token punctuation">(</span><span class="token number">2.61589</span><span class="token punctuation">)</span><br /><span class="token keyword">print</span><span class="token punctuation">(</span>val<span class="token punctuation">)</span> <span class="token comment"># 7.66950</span></code></pre>
<p>There is much more to be discovered in the <a href="https://docs.python.org/3/library/decimal.html">decimal</a> module, but I will leave that up to you. I hope this article shed some light on floating point numbers in Python and the options you have for dealing with extremely precise decimal calculations.</p>
Fetch a remote branch to review changes2021-05-03T00:00:00Zhttps://tannerdolby.com/writing/pull-into-a-feature-branch/<p>When reviewing a PR, its usually helpful to pull into that feature branch and test the changes locally in your own copy of the project.</p>
<blockquote>
<p>Can you pull into my feature branch and review the changes locally?</p>
</blockquote>
<p>I saw this phrase appear again and again while contributing to Open Source. Before I knew the <code>git</code> commands to accomplish pulling into a feature branch, I tried thinking about how I would actually get the changes from a remote branch. It seemed straightforward, fetch changes from an upstream branch and checkout your own local branch with those fetched changes. Turns out it was really quite simple, but we need to specify an associated pull request ID when fetching the remote branch.</p>
<pre class="language-git"><code class="language-git">git fetch origin pull/id/head:$BRANCHNAME</code></pre>
<p>We fetch the changes from a specific feature branch and then can use <code>git checkout</code> to switch branches into the feature branch.</p>
<pre class="language-git"><code class="language-git">git fetch origin pull/2/head:563-some-bug-fix<br /><br />git checkout 563-some-bug-fix</code></pre>
<p>That's it. Fetch changes from a local or remote feature branch and switch branches to the newly created branch from the fetch. If your pulling into a feature branch from a remote repository, use <code>upstream</code> instead of <code>origin</code>.</p>
<pre class="language-git"><code class="language-git">git fetch upstream pull/id/head:$BRANCHNAME</code></pre>
<p>Lets say there was a pull request with <code>id</code> equaling 25 and the branch this PR was submitted from is <code>323-fix-async</code>. The following usage would be:</p>
<pre class="language-git"><code class="language-git">git fetch upstream pull/25/head:323-fix-async<br /></code></pre>
<p>Then switch branches into the feature branch with <code>git checkout</code>.</p>
<pre class="language-git"><code class="language-git">git checkout 323-fix-async<br /><br />Switched to branch <span class="token string">'323-fix-async'</span></code></pre>
<p>Now you have a local copy of the changes in a upstream feature branch, its time to start revewing and approve or reject those changes! If you want to see what branch your currently on, use <code>git branch</code>.</p>
<h2 class="post-heading">Pulling on a branch</h2>
<p>Let's say we had a feature branch named <code>112-fix-buffer</code> that we submitted some changes on in a public repository called <code>the-buffer-proj</code>. When someone else pulls into your feature branch 112-fix-buffer and makes changes then pushes those changes. Your branch locally will be "behind" as there are changes proposed by others that you haven't synced with yet. To get up-to-date (merge) with your own branch just pull on it to get the latest changes.</p>
<pre class="language-cpp"><code class="language-cpp">git pull origin <span class="token number">112</span><span class="token operator">-</span>fix<span class="token operator">-</span>buffer</code></pre>
<p>This will perform a fetch and merge of remote commits.</p>
Using Modules in Node.js2021-03-24T00:00:00Zhttps://tannerdolby.com/writing/using-modules-in-node.js/<p>Files can become quite large in a Node.js project. Modules provide developers a "modular" approach by putting related code into separate files and then exporting them to be used elsewhere.</p>
<h2 class="post-heading">What is a module?</h2>
<p>Modules in Node.js are essentially just files. They provide a place for related code to be stored and exported for reuse throughout the application. Each module will usually have it's own context (ie data, code). The reason why every module has it's own context is because it can't interfere with other modules or pollute the global scope by defining too many variables that are globally accessible.</p>
<p>If you don't want code in a file to be used elsewhere or shared between files, simply don't use <code>module.exports</code> as you don't wish to export any code from that file.</p>
<p>Below is a demo of sorts outlining one large file <code>server.js</code>, which will have it's code separated into "modules". These modules will contain related code extracted from <code>server.js</code> that can be exported and reused throughout the application.</p>
<pre class="language-js"><code class="language-js"> <span class="token operator">|</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span><span class="token operator">|</span><br /> <span class="token operator">|</span> server<span class="token punctuation">.</span>js <span class="token operator">|</span><br /> <span class="token operator">|</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span><span class="token operator">|</span><br /> <span class="token operator">|</span> <span class="token operator">|</span> <span class="token operator">|</span><br /> <span class="token operator">/</span> <span class="token operator">|</span> \<br /><span class="token operator">|</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span><span class="token operator">|</span> <span class="token operator">|</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span><span class="token operator">|</span> <span class="token operator">|</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span><span class="token operator">|</span><br /><span class="token operator">|</span> file1<span class="token punctuation">.</span>js<span class="token operator">|</span> <span class="token operator">|</span> file2<span class="token punctuation">.</span>js<span class="token operator">|</span> <span class="token operator">|</span> file3<span class="token punctuation">.</span>js<span class="token operator">|</span><br /><span class="token operator">|</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span><span class="token operator">|</span> <span class="token operator">|</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span><span class="token operator">|</span> <span class="token operator">|</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span><span class="token operator">|</span></code></pre>
<p>Each of the files connected to <code>server.js</code> in the diagram are considered "modules". So what actually goes into each of the <code>fileX.js</code> files? Inside each module will be related code to <code>server.js</code>. Therefore, <code>file1.js</code> could contain code for adding new users to the server by defining an API endpoint for making the POST request.</p>
<p>Another file, <code>file2.js</code> might contain code for authenticating logged in users. This file would have <code>jsonwebtoken</code> (JWT) and potentially <code>bcrypt</code> to verify users JWT token and compare hashed passwords.</p>
<p>The great thing about developing with Node.js, is that we can make our code "modular" with the help <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules">modules</a>. Instead of having one gigantic server file, create modules containing specific functionalities for the server and then import that module into the server file. Potentially reducing the main files size and making your code more modular.</p>
<h2 class="post-heading">How to create a module</h2>
<p>Creating modules are dead simple. Separate some related code from the main file and place it in a new file which we can export for use later. Below will be an example using one main file <code>animal.js</code>, which we can break into modules to reduce the overall file size.</p>
<div class="filename-title"><span>Filename</span>: <em>animal.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token comment">// define some animal sound functions</span><br /><span class="token keyword">function</span> <span class="token function">hiss</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><br /><span class="token keyword">function</span> <span class="token function">bark</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><br /><span class="token keyword">function</span> <span class="token function">quack</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><br /><br /><span class="token comment">// use the functions to log console output</span><br /><span class="token keyword">const</span> dog <span class="token operator">=</span> <span class="token string">"A dog goes "</span> <span class="token operator">+</span> <span class="token function">bark</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> snake <span class="token operator">=</span> <span class="token string">"A snake goes "</span> <span class="token operator">+</span> <span class="token function">hiss</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> duck <span class="token operator">=</span> <span class="token string">"A duck goes "</span> <span class="token operator">+</span> <span class="token function">quack</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Instead of defining the <code>hiss/bark/quack</code> functions within <code>animal.js</code>, let's create a module called <code>sounds.js</code> and store the functions.</p>
<div class="filename-title"><span>Filename</span>: <em>sounds.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">bark</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token string">"Woof woof woof!"</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><span class="token keyword">function</span> <span class="token function">hiss</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token string">"Sssssssss!"</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><span class="token keyword">function</span> <span class="token function">quack</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token string">"Quack quack!"</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br />module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span><br /> bark<span class="token punctuation">,</span><br /> hiss<span class="token punctuation">,</span><br /> quack<br /><span class="token punctuation">}</span></code></pre>
<p>To convert the <code>sounds.js</code> file into a module, we must use <code>module.exports</code> to store the functions. Once the code has been exported, it can be used anywhere else with the help of <code>require()</code>.</p>
<h2 class="post-heading">Using code from a module</h2>
<p>Now that we have created a module, it's time to use the exported code inside <code>animal.js</code> to reduce the file size. First, use the <code>require</code> keyword to bring the <code>sounds.js</code> module into <code>animal.js</code>. Make sure to provide <code>require</code> with the relative path to the module.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> sounds <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./sounds"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">const</span> dog <span class="token operator">=</span> <span class="token string">"A dog goes "</span> <span class="token operator">+</span> sounds<span class="token punctuation">.</span><span class="token function">bark</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> snake <span class="token operator">=</span> <span class="token string">"A snake goes "</span> <span class="token operator">+</span> sounds<span class="token punctuation">.</span><span class="token function">hiss</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> duck <span class="token operator">=</span> <span class="token string">"A duck goes "</span> <span class="token operator">+</span> sounds<span class="token punctuation">.</span><span class="token function">quack</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>dog<span class="token punctuation">)</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>snake<span class="token punctuation">)</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>duck<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Output:</p>
<pre class="language-html"><code class="language-html">A dog goes Woof woof woof!<br />A snake goes Ssssssss!<br />A duck goes Quack Quack</code></pre>
<h2 class="post-heading">Conclusion</h2>
<p>There are a few different ways you can use <code>module.exports</code> in Node.js, I showed one way above using <code>module.exports = {}</code>. You can also use the following:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">greet</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token string">"Hello world!"</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">// Define the property on module.exports and assign it</span><br />module<span class="token punctuation">.</span>exports<span class="token punctuation">.</span>greet <span class="token operator">=</span> greet<span class="token punctuation">;</span><br /><br /><span class="token comment">// Use a comma separated list</span><br />module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span><br /> greet<span class="token punctuation">,</span><br /> someOtherFunc<br /><span class="token punctuation">}</span><br /><br /><span class="token comment">// Define the function inside the module.exports object</span><br />module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span><br /> <span class="token function-variable function">greet</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token string">"Hello world!"</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<p>Using modules are a great way to keep your code organized and reusable. I'm beginning to realize how modules really do help in writing structured code.</p>
Remove duplicates in Arrays2021-02-17T00:00:00Zhttps://tannerdolby.com/writing/remove-duplicates-in-arrays/<p>Removing duplicate values from an array is quite a common task in programming. Sometimes, specific scenarios require a collection of data to only store unique values. That is, no repeated values.</p>
<p>A <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set"><code>Set</code></a> data structure is commonly used in programming languages to store unique values. The Set object in JavaScript allows you to store "unique" values of any data type. For a value in the Set to be unique, it may only occur once, otherwise duplicate values are removed from the collection. This makes removing duplicate values from an array trivial by transferring the array values into a Set.</p>
<p>Below is an example of removing duplicate values from an array by converting the <code>Array</code> to a <code>Set</code>.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <br /><span class="token keyword">const</span> unique <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token keyword">new</span> <span class="token class-name">Set</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>set<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Output:</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">]</span></code></pre>
<p>There is quite a bit going on in the above code block. We declare an array <code>arr</code> with two duplicate values. To remove those duplicate values, we add the array values into a Set called <code>unique</code>. Next, we can convert the Set into an <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a> by wrapping the <code>new Set()</code> instance inside brackets <code>[]</code> and using the (<code>...</code>) <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax">spread operator</a>.</p>
<h2 class="post-heading">Other Options</h2>
<p>Using a <code>Set</code> is my go-to way of removing duplicate values in an Array, but there is also a few other options for this task. Utilizing <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf"><code>Array.prototype.indexOf</code></a> and the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter"><code>Array.prototype.filter</code></a> method allows us to filter an Array for duplicate values and return the filtered array which only contains unique values.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"a"</span><span class="token punctuation">,</span> <span class="token string">"b"</span><span class="token punctuation">,</span> <span class="token string">"c"</span><span class="token punctuation">,</span> <span class="token string">"b"</span><span class="token punctuation">,</span> <span class="token string">"a"</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> unique <span class="token operator">=</span> arr<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">item<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> arr<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span> <span class="token operator">==</span> index<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>unique<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Output:</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">[</span><span class="token string">"a"</span><span class="token punctuation">,</span> <span class="token string">"b"</span><span class="token punctuation">,</span> <span class="token string">"c"</span><span class="token punctuation">]</span></code></pre>
<p><code>Array.prototype.indexOf</code> returns the first index at which a given element can be found in the array. If the element isn't present it returns <code>-1</code>. The way the above logic works for removing duplicates is by iterating over the array <code>arr</code> and checking each value to see if the <code>arr.indexOf(item)</code> index matches the position of the element being processed in the <code>filter()</code> method.</p>
<p><code>Array.prototype.filter</code> creates and returns a new array with all values that pass the test provided in the callback function. Similar to a <code>forEach()</code> method, the <code>filter()</code> method calls the provided callback function once for each element in the array. The difference between <code>forEach</code> and <code>filter</code> is that <code>filter()</code> creates a new array with all the values for which the callback function returns a <a href="https://developer.mozilla.org/en-US/docs/Glossary/Truthy">"truthy"</a> value.</p>
<p>To better understand the logic, the first iteration would look something like:</p>
<pre class="language-js"><code class="language-js">arr<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span><span class="token string">"a"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 0 (first index)</span><br />index <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">// first element being processed</span><br /><span class="token number">0</span> <span class="token operator">==</span> <span class="token number">0</span> <span class="token comment">// true, add "a" to the new filtered array</span><br /><span class="token operator">...</span><br />arr<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span><span class="token string">"c"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 2 (third index)</span><br />index <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span> <span class="token comment">// third element being processed</span><br /><span class="token number">2</span> <span class="token operator">==</span> <span class="token number">2</span> <span class="token comment">// true</span><br /><br /><span class="token comment">// (4th index & first repeat) returns 1 since "b" appears in the array at index 1 first ie 2nd element</span><br />arr<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span><span class="token string">"b"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 1</span><br />index <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span> <span class="token comment">// fourth element being processed</span><br /><span class="token number">1</span> <span class="token operator">==</span> <span class="token number">3</span> <span class="token comment">// false (don't add second occurrence of "b" to filtered array)</span></code></pre>
<p>And the same logic is applied to the remaining elements to be processed, if they return true after being processed by the callback function, the values are added to the constructed filtered array. Hopefully the above examples explain how using <code>indexOf</code> and <code>filter</code> to remove duplicates from an array is clear.</p>
<p>Lastly, you could use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach"><code>Array.prototype.forEach</code></a> and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes"><code>Array.prototype.includes</code></a> to check for duplicate values and then push the unique values into a new array. Using <code>forEach</code> behaves similiar to <code>filter</code> by performing the callback function for each element in the array. The <code>includes</code> method returns <code>true</code> or <code>false</code> depending on the value exists in the array or not.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// create empty array to store values after conditional checks</span><br /><span class="token keyword">const</span> unique <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><br />arr<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">item</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>unique<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> unique<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>unique<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Output:</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">]</span></code></pre>
<p>The above works by iterating over the original array and performing the callback function on each element to check if the the unique array <code>unique</code> doesn't already have the value. If the unique array (which starts as empty) doesn't include the element in <code>arr</code> then add it to the unique array with <code>unique.push(item)</code>. Therefore, to start the first 3 values added to <code>unique</code> will be <code>[1, 2, 4]</code> and then it checks to see that the next 4 is a duplicate and therefore doesn't add it to the array along with 2 and finally adds 6 since it doesn't currently exist in <code>unique</code>.</p>
<p>That's all folks. Feel free to read more about removing duplicates in arrays from this great <a href="https://www.javascripttutorial.net/array/javascript-remove-duplicates-from-array/">resource</a>.</p>
Creating a blog template with Angular and Node.js2021-02-10T00:00:00Zhttps://tannerdolby.com/writing/creating-a-blog-template-with-angular-and-node.js/<p>I wanted to use Angular and Node.js for creating a blog template similar to how I would do things in Eleventy. Create one base template that each of the blog posts content can be displayed on. It showcases Angular Material, GitHub REST API, Netlify lambda functions and Netlify for hosting.</p>
<h2 class="post-heading">How does it work?</h2>
<p>Coming from a background of using Static Site Generators (Eleventy), I've missed being able to write a bunch of blog posts and put their contents in a <em>single</em> post template. Where you have one directory of blog posts, could be Markdown files, HTML files, etc. Then those pages are fed to a "layout", which is essentially just an HTML page that acts as a template or base layout for template content that will be added to the page.</p>
<p>With Angular, I thought it wouldn't make much sense to create a component for every blog post, that just seems like unecessary work as the only part that really matters is the Markup or <code>name.component.html</code> template file. Unless you needed the HTML files to have specific metadata then it might make sense to have each post be a full blown component.</p>
<p>The <code>/assets/pages</code> directory in the Angular project is where all the blog post <code>.html</code> files are stored and post metadata lives in <code>/assets/blog.json</code>.</p>
<p>The <code>/pages</code> directory will hold every blog posts <code>.html</code> file. If you were thinking about writing a new post, you would first create the file in <code>/assets/pages</code> as <code>some-new-post.html</code> and give the file some content,</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>Welcome to my post!<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>This is some text<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span></code></pre>
<p>and provide metadata for that post in <code>/assets/blog.json</code> by creating a new post object:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">[</span><br /> <span class="token punctuation">{</span><br /> <span class="token property">"title"</span><span class="token operator">:</span> <span class="token string">"Some New Post"</span><span class="token punctuation">,</span><br /> <span class="token property">"date"</span><span class="token operator">:</span> <span class="token string">"3/29/2021"</span><span class="token punctuation">,</span><br /> <span class="token property">"tags"</span><span class="token operator">:</span> <span class="token punctuation">[</span><br /> <span class="token string">"mongodb"</span><span class="token punctuation">,</span><br /> <span class="token string">"nosql"</span><br /> <span class="token punctuation">]</span><span class="token punctuation">,</span><br /> <span class="token property">"template"</span><span class="token operator">:</span> <span class="token string">"some-post.html"</span><span class="token punctuation">,</span><br /> <span class="token property">"image"</span><span class="token operator">:</span> <span class="token string">"./assets/images/mongodb.jpeg"</span><span class="token punctuation">,</span><br /> <span class="token property">"preview"</span><span class="token operator">:</span> <span class="token string">"Some post preview"</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">]</span><br /></code></pre>
<p>Now you can sit back and let Node.js do the work of reading the blog post files in <code>/assets/pages</code> to extract the HTML content. Then send the metadata and post HTML to the Angular service to be rendered on the page. The <a href="https://docs.github.com/en/rest">GitHub REST API</a> is used to grab the <code>blog.json</code> metadata file and blog posts in the <code>/pages</code> directory. This file reading job was originally handled by the File System Module but since Netlify lambda functions don't bring along static assets with them in the <code>functions</code> folder, I was forced to fallback to fetching files and their contents using the GitHub API endpoints.</p>
<p>Using a service within the Angular code, we can fetch data from the API endpoints created by the lambda functions which store the responses from hitting the GitHub REST API.</p>
<h2 class="post-heading">Updating API endpoints</h2>
<p>When you deploy your own site using this template on Netlify, you must update the <code>/assets/endpoints.ts</code> file which holds all of the API endpoint URLs. The <code>prod</code> fields take the highest priority where the other two can be left out in terms of the app running in production after deployment.</p>
<div class="filename-title"><span>Filename</span>: <em>endpoints.ts</em></div>
<pre class="language-ts"><code class="language-ts"><span class="token keyword">export</span> <span class="token keyword">const</span> endpoints <span class="token operator">=</span> <span class="token punctuation">{</span><br /> <span class="token string">"prod"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token string">"post"</span><span class="token operator">:</span> <span class="token string">"https://anodeblog.netlify.app/.netlify/functions/post"</span><span class="token punctuation">,</span><br /> <span class="token string">"postsMetadata"</span><span class="token operator">:</span> <span class="token string">"https://anodeblog.netlify.app/.netlify/functions/metadata"</span><span class="token punctuation">,</span><br /> <span class="token string">"recentPosts"</span><span class="token operator">:</span> <span class="token string">"https://anodeblog.netlify.app/.netlify/functions/metadata"</span><span class="token punctuation">,</span><br /> <span class="token string">"postsByTag"</span><span class="token operator">:</span> <span class="token string">"https://anodeblog.netlify.app/.netlify/functions/tagged"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token string">"lambda-dev"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token string">"post"</span><span class="token operator">:</span> <span class="token string">"http://localhost:9000/.netlify/functions/app/blog/"</span><span class="token punctuation">,</span><br /> <span class="token string">"recentPosts"</span><span class="token operator">:</span> <span class="token string">"http://localhost:9000/.netlify/functions/app/recent"</span><span class="token punctuation">,</span><br /> <span class="token string">"postsMetadata"</span><span class="token operator">:</span> <span class="token string">"http://localhost:9000/.netlify/functions/app/blog"</span><span class="token punctuation">,</span><br /> <span class="token string">"postsByTag"</span><span class="token operator">:</span> <span class="token string">"http://localhost:9000/.netlify/functions/app/blog/topics"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token string">"express-dev"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token string">"post"</span><span class="token operator">:</span> <span class="token string">"http://localhost:4000/blog/"</span><span class="token punctuation">,</span><br /> <span class="token string">"recentPosts"</span><span class="token operator">:</span> <span class="token string">"http://localhost:4000/recent"</span><span class="token punctuation">,</span><br /> <span class="token string">"postsByTag"</span><span class="token operator">:</span> <span class="token string">"http://localhost:4000/blog/topics"</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<h2 class="post-heading">What endpoints are available?</h2>
<p>Each of the Netlify lambda functions will be deployed as an API endpoint. That means the following endpoints exist:</p>
<table>
<thead>
<tr>
<th>Endpoint</th>
<th>Method</th>
<th>Desc</th>
</tr>
</thead>
<tbody>
<tr>
<td>/.netlify/functions/metadata</td>
<td>GET</td>
<td>Get all of the blog post metadata</td>
</tr>
<tr>
<td>/.netlify/functions/post?name=some-slug</td>
<td>GET</td>
<td>Get a single blog post by slug.</td>
</tr>
<tr>
<td>/.netlify/functions/recent</td>
<td>GET</td>
<td>Get three of the most recent blog posts, sorted by creation date.</td>
</tr>
<tr>
<td>/.netlify/functions/tagged?tag=sometag</td>
<td>GET</td>
<td>Get posts by tag.</td>
</tr>
</tbody>
</table>
<h2 class="post-heading">Defining Redirects</h2>
<p>Angular projects are usually single page applications (SPAs). Essentially, this means that the page shouldn't really ever be reloaded. Your just visiting different routes in the single page view which serve different content. For example, <code>my-website.com/blog</code> would be serving a different component than <code>my-website/about</code>. The router outlet is placed in the root components template and this allows the components that correspond with the requested route to be served on the page, all without any page reloading, just re-routing. The <code>path</code> keys in <code>app-routing.module.ts</code> are where each route will be defined in Angular projects.</p>
<p>That being said, when serving the static files from an Angular project by using <code>res.sendFile</code> in Node.js/Express endpoints. I usually only send the <code>index.html</code> file from the Angular build files at the <code>/</code> root endpoint since the router will handle all the SPA routing. Since Angular focuses on not reloading the page, this can lead to the static file not rendering when the page is refreshed and only showing whatever data was being served as a response to that specific endpoint. This same situation happens on Netlify (as expected). To handle this, Netlify allows us to define some <a href="https://docs.netlify.com/routing/redirects/">redirects</a> in the <code>netlify.toml</code> configuration file. Specifying a <code>from</code> and <code>to</code> URL string, along with an optional HTTP status code with <code>status</code>.</p>
<pre class="language-toml"><code class="language-toml"><span class="token punctuation">[</span><span class="token table class-name">build</span><span class="token punctuation">]</span><br /> <span class="token key property">command</span> <span class="token punctuation">=</span> <span class="token string">"functions"</span><br /> <span class="token key property">publish</span> <span class="token punctuation">=</span> <span class="token string">"dist/blog-client"</span><br /><br /> <span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token table class-name">redirects</span><span class="token punctuation">]</span><span class="token punctuation">]</span><br /> <span class="token key property">from</span> <span class="token punctuation">=</span> <span class="token string">"https://anodeblog.netlify.app/*"</span><br /> <span class="token key property">to</span> <span class="token punctuation">=</span> <span class="token string">"https://anodeblog.netlify.app"</span><br /> <span class="token key property">status</span> <span class="token punctuation">=</span> <span class="token number">200</span></code></pre>
<p>I want to redirect any path that is prefixed with <code>https://anodeblog.netlify.app</code> by using the <code>*</code> asterisk. This means any route on the website will be redirected to the <code>to</code> URL. Therefore, if I refresh the page on <code>https://anodeblog.netlify.app/blog</code> the same page will be rendered because we are redirecting <code>anodeblog.netlify.app/blog</code> back to <code>https://anodeblog.netlify.app</code> which contains the <code>index.html</code> from Angular build files where the Router lives and can correctly route to the corresponding component based on the request URL. If the <code>[[redirects]]</code> content was not defined in <code>netlify.toml</code> then when you attempt to refresh the page on <code>/blog</code> it will return a "404 not found" as it can't find or doesn't recognize static files being served at this route.</p>
<h2 class="post-heading">Future work</h2>
<p>It would be really nice to add some sort of Caching mechanism to this template. That way, the GitHub REST API could only be hit once when the site is deployed or on some other event. Then we can use the API data to supply the Angular services and render the content on the page. Currently the API is being called on every page, this is not ideal as the GitHub REST API does have rate limiting built in. Bringing in state management with NgRx would be a good way to keep track of the cached posts in the "store".</p>
<h2 class="post-heading">Closing remarks</h2>
<p>The GitHub REST API does have a limited rate for hitting the endpoints. This causes a small problem as the app relies on the REST API's endpoints for fetching file data. The rate is relatively high per hour but if your site was quite busy this would lead to a problem. I think one way around this is caching the first API requests for metadata and the posts directory then simply reuse that data throughout the app. Making only 1-2 API calls no matter the traffic instead of a call for everytime the a new page is navigated too. Using NgRx for state management would be nice to update the intial store state with the cached API response.</p>
<p>Netlify starter accounts provide really great features for hosting your own website or blog. I've usually only used <a href="https://netlify.com/">Netlify</a> for hosting static sites, but since they introduced <a href="https://www.netlify.com/products/functions/">Netlify Lambda functions</a>, which are essentially AWS Lambda functions. We are now able to host full stack applications through Netlify. The netlify functions we create are deployed as API endpoints which is really cool.</p>
<p><a href="https://www.netlify.com/blog/2018/03/20/netlifys-aws-lambda-functions-bring-the-backend-to-your-frontend-workflow/">Pricing is metered</a> for the Netlify Lambda functions so keep that in mind if you choose to host this full stack app with Netlify. Unless you expect alot of site traffic, the Netlify starter account limits are plenty for a personal website.</p>
<p>You can view the <a href="https://github.com/tannerdolby/angular-node-blog">source code</a> over on GitHub.</p>
<p>Thanks for reading! 🚀</p>
What is an Array in JavaScript?2021-02-06T00:00:00Zhttps://tannerdolby.com/writing/what-is-an-array-in-javascript/<p>In JavaScript, arrays are predefined objects, where the indexes are the arrays properties. They can hold a collection of values with differing data types. The array is a go-to data structure for common list related tasks.</p>
<h2 class="post-heading">Is JavaScript Object Oriented?</h2>
<p>JavaScript is a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model#class-based_vs._prototype-based_languages">prototype based</a>, multi-paradigm, single threaded, dynamic language which supports object oriented, imperative, and declarative styles.</p>
<p>The one difference between other OOP languages like Java or C++ and JavaScript, is the fact that JavaScript isn't class based, it's prototype based and doesn't require explicit <code>class</code> usage to define objects. It uses prototype based object constructions. Within a prototype based language like JavaScript, the prototypical object is an object used as a template to get the initial properties for a new object. We can use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function">function declarations</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#class_declarations">class declarations</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#class_expressions">class expressions</a> for defining a template for objects.</p>
<p>Instead of defining a class declaration for every object like we would in Java:</p>
<div class="filename-title"><span>Filename</span>: <em>Shape.java</em></div>
<pre class="language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Shape</span> <span class="token punctuation">{</span><br /> <span class="token keyword">public</span> <span class="token keyword">int</span> x<span class="token punctuation">;</span><br /> <span class="token keyword">public</span> <span class="token keyword">int</span> y<span class="token punctuation">;</span><br /> <span class="token keyword">public</span> string currShape<span class="token punctuation">;</span><br /><br /> <span class="token function">constructor</span><span class="token punctuation">(</span>x<span class="token operator">:</span> <span class="token keyword">int</span><span class="token punctuation">,</span> y<span class="token operator">:</span> <span class="token keyword">int</span><span class="token punctuation">,</span> currShape<span class="token operator">:</span> string<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>x <span class="token operator">=</span> x<span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>y <span class="token operator">=</span> y<span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>currShape <span class="token operator">=</span> currShape<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>the equivalent <code>function</code> declaration in JavaScript would look like this:</p>
<div class="filename-title"><span>Filename</span>: <em>Shape.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">Shape</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>x <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>y <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>currShape <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>The reason why sometimes choosing a "function declaration" will be preferred is because of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#hoisting">hoisting</a>. Function declarations are <a href="https://developer.mozilla.org/en-US/docs/Glossary/Hoisting">hoisted</a> where class declarations are not. Which in short, means that with function declarations the compiler allocates memory for the function declarations prior to the execution of code, so we can access the object "before" its declaration like this:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> el <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// OK!</span><br /><br /><span class="token keyword">function</span> <span class="token function">Foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>bar <span class="token operator">=</span> <span class="token string">"foobar"</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>The above is possible thanks to hoisting, which makes variables and function declarations able to be accessed before their definition. Hoisting only works for declarations and not initializations.</p>
<h3 class="post-heading">Can I still use ES6 style classes</h3>
<p>You can most definitely still create the template for objects (classes) using ES6 style class syntax, which has been described as "class declarations" above. Just as shown earlier in the article, we can define classes in JavaScript with the ES6 style (class declaration) like this:</p>
<div class="filename-title"><span>Filename</span>: <em>myclass.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token keyword">class</span> <span class="token class-name">MyClass</span> <span class="token punctuation">{</span><br /> <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">x<span class="token punctuation">,</span> y</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>x <span class="token operator">=</span> x<span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>y <span class="token operator">=</span> y<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<p>using named or unnamed class expressions works too:</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// unnamed</span><br /><span class="token keyword">const</span> MyOtherClass <span class="token operator">=</span> <span class="token keyword">class</span> <span class="token punctuation">{</span><br /> <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">foo</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>foo <span class="token operator">=</span> foo<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// named</span><br /><span class="token keyword">const</span> SomeOtherClass <span class="token operator">=</span> <span class="token keyword">class</span> <span class="token class-name">SomeOther</span> <span class="token punctuation">{</span><br /> <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">foo</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>foo <span class="token operator">=</span> foo<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>If you want to specify the "next" object in the inheritance chain. Like we would by defining a class as a child of some superclass <code>class Foo extends Bar</code>. We add a prototypical instance as the value of the <code>prototype</code> property within the constructor, then simply override the prototypes constructor to the constructor function.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">Square</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token function">Shape</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>currShape <span class="token operator">=</span> <span class="token string">"Square"</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><span class="token comment">// Pass in the prototypical instance to Object.create()</span><br /><span class="token comment">// and assign it to the prototype property of Square definition</span><br /><span class="token class-name">Square</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token class-name">Shape</span><span class="token punctuation">.</span>prototype<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// Override the constructor with our constructor function Shape</span><br /><span class="token class-name">Square</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>constructor <span class="token operator">=</span> Square<span class="token punctuation">;</span></code></pre>
<p>Now we have a inheritance chain, where the <code>Shape</code> definition descends from <code>Square</code>. The hierarchy would look like this in Java:</p>
<pre class="language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Square</span> <span class="token keyword">extends</span> <span class="token class-name">Shape</span> <span class="token punctuation">{</span><br /> <span class="token keyword">public</span> string currShape <span class="token operator">=</span> <span class="token string">"Square"</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>If your coming from a C or Java background which is class-based, it might take a little bit of practice and reading to get the hang of prototype-based languages and Object model along with the inheritance chain. You can read more on <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model#class-based_vs._prototype-based_languages">MDN - Details of the Object model</a>.</p>
<h2 class="post-heading">Defining Objects</h2>
<p>We can define an <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><code>Object</code></a> in multiple ways in JavaScript:</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// Create an object literal</span><br /><span class="token keyword">let</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span> x<span class="token operator">:</span> <span class="token number">20</span><span class="token punctuation">,</span> y<span class="token operator">:</span> <span class="token number">40</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Create an empty object and assign its properties/values (key value pairs)</span><br /><span class="token keyword">let</span> someObj <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span><br />someObj<span class="token punctuation">.</span>prop1 <span class="token operator">=</span> <span class="token string">"hello"</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Create an object using the new keyword</span><br /><span class="token keyword">let</span> myObj <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />myObj<span class="token punctuation">.</span>foo <span class="token operator">=</span> <span class="token string">"bar"</span><span class="token punctuation">;</span></code></pre>
<p>We can also utilize <code>Object.create()</code> to create a new object from an existing object by using it as the prototype for our newly created object.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> Human <span class="token operator">=</span> <span class="token punctuation">{</span><br /> name<span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span><br /> isHungry<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br /> <span class="token function-variable function">about</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">My name is </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">. Am I hungry? </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>isHungry<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">const</span> tanner <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>Human<span class="token punctuation">)</span><span class="token punctuation">;</span><br />tanner<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"Tanner"</span><span class="token punctuation">;</span><br />tanner<span class="token punctuation">.</span>isHungry <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span><br />tanner<span class="token punctuation">.</span><span class="token function">about</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token comment">// My name is Tanner. Am I hungry? true</span></code></pre>
<p>You can create a normal empty object simply by using <code>Object.create({})</code>. If you need to create a <code>null</code> object instance, like <code>Object.create(null)</code>, keep in mind its not a normal object and won't have access to almost all expected methods like "generic" objects will. There seem to be some ways around this, but the most foolproof option is setting the generic prototype as the new <code>null</code> objects prototype with <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf"><code>setPrototypeOf</code></a>.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">let</span> oddball <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// a "null" object (not standard)</span><br />oddball<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Error! toString is not a function</span><br /><br /><span class="token comment">// Set the object instance to be a "generic" prototype</span><br />Object<span class="token punctuation">.</span><span class="token function">setPrototypeOf</span><span class="token punctuation">(</span>oddball<span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br />oddball<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [object Object]</span></code></pre>
<p>In Java and C++, we create the "template" for objects by using the <code>class</code> keyword as these are "class-based" languages, where we define the objects state (member variables) and behavior (methods). JavaScript does have a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes"><code>Class</code></a> reserved keyword for creating classes but it's usually best to use functions and prototypical objects to build out the inheritance chain like we would define a superclass and child classes in Java.</p>
<h3 class="post-heading">Anatomy of an Array</h3>
<p>In JavaScript, arrays can more closely resemble a Map with name/value pairs.</p>
<blockquote>
<p>Arrays are predefined objects, where its indexes are the properties.</p>
</blockquote>
<p>That means the first value of an array at index 0 would be displayed as <code>0: 15</code> where the 0th (first index) holds a value of 15. One of my favorite things about JavaScript arrays compared to other languages arrays (like Java) is the fact that JavaScript arrays can hold a collection of values with different data types and grow dynamically.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token string">"foo"</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> prop<span class="token operator">:</span> <span class="token string">"bar"</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 10 (Number)</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// "foo" (String)</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true (Boolean)</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Object { prop: "bar" }</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">.</span>prop<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// "bar" (access object properties)</span></code></pre>
<p>There are many <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures">data structures</a> in JavaScript and like shown above, arrays can hold any of the primitive types (undefined, String, Number, Boolean, BigInt, Symbol) and structural types.</p>
<blockquote>
<p>Note: In Java, a generic array can only hold values of the same data type and cannot grow dynamically. This is where an <a href="https://www.geeksforgeeks.org/arraylist-in-java/"><code>ArrayList</code></a> comes in handy because it's size can be dynamic and doesn't need to be "predefined" similar to arrays in JavaScript.</p>
</blockquote>
<h2 class="post-heading">How can I create an Array?</h2>
<p>There are a few ways to go about creating an <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a> in JavaScript.</p>
<p>You can create an empty array and then assign it's values:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br />arr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span><br />arr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span><br />arr<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">;</span><br /><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [1, 3, 5]</span></code></pre>
<p>Define the array inline:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">"foo"</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 1</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 2</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// "foo"</span></code></pre>
<p>Use the <code>new</code> keyword to create an Array object and then assign its indexes some values:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Array</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />arr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">"foo"</span><span class="token punctuation">;</span><br />arr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">"bar"</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// ["foo", "bar"]</span></code></pre>
<p>The indexes in an array are integer values, therefore you cannot use the dot operator <code>Object.property</code> to access values from the array and must use bracket notation <code>Object["property"]</code>. The indexes represent the property names for the array object itself so you should only use numeric index values to the array. If you add a non-numeric index to the array, it must be a string literal containing a number in the quotes. You may treat the array more like an object and use <code>arr["foo"] = "bar"</code> but the index "foo" will not be counted when calling <code>arr.length</code>.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">"foo"</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br />arr<span class="token punctuation">[</span><span class="token string">"3"</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">"bar"</span><span class="token punctuation">;</span><br />arr<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">"fuzz"</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [1, 2, "foo", "bar", "fuzz"]</span></code></pre>
<p>Because the property names for an array object are it's indexes, when we access or assign an index in the array using bracket notation like <code>arr[4]</code>, there is an implicit type coercion happening in the background to cast the value <code>4</code> which is a Number to type String.</p>
<h2 class="post-heading">Arrays are objects in JavaScript?</h2>
<p>You might be asking yourself, so are arrays objects in JavaScript? And the answer is <strong>yes</strong>. If you check with <code>typeof [1,2,3]</code> it will output <code>[object Array] (3)</code> verifying it is indeed an Array object. We discussed at the beginning of the article, arrays are predefined objects. It becomes very clear arrays are objects when we use the <code>length</code> property of an array like <code>arr.length</code> to return the length. The way we access the length property using dot notation is exactly the same as how we would access the property of any object like <code>Object.property</code>.</p>
<p>To further solidify that arrays are objects, the indexes in an array are the properties, so when we access a value such as <code>arr["2"]</code> we are accessing the <code>Object["2"]</code> value. The value stored at index 2 can be accessed from the array object by using the property <code>"2"</code>.</p>
<p>One last interesting note about arrays involves <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length"><code>Array.prototype.length</code></a>, which is essentially <code>Object.length</code>. When you have used the <code>length</code> property to count the number of values in an array, you might think it is counting each index that has a value. This is actually not the case. The length property returns the greatest number value index and increments it by one (due to 0-base indexing). Some people might look at this as a flaw, but I think it's a good way for us as developers to define arrays with logical and sequential numeric indexes to make sure when we use <code>Object.length</code> it returns the expected array length.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br />arr<span class="token punctuation">[</span><span class="token number">7</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">4</span><span class="token punctuation">;</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [1, 2, 3, undefined, undefined, undefined, undefined, 4]</span><br />console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 8</span></code></pre>
<p>You might think the above array <code>arr</code> would have a length of 4. But it actually has a length of 8. This is because the <code>arr.length</code> call returns the highest index in the array (7) and increments it by one (7+1=8). The way this works is that since the indexes <code>arr[3]-arr[6]</code> were not provided values, they are simply filled with <code>undefined</code>.</p>
Using Git for Contributing to Open Source2020-12-27T00:00:00Zhttps://tannerdolby.com/writing/using-git-for-contributing-to-open-source/<p>To begin contributing to open-source software, you might want to become familiar with Git. Understanding the workflow of creating your own local copy of a repository and keeping it up to date with the upstream repository is integral to start contributing in public projects.</p>
<p><a href="https://git-scm.com/">Git</a> is a distributed version control system (DVCS) that can handle just about any size project you throw at it. The software is blazing fast and is now something I use everyday while contributing to projects on GitHub.</p>
<h2 class="post-heading">Local Setup</h2>
<p>Before you can start submitting a Pull Request (PR) to a public repository, you will usually want to copy the project files to your local system. This can be done by performing a <code>git clone</code> on a forked public repository from GitHub. Before cloning, you need to create your own local copy by forking it. Then you can setup your upstream repository (e.g. the repo you forked from) and any other branch or environment setup.</p>
<h2 class="post-heading">Fork</h2>
<p>To create a local copy of a repository, use the <code>Fork</code> button in the top right corner of the public repository webpage on GitHub. After forking a repository, the project will be part of your users account as <code>your-username/repository-name</code>.</p>
<h2 class="post-heading">Clone your fork</h2>
<p>Copy the SSH URL (or HTTPS) of your own organization’s fork of the project and then clone the project. The URL can be found by clicking the large green button on GitHub that says "Code". Below is an example of my GitHub account (<a href="https://github.com/tannerdolby">@tannerdolby</a>) cloning my fork of <a href="https://github.com/11ty/11ty-website">11ty/11ty-website</a>.</p>
<pre class="language-git"><code class="language-git">git clone git@github.com:tannerdolby/11ty-website.git</code></pre>
<h2 class="post-heading">Setup tracking of remote upstream repository</h2>
<p>To make sure your local copy of the project (the fork) is up to date with the original upstream repository. Grab the <code>.git</code> SSH/HTTPS URL from the original repository <a href="https://github.com/11ty/11ty-website">11ty/11ty-website</a>. This URL will have the original project organization name followed by the repository like <code>11ty/11ty-website</code>.</p>
<p>Add the upstream repository as a remote:</p>
<pre class="language-git"><code class="language-git">git remote add upstream git@github.com:11ty/11ty-website.git</code></pre>
<p>Point your local copy of the master branch (which is currently pointing to 'origin') to the upstream repository. Once completed, you can easily pull changes from 'master' and get the latest changes from the upstream repository. If the upstream repository doesn't use the default <code>master</code> branch and uses another branch such as <code>main</code>. Just make sure to update the following Git command to reflect that.</p>
<pre class="language-git"><code class="language-git">git branch --set-upstream-to=upstream/master master</code></pre>
<p>To get details about the upstream remote repository, you can use <code>git fetch</code>. This will display a list of all the branches referenced in the upstream repository.</p>
<pre class="language-git"><code class="language-git">git fetch upstream<br /><br />From github.com:11ty/11ty-website<br /> 834b9589..0ae7bf64 master -> upstream/master<br /> * [new branch] opencollective-update-opencollective-integration -> upstream/opencollective-update-opencollective-integration<br /> e8fed377..70951217 production-dev -> upstream/production-dev</code></pre>
<h2 class="post-heading">Stay up to date</h2>
<p>Let's say a contributor submitted a pull request to fix a bug in your project. You review the PR and decide to approve the changes and merge them into the <code>master</code> branch (or whatever branch your working on). Now your <code>origin/master</code> is "behind" by the remote <code>master</code> by 'X' commits depending on the number of commits in the merged PR.</p>
<p>To remedy this, you just need to "sync" with the remote repository to make sure your local project is up-to-date and has the newly added changes. In Git, <code>origin</code> is a shorthand name for the remote repository where you want to publish commits.</p>
<p>Once you <a href="https://git-scm.com/docs/git-pull">pull</a> on the <code>master</code> branch and get those changes, your project <code>origin/master</code> will be "even" with remote <code>master</code> and the message of "ahead/behind by 'X' commits" will have gone away.</p>
<pre class="language-git"><code class="language-git">git pull origin master</code></pre>
<p>If you need to stay up to date with some branch in a public remote repository, simply use <code>upstream</code> instead of <code>origin</code> and you can use the same syntax to pull on the branch and get the changes.</p>
<pre class="language-git"><code class="language-git">git pull upstream <BRANCHNAME></code></pre>
<p>Note: Using <code>git fetch upstream</code> is always helpful to use before pulling on branches in a public repository to sync with the latest changes.</p>
<h2 class="post-heading">Making changes</h2>
<p>Now that your local copy of the project is all setup to track changes from the upstream repository, it's time to start making changes. Once you have modified files within your local copy of the project, the source tree will track those changes and put them in something called the "Staging Area".</p>
<p>When file changes are recoginized in the staging area, you can perform <code>git add <filename></code> to "stage" those changes to then commit and push the changes into the upstream repository.</p>
<p>To display the status of your source tree, run the <code>git status</code> command.</p>
<pre class="language-git"><code class="language-git"><span class="token command">tannerdolby:11ty-portfolio TannerDolby$ git status</span><br />On branch master<br />Your branch is up to date with <span class="token string">'origin/master'</span>.<br /><br />Changes not staged for commit:<br /> (use <span class="token string">"git add/rm <file>..."</span> to update what will be committed)<br /> (use <span class="token string">"git checkout -- <file>..."</span> to discard changes in working directory)<br /><br /> modified: src/writing/node-list.md</code></pre>
<p>Add the modified file to the staging area:</p>
<pre class="language-git"><code class="language-git">git add src/writing/node-list.md</code></pre>
<p>When you add the file changes to the staging area (ie stage changes). The <code>git status</code> command will look like this:</p>
<pre class="language-git"><code class="language-git"><span class="token command">tannerdolby:11ty-portfolio TannerDolby$ git status</span><br />On branch master<br />Your branch is up to date with <span class="token string">'origin/master'</span>.<br /><br />Changes to be committed:<br /> (use <span class="token string">"git reset HEAD <file>..."</span> to unstage)<br /><br /> modified: src/writing/node-list.md</code></pre>
<p>Now that the modified files have been staged, it's time to commit those changes and push.</p>
<pre class="language-git"><code class="language-git">git commit -m <span class="token string">"commit message"</span></code></pre>
<h2 class="post-heading">Pushing changes upstream</h2>
<p>With the changes committed, you are now ready to push those changes into the project. Using <code>git push</code> ensures that the file modifications that were apart of your commits are included in the up-to-date project. To understand the Git command below. The <code>-u</code> is shorthand for <code>--set-upstream</code>. The full syntax for using the push command is: <code>git push <local-branch> <upstream-branch></code></p>
<pre class="language-git"><code class="language-git">git push -u origin master</code></pre>
<h2 class="post-heading">Creating a Pull Request</h2>
<p>Once you have pushed your commits upstream, you can open a Pull Request (PR). A pull request is essentially a way of asking the project maintainer to review your changes and merge them into the original project. After you push your commits, you can head over to the original repository on GitHub and open a new PR.</p>
<p>Click on the Pull Requests tab and then "Compare across forks", make sure that you compare with the branch you've pushed from. Sometimes, it will take a few minutes for the PR to appear in the "Pull Requests" tab in the original repo.</p>
<p>Once you create a PR, you will be asked to provide a title for it and a description. I typically just add a descriptive title for what changes I made and a short description, unless I need to ask the maintainer about more specific details.</p>
<pre class="language-git"><code class="language-git">Title: Fix failing unit tests for direct links<br /><br />Desc: Fixes #855</code></pre>
<p>The above code snippet is an example of what title and description I would typically use for submitting a PR. The <code>#855</code> is a issue number that the PR would potentially fix, if the PR doesn't directly fix a current issue, then simply describe your PR with a short description.</p>
<p>Ignore the "Title:" and "Desc:" as I only included those only as a helpful reminder of what you will see on GitHub.</p>
<p>After you submit the PR, you have sucessfully completed creating and submitting a pull request. Congrats! Now all you can do is wait to hear back from the project maintainer. If the PR needs changes, the maintainer will "Request Changes". If not, your PR will be sucessfully merged into the project. This might seem like quite the process, but these are the necessary steps to becoming comfortable with contributing to open-source software.</p>
Add Search to a Static Site Using Custom Data Attributes2020-12-18T00:00:00Zhttps://tannerdolby.com/writing/add-search-to-a-static-site-using-custom-data-attributes/<p>Creating search functionality for a static site isn't always easy. Luckily, using custom data attributes and a bit of JavaScript. You can filter blog posts by comparing the search input to post titles and visually hide posts that don't match the search query.</p>
<p>The blog post titles will be stored in a custom <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes">data attribute</a> <code>data-post-title</code> to be compared with the user input from the search bar. Using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event">input event</a>, we can compare the <code><input></code> elements value with blog post titles in the data attribute everytime the search bar changes.</p>
<p>This way the user input inside the search bar (ie search query) will be checked against each blog post title for every character that is added or removed to the search. The "dynamic" search feel is made possible thanks to the <code>input</code> event. Below is the HTML for creating a search bar <code><input></code> and corresponding <code><label></code>.</p>
<div class="filename-title"><span>Filename</span>: <em>index.html</em></div>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search-bar<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Search the Blog<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search-bar<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>search<span class="token punctuation">"</span></span> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Search...<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /><span class="token comment"><!-- Blog post --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>article</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>post<span class="token punctuation">"</span></span> <span class="token attr-name">data-post-title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Blog Post<span class="token punctuation">"</span></span> <span class="token attr-name">data-post-tags</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>[<span class="token punctuation">'</span>eleventy<span class="token punctuation">'</span>, <span class="token punctuation">'</span>ssg<span class="token punctuation">'</span>]<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>..<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>article</span><span class="token punctuation">></span></span></code></pre>
<p>Blog post titles in the custom data attribute <code>data-post-title</code> can be accessed from the DOM via <code>HTMLElement.dataset.postTitle</code> (keep in mind the stuff after the asterisk in <code>data-*</code> which is hyphen separated will be camelCased). We can also access the tags array for a post by using <code>HTMLElement.dataset.postTags</code>.</p>
<p>After checking the search query against post titles and post tags, we can then visually hide the posts with titles and/or tags not matching the search query. I'm using a <code>sr-only</code> class and <code>aria-hidden="true"</code> attribute to visually hide non-matching posts from the document and accessibility API.</p>
<div class="filename-title"><span>Filename</span>: <em>style.css</em></div>
<pre class="language-css"><code class="language-css"><span class="token selector">.sr-only</span> <span class="token punctuation">{</span><br /> <span class="token property">clip</span><span class="token punctuation">:</span> <span class="token function">rect</span><span class="token punctuation">(</span>0 0 0 0<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">clip-path</span><span class="token punctuation">:</span> <span class="token function">inset</span><span class="token punctuation">(</span>50%<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">height</span><span class="token punctuation">:</span> 1px<span class="token punctuation">;</span><br /> <span class="token property">overflow</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span><br /> <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span><br /> <span class="token property">white-space</span><span class="token punctuation">:</span> nowrap<span class="token punctuation">;</span><br /> <span class="token property">width</span><span class="token punctuation">:</span> 1px<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Note: Using a service like <a href="https://www.algolia.com/">Algolia</a> will provide a more rich search functionality with all the bells and whistles. But if your search needs are minimal (like mine) this implementation could work great for you.</p>
<h2 class="post-heading">Creating the Search</h2>
<p>First, we need a client-side script <code>search.js</code> to grab all the blog posts from the document and store them in the variable <code>posts</code>. You can do this by using the <code>getElementsByClassName</code> method of the <code>Document</code> interface, which returns a live HTMLCollection.</p>
<p>You can now iterate over the items in the <code>posts</code> collection and compare the search query with each data attribute, <code>data-post-title="Some blog post"</code>.</p>
<p>If a post title matches the consecutive characters entered into the <code><input></code> element then visually hide the non-matching posts by adding the <code>.sr-only</code> class. Since the <code>input</code> event fires everytime the search bar text changes, we can compare the query with post titles for each change to the search input.</p>
<p>I'm using an Eleventy Collection to loop over all the posts in my blog and generate <code><article></code> elements. If you're not using a templating language or Eleventy, feel free to omit the Nunjucks <code>{% for %}</code> loop.</p>
<p>Here is the full code snippet for adding search functionality to your static site.</p>
<div class="filename-title"><span>Filename</span>: <em>index.html</em></div>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ul</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>my-posts<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br />{% for post in collections.posts | reverse %}<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>li</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>article</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>post<span class="token punctuation">"</span></span> <span class="token attr-name">data-post-title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>{{ post.data.title }}<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>{{ post.url }}<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>{{ post.data.title }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span>Some preview text<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>article</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>li</span><span class="token punctuation">></span></span><br />{% endfor %}<br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ul</span><span class="token punctuation">></span></span></code></pre>
<div class="filename-title"><span>Filename</span>: <em>search.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token comment">// grab blog posts and convert HTMLCollection to Array with the spread operator</span><br /><span class="token keyword">const</span> posts <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">...</span>document<span class="token punctuation">.</span><span class="token function">getElementsByClassName</span><span class="token punctuation">(</span><span class="token string">"post"</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> searchBar <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"#search-bar"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">function</span> <span class="token function">getInput</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br />searchBar<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">"input"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">let</span> userInput <span class="token operator">=</span> <span class="token function">getInput</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">let</span> searchQuery <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /><br /> searchQuery<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>userInput<span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">const</span> matchingPost <span class="token operator">=</span> posts<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">post</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> title <span class="token operator">=</span> post<span class="token punctuation">.</span>dataset<span class="token punctuation">.</span>postTitle<span class="token punctuation">;</span><br /> <span class="token keyword">const</span> tags <span class="token operator">=</span> post<span class="token punctuation">.</span>dataset<span class="token punctuation">.</span>tags<span class="token punctuation">;</span><br /> <span class="token keyword">return</span> title<span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>searchQuery<span class="token punctuation">)</span> <span class="token operator">||</span> tags<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>searchQuery<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">const</span> nonMatchingPost <span class="token operator">=</span> posts<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">post</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token operator">!</span>post<span class="token punctuation">.</span>dataset<span class="token punctuation">.</span>postTitle<span class="token punctuation">.</span><span class="token function">toLowerCase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>searchQuery<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token comment">// if there is a matching post then visually hide non-matching posts</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>matchingPost<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> nonMatchingPost<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">post</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> post<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"sr-only"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> post<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"aria-hidden"</span><span class="token punctuation">,</span> <span class="token string">"true"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><br /> <span class="token comment">/* if the matching post is hidden from a previous query <br /> and matches search query, show it */</span><br /> matchingPost<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">post</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>post<span class="token punctuation">.</span>classList<span class="token punctuation">.</span>value<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">"sr-only"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> post<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token string">"sr-only"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> post<span class="token punctuation">.</span><span class="token function">removeAttribute</span><span class="token punctuation">(</span><span class="token string">"aria-hidden"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 class="post-heading">Conclusion</h2>
<p>I'm using this functionality for my websites <a href="https://tannerdolby.com/search/">search feature</a> if you wanna see it in action. I would like to improve upon this by adding more data attributes to allow the search query to compare text in the blog posts preview or other data. Potentially introducing weights for search queries where if the title and preview text both contain a match, then the logic will place title matches higher than preview text. Thanks for reading. Stay tuned!</p>
Create Objects From an Array of Key and Value like Strings2020-12-06T00:00:00Zhttps://tannerdolby.com/writing/create-objects-from-an-array-of-key-and-value-like-strings/<p>Have you ever had an array of values that you needed to convert to an object? I've run into this scenario quite a few times and wanted to write about it.</p>
<p>While working on the <a href="https://adventofcode.com/2020/day/4">Day 4</a> challenge for this years <a href="https://adventofcode.com/2020/">Advent of Code</a>. I came across the need to transform a large string of key and value like inputs from the challenges input data. To give a little bit of context, the Day 4 challenge provided passport input data and asked us to verify whether each passport had the <em>required</em> fields. The data looked like this:</p>
<div class="filename-title"><span>Filename</span>: <em>input.txt</em></div>
<pre class="language-text"><code class="language-text">ecl:#eef340 eyr:2023 hcl:#c0946f pid:244684338 iyr:2020 cid:57 byr:1969 hgt:152cm<br /><br />pid:303807545 cid:213 ecl:gry hcl:#fffffd<br />eyr:2038 byr:1951<br />hgt:171cm iyr:2011</code></pre>
<p>Where each piece of passport data is separated by empty space newlines (<code>\n</code>). The input file contained 257 entries, but I only showed a few for readability. Some of the data is formatted all in one line where others span multiple lines but ultimately each entry is separated by the empty space new line.</p>
<h2 class="post-heading">Formatting Input Data</h2>
<p>If your input data is in need of transformation, to format the string into a single line. The following steps may prove useful to you. To start handling a large <code>.txt</code> file like the file shown above, <code>input.txt</code>. Start by creating a template literal by wrapping the input text in opening and closing backticks.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> input <span class="token operator">=</span> <br /><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">ecl:#eef340 eyr:2023 hcl:#c0946f pid:244684338 iyr:2020 cid:57 byr:1969 hgt:152cm<br /><br />pid:303807545 cid:213 ecl:gry hcl:#fffffd<br />eyr:2038 byr:1951<br />hgt:171cm iyr:2011</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span></code></pre>
<p>Now since the input is a <code>String</code> data type, we have access to <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split"><code>String.prototype.split</code></a>. Therefore, it's going to be much easier to put the data from the text file into a data structure, such as an <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array"><code>Array</code></a> for manipulation.</p>
<div class="filename-title"><span>Filename</span>: <em>passports.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> passportData <span class="token operator">=</span> input<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">"\n\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Using <code>.split("\n\n")</code> is the best method for transforming the input data in <code>input.txt</code>. This way, each passports data is stored as an array of passport strings. The multi-line entries still contain <code>\n</code> entities so the formatting work is not yet complete.</p>
<pre class="language-js"><code class="language-js"><span class="token number">0</span><span class="token operator">:</span> <span class="token string">"ecl:#eef340 eyr:2023 hcl:#c0946f pid:244684338 iyr:2020 cid:57 byr:1969 hgt:152cm"</span><br /><span class="token number">1</span><span class="token operator">:</span> <span class="token string">"pid:303807545 cid:213 ecl:gry hcl:#fffffd↵eyr:2038 byr:1951↵hgt:171cm iyr:2011"</span><br /><span class="token number">2</span><span class="token operator">:</span> <span class="token string">"hcl:#c0946f byr:1933 eyr:2025 pid:517067213 hgt:173cm↵ecl:hzl↵iyr:2018"</span></code></pre>
<p>Since not all the values in the input data were single line entries, they still contain a <code>↵</code> which is equivalent to the <code>Enter</code> key or more commonly, a newline <code>\n</code>. To handle this last formatting task, I thought it would be best to use <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map"><code>Array.prototype.map</code></a> since the underlying data structure is an array after using <code>split</code>. Then we can join together the array of strings using <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join"><code>Array.prototype.join</code></a> and leave an empty space between each string in the array.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> passportData <span class="token operator">=</span> input<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">"\n\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> cleanData <span class="token operator">=</span> passportData<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">p</span> <span class="token operator">=></span> p<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">"\n"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">" "</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Now all the formatting is done and all passport data is stored as an array of single line strings containing key/value like data.</p>
<pre class="language-js"><code class="language-js"><span class="token number">0</span><span class="token operator">:</span> <span class="token string">"ecl:#eef340 eyr:2023 hcl:#c0946f pid:244684338 iyr:2020 cid:57 byr:1969 hgt:152cm"</span><br /><span class="token number">1</span><span class="token operator">:</span> <span class="token string">"pid:303807545 cid:213 ecl:gry hcl:#fffffd eyr:2038 byr:1951 hgt:171cm iyr:2011"</span><br /><span class="token number">2</span><span class="token operator">:</span> <span class="token string">"hcl:#c0946f byr:1933 eyr:2025 pid:517067213 hgt:173cm ecl:hzl iyr:2018"</span></code></pre>
<h2 class="post-heading">Convert an array of strings to an object</h2>
<p>I created a helper function to handle the converting. It accepts one parameter, a string, or an array of strings and splits the incoming string by a colon <code>:</code>. Then using a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of"><code>for..of</code></a> statement it's quite straightforward to assign the key and value chunks to variables. The utility function looks like this:</p>
<div class="filename-title"><span>Filename</span>: <em>script.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">convertToObj</span><span class="token punctuation">(</span><span class="token parameter">arr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span><br /> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">const</span> s <span class="token keyword">of</span> arr<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> data <span class="token operator">=</span> s<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">":"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">let</span> key <span class="token operator">=</span> data<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span><br /> <span class="token keyword">let</span> value <span class="token operator">=</span> data<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> obj<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> value<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token keyword">return</span> obj<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>The function could use some testing and refined logic to handle more use-cases, but to demonstrate how the utility works for an array of strings:</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> converted <span class="token operator">=</span> <span class="token function">convertToObj</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">"key1: red"</span><span class="token punctuation">,</span> <span class="token string">"key2: yellow"</span><span class="token punctuation">,</span> <span class="token string">"key3: purple"</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>The output of <code>console.log(converted)</code> would be:</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">{</span><br /> key1<span class="token operator">:</span> <span class="token string">"red"</span><span class="token punctuation">,</span> <br /> key2<span class="token operator">:</span> <span class="token string">"yellow"</span><span class="token punctuation">,</span> <br /> key3<span class="token operator">:</span> <span class="token string">"purple"</span><br /><span class="token punctuation">}</span></code></pre>
<p>In order to utilize the full potential of this helper function (specifically for the Day 4 challenge). We can use another <code>for..of</code> loop to invoke <code>converToObj</code> for each passport string in the array of strings from our formatted data.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> passportData <span class="token operator">=</span> input<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">"\n\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> cleanData <span class="token operator">=</span> passportData<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">p</span> <span class="token operator">=></span> p<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">"\n"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">" "</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">for</span> <span class="token punctuation">(</span>str <span class="token keyword">of</span> cleanData<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> inputs <span class="token operator">=</span> str<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">" "</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> data <span class="token operator">=</span> <span class="token function">convertToDict</span><span class="token punctuation">(</span>inputs<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">isValid</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 206 valid passports :)</span><br /><span class="token punctuation">}</span></code></pre>
<p>The output of <code>data</code> would be each passport string converted to a well defined object.</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">{</span>ecl<span class="token operator">:</span> <span class="token string">"#eef340"</span><span class="token punctuation">,</span> eyr<span class="token operator">:</span> <span class="token string">"2023"</span><span class="token punctuation">,</span> hcl<span class="token operator">:</span> <span class="token string">"#c0946f"</span><span class="token punctuation">,</span> pid<span class="token operator">:</span> <span class="token string">"244684338"</span><span class="token punctuation">,</span> iyr<span class="token operator">:</span> <span class="token string">"2020"</span><span class="token punctuation">,</span> …<span class="token punctuation">}</span><br /><span class="token punctuation">{</span>pid<span class="token operator">:</span> <span class="token string">"303807545"</span><span class="token punctuation">,</span> cid<span class="token operator">:</span> <span class="token string">"213"</span><span class="token punctuation">,</span> ecl<span class="token operator">:</span> <span class="token string">"gry"</span><span class="token punctuation">,</span> hcl<span class="token operator">:</span> <span class="token string">"#fffffd"</span><span class="token punctuation">,</span> eyr<span class="token operator">:</span> <span class="token string">"2038"</span><span class="token punctuation">,</span> …<span class="token punctuation">}</span><br /><span class="token punctuation">{</span>hcl<span class="token operator">:</span> <span class="token string">"#c0946f"</span><span class="token punctuation">,</span> byr<span class="token operator">:</span> <span class="token string">"1933"</span><span class="token punctuation">,</span> eyr<span class="token operator">:</span> <span class="token string">"2025"</span><span class="token punctuation">,</span> pid<span class="token operator">:</span> <span class="token string">"517067213"</span><span class="token punctuation">,</span> hgt<span class="token operator">:</span> <span class="token string">"173cm"</span><span class="token punctuation">,</span> …<span class="token punctuation">}</span></code></pre>
<p>To finish solving Day 4 part one, I wrote an <code>isValid</code> function to check each of the required passport fields.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">isValid</span><span class="token punctuation">(</span><span class="token parameter">obj</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">var</span> byr <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">"byr"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">var</span> iyr <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">"iyr"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">var</span> eyr <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">"eyr"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">var</span> hcl <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">"hcl"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">var</span> ecl <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">"ecl"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">var</span> hgt <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">"hgt"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">var</span> pid <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">"pid"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">return</span> byr <span class="token operator">&&</span> iyr <span class="token operator">&&</span> eyr <span class="token operator">&&</span> hcl <span class="token operator">&&</span> ecl <span class="token operator">&&</span> hgt <span class="token operator">&&</span> pid <span class="token operator">?</span> obj <span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Well! I may have talked about many things in this article, but hopefully the helper function for converting key and value like strings to a well defined object was clear. This article will also help you to solve part one of the Advent of Code Day 4 challenge. The source code for this can be found at <a href="https://github.com/tannerdolby/advent-of-code/blob/master/js/day-four.js">tannerdolby/advent-of-code</a> on GitHub.</p>
Create a Custom Collection with Eleventy2020-10-31T00:00:00Zhttps://tannerdolby.com/writing/create-a-custom-collection-with-eleventy/<p>If you've built sites using Eleventy before, you're probably familiar with <a href="https://www.11ty.dev/docs/collections/">collections</a>. Collections are a great feature to show blog posts on your site. If your posts are written inside of markdown files, you can give each post the <code>tags</code> key as front matter data to create a collection.</p>
<p>Front matter in 11ty is placed inside opening and closing document separators <code>---</code> and uses YAML syntax. Two markdown files <code>post-one.md</code> and <code>post-two.md</code> will be the blog posts contained in the <code>posts</code> collection.</p>
<div class="filename-title"><span>Filename</span>: <em>post-one.md</em></div>
<pre class="language-yaml"><code class="language-yaml"><span class="token punctuation">---</span><br /><span class="token key atrule">title</span><span class="token punctuation">:</span> Blog post one<br /><span class="token key atrule">permalink</span><span class="token punctuation">:</span> <span class="token string">"/posts/{{ title | slug }}"</span><br /><span class="token key atrule">tags</span><span class="token punctuation">:</span> posts<br /><span class="token punctuation">---</span><br />Some content in post one</code></pre>
<div class="filename-title"><span>Filename</span>: <em>post-two.md</em></div>
<pre class="language-yaml"><code class="language-yaml"><span class="token punctuation">---</span><br /><span class="token key atrule">title</span><span class="token punctuation">:</span> Blog post two<br /><span class="token key atrule">permalink</span><span class="token punctuation">:</span> <span class="token string">"/posts/{{ title | slug }}"</span><br /><span class="token key atrule">tags</span><span class="token punctuation">:</span> posts<br /><span class="token punctuation">---</span><br />Some content in post two</code></pre>
<p>You might have noticed a <code>permalink</code> key in the front matter data. Eleventy's <a href="https://www.11ty.dev/docs/permalinks/">permalink</a> does some cool stuff to make sure that "Cool URIs don't change". You can use the <code>permalink</code> key to remap a templates output to a path other than the default <code>inputPath</code>. The output from setting a <code>permalink</code> will leave off the file extension.</p>
<p>The two markdown files would be written to the <code>_site</code> output as:</p>
<pre class="language-html"><code class="language-html">/posts/blog-post-one/<br />/posts/blog-post-two/</code></pre>
<p>Using the <code>slug</code> filter works nicely to slugify your posts <code>title</code> key. The above permalink could also be written as <code>permalink: "/posts/blog-post-two/"</code> if you wanted to manually write the equivalent of <code>{{ title | slug }}</code>.</p>
<h2 class="post-heading">Accessing Collection Data</h2>
<p>Now that both of the blog posts have been given the <code>posts</code> tag. They can be easily accessed from the <code>posts</code> collection in the following way using a Nunjucks <code>for</code> loop.</p>
<pre class="language-html"><code class="language-html">{% for post in collections.posts %}<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>{{ page.url }}<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>{{ post.data.title }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><br />{% endfor %}</code></pre>
<p>This would iterate over the <code>posts</code> collection and access the front matter data <code>title</code> to create a link to each blog post.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/posts/blog-post-one/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Blog post one<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/posts/blog-post-two/<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Blog post two<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span></code></pre>
<p>If you wanted to show the markdown from blog posts in another template or layout file, you can use <code>{{ content | safe }}</code>.</p>
<h2 class="post-heading" id="handling-multiple-tags">Handling multiple tags</h2>
<p>One way to create a new collection is simply by giving a <code>.md</code> file a new tag within the <code>tags</code> key. This method has been demonstrated above to access the <code>posts</code> collection.</p>
<p>When you have multiple tags on a blog post, such as <code>html</code>, <code>css</code>, <code>js</code>. You will add each tag to the <code>tags</code> key as a list of values.</p>
<pre class="language-yaml"><code class="language-yaml"><span class="token punctuation">---</span><br /><span class="token key atrule">tags</span><span class="token punctuation">:</span> <br /> <span class="token punctuation">-</span> html<br /> <span class="token punctuation">-</span> css<br /> <span class="token punctuation">-</span> js<br /><span class="token punctuation">---</span></code></pre>
<p>This is where creating a <a href="https://www.11ty.dev/docs/collections/">custom collection</a> comes in handy. Instead of including the <code>posts</code> tag in the <code>tags</code> list for every blog post (which might be repetitive), just create a custom collection with the markdown files from <code>/posts/</code> inside the <code>.eleventy.js</code> file. This way you can omit <code>posts</code> from the tags list within front matter data.</p>
<h2 class="post-heading">Create Custom Collections</h2>
<p>All blog posts in this article are saved as <code>.md</code> files in the <code>/posts/</code> directory. To create a custom collection, navigate to <code>.eleventy.js</code>. You will utilize the first argument of the config function <code>eleventyConfig</code> to call the API and use <code>addCollection</code> to create a new custom collection.</p>
<p>You can add the markdown files within <code>/posts/</code> to the new collection using <code>getFilteredByGlob(glob)</code>, which will match an arbitrary glob or array of globs against the input file's full path (<code>inputPath</code>).</p>
<div class="filename-title"><span>Filename</span>: <em>.eleventy.js</em></div>
<pre class="language-js"><code class="language-js">module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">eleventyConfig</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// Creates custom collection "myPosts"</span><br /> eleventyConfig<span class="token punctuation">.</span><span class="token function">addCollection</span><span class="token punctuation">(</span><span class="token string">"myPosts"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">collection</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> collection<span class="token punctuation">.</span><span class="token function">getFilteredByGlob</span><span class="token punctuation">(</span><span class="token string">"/posts/*.md"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Now a custom collection called <code>myPosts</code> has been created which contains all the markdown files in <code>/posts/</code>. You can access this custom collection just like a regular collection.</p>
<pre class="language-html"><code class="language-html">{% for article in collections.myPosts %}<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h2</span><span class="token punctuation">></span></span>{{ article.data.title }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h2</span><span class="token punctuation">></span></span><br />{% endfor %}</code></pre>
<p>Another useful method is <code>getFilteredByTags(tags)</code> which will retrieve any content that includes all of the tags passed in.</p>
<pre class="language-js"><code class="language-js">eleventyConfig<span class="token punctuation">.</span><span class="token function">addCollection</span><span class="token punctuation">(</span><span class="token string">"web"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">collection</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> collection<span class="token punctuation">.</span><span class="token function">getFilteredByTags</span><span class="token punctuation">(</span><span class="token string">"html"</span><span class="token punctuation">,</span> <span class="token string">"css"</span><span class="token punctuation">,</span> <span class="token string">"js"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 class="post-heading">Filter Recent Posts</h2>
<p>If you wanted to dedicate a section of the page for some of your most recent blog posts. You could create a custom sorted collection and perform a <code>slice</code> array operation to filter the number of recent posts.</p>
<pre class="language-js"><code class="language-js">eleventyConfig<span class="token punctuation">.</span><span class="token function">addCollection</span><span class="token punctuation">(</span><span class="token string">"recentPosts"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">collection</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> collection<span class="token punctuation">.</span><span class="token function">getAllSorted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">reverse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /></code></pre>
<h2 class="post-heading">Conclusion</h2>
<p>Custom collections along with the ability to build powerful shortcodes and filters in <code>.eleventy.js</code> using the <a href="https://www.11ty.dev/docs/config/">configuration API</a> is one of the main reasons why <a href="https://tannerdolby.com/writing/?filter=eleventy">#eleventy</a> rocks!</p>
An Introduction to Client-side JavaScript2020-10-06T00:00:00Zhttps://tannerdolby.com/writing/an-introduction-to-client-side-javascript/<p>Have you ever thought to yourself while building a website, how could I create HTML elements and bind them to the DOM? This article explains some of the fundamentals for interacting with the DOM tree using client-side JavaScript.</p>
<p>Maybe you've been tasked with writing a function that creates multiple <code><li></code> list elements. If you wanted to programmaticlly set attributes and apply styles, this is where the power client-side JavaScript really shines!</p>
<p>Client-side means that the JavaScript code is run on the client machine, which is the browser. Server-side JavaScript means that the code is run on the server which is serving web pages.</p>
<h2 class="post-heading">This post will aim to cover:</h2>
<ol>
<li>Virtually creating HTML elements in JavaScript</li>
<li>Creating and setting attributes to HTML DOM elements</li>
<li>Binding the created HTML elements to the DOM</li>
</ol>
<h2 class="post-heading">What is JavaScript?</h2>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript">JavaScript</a> is a lightweight, interpreted, compiled programming language with first class functions. While it is most well-known as the scripting language for Web pages, many non-browser environments also use it, such as Node.js, Apache CouchDB and Adobe Acrobat.</p>
<h2 class="post-heading">Why read this article?</h2>
<p>If you're like me, I was (for some reason) afraid of learning to code in JavaScript at first. We just didn't get along. Then I stumbled upon this video titled: <a href="https://www.youtube.com/watch?time_continue=4&v=HnXmI2UVZlU&feature=emb_logo">This is truly the only way to learn JavaScript</a> by Chris Hawkes.</p>
<p>After watching the video, I was captivated by the fact you could virtually create HTML DOM elements in JavaScript. This essentially took out all the need to ever go into my <code>.html</code> files, hypothetically speaking. Other than to include a <code>script</code> element for referencing the client side JavaScript containing all of the virtually created DOM elements.</p>
<h2 class="post-heading">So where does HTML fit into the picture?</h2>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/HTML">HTML</a> or HyperText Markup Language is the most rudimentary building block in web development. Using HTML allows developers to define the meaning and structure of web content through semantic HTML DOM elements.</p>
<h2 class="post-heading">What is the DOM?</h2>
<p>From <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction">MDN</a>, The Document Object Model (DOM) is the data representation of the objects that comprise the structure and content of a document on the web. The DOM represents the HTML or XML document so that programming languages can easily connect to the page. Think of the DOM as a large tree like structure with the <code>document</code> (root node) at the top of the tree with the <code><html></code> (root element) on the next branch and the rest of the HTML elements to follow.</p>
<h2 class="post-heading">Build the DOM Tree</h2>
<p>JavaScript allows for virtually creating HTML elements using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document">Document</a> interface and associated <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document#Methods">methods</a>. Below is an example of virtually creating a new <code><div></code> element using <code>createElement()</code> and attaching it to the DOM tree within the <code><body></code> node of the current document.</p>
<div class="filename-title"><span>Filename</span>: <em>script.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> div <span class="token operator">=</span> document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"div"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h2 class="post-heading">Creating HTML attributes</h2>
<p>After virtually creating HTML elements with JavaScript, you can add and remove attributes from them. The <code>Document</code> interface provides a method called <code>createAttribute()</code> to create HTML element attributes.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">var</span> div_att <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createAttribute</span><span class="token punctuation">(</span><span class="token string">"class"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />div_att<span class="token punctuation">.</span>value <span class="token operator">=</span> <span class="token string">"page-content"</span><span class="token punctuation">;</span></code></pre>
<p>This creates a <code>class</code> attribute and assigns it the value "page-content", ie <code>class="page-content"</code>.</p>
<h2 class="post-heading">Injecting and Setting Element Attributes</h2>
<p>Up until this point, we have virtually created HTML elements using <code>createElement()</code> and gave those elements some attributes using <code>createAttribute()</code>. Now it's time to inject values into the attributes and set their values using the <code>setAttributeNode()</code> method. Putting all the previous steps together:</p>
<ol>
<li>Create the HTML div element.</li>
<li>Create class attribute for the newly created element.</li>
<li>Inject the class attribute value with the text "page-content".</li>
<li>Set the injected attribute values for DOM elements.</li>
</ol>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> div <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'div'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> div_class <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createAttribute</span><span class="token punctuation">(</span><span class="token string">"class"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />div_class<span class="token punctuation">.</span>value <span class="token operator">=</span> <span class="token string">"page-content"</span><span class="token punctuation">;</span><br />div<span class="token punctuation">.</span><span class="token function">setAttributeNode</span><span class="token punctuation">(</span>div_class<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3 id="quickly-set-attr" class="post-heading">Create and set attributes more efficiently</h3>
<p>The faster way to create and set an attribute for any HTML DOM element, is by using <code>setAttribute</code> which takes two arguments. The first being a valid attribute name and the second being a value for that attribute.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> div <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'div'</span><span class="token punctuation">;</span><br />div<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"class"</span><span class="token punctuation">,</span> <span class="token string">"page-content"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>This produces the same markup <code><div class="page-content"></div></code> as the method above. You can also get and set the <code>class</code> attribute for a specific HTML element by accessing the <code>className</code> property of the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/className">Element</a> interface.</p>
<pre class="language-js"><code class="language-js">HTMLElement<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">"page-content"</span></code></pre>
<p>The DOM provides many unique ways to modify the content within HTML nodes or completely alter the document structure. Using the <strong>read-only</strong> <code>classList</code> property returns a live <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/classList">DOMTokenList</a> collection of class attributes for the element.</p>
<p>The DOMTokenList itself is read-only, although you can modify it with the <a href="https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/add">add()</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/remove">remove()</a>, and <a href="https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle">toggle()</a> methods.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> p <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"p"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />p<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"class"</span><span class="token punctuation">,</span> <span class="token string">"first-class"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// <p class="first-class"></p></span><br /><br />p<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">"second-class"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// <p class="first-class second-class"></p></span><br />p<span class="token punctuation">.</span>classList<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token string">"first-class"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// <p class="second-class"></p></span></code></pre>
<p><strong>Note</strong>: You can quickly see the nodes and objects contained in each DOM element by inspecting the page and navigating to the properties tab.</p>
<h2 class="post-heading">Binding elements to the DOM</h2>
<p>The final step in this workflow is to bind the HTML elements to our DOM tree using <code>appendChild()</code>. This step in the process truly improved my overall web content structuring and DOM understanding.</p>
<p>You can utilize the <code>appendChild()</code> method and bind the virtually created HTML elements to the DOM within the document as a child of the <code>body</code> tag.</p>
<pre class="language-js"><code class="language-js">document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>div<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// binding the div element to DOM tree</span></code></pre>
<p>So far, you've created one HTML <code>div</code> element, set its <code>class</code> attribute and then finalized the processing by binding it to the DOM tree. Specifically binding the element onto the <code><body></code> node of the document. Now who said using JavaScript in web development had to be hard?</p>
<h2 class="post-heading">Setup Browser Testing Environment</h2>
<p>Most browsers will allow you to right click on a webpage and use the <code>inspect</code> menu button to inspect the markup within the current page. I recommend installing Chrome <a href="https://developers.google.com/web/tools/chrome-devtools">Dev Tools</a> or some form of developer tools for the specific browser you are using. You also need a text editor of any flavor. I'm using Visual Studio Code as my IDE (Integrated Development Environment) but feel free to use whichever editor you'd like.</p>
<p>Open up a terminal window and create a new directory named js-tutorial using the <code>mkdir</code> command,</p>
<pre class="language-shell"><code class="language-shell">spherical:~ TannerDolby$ <span class="token function">mkdir</span> js-tutorial</code></pre>
<p>Then change directory into the newly created one name js-tutorial,</p>
<pre class="language-shell"><code class="language-shell">spherical:~ TannerDolby$ <span class="token builtin class-name">cd</span> js-tutorial</code></pre>
<p>The directory js-tutorial currently does not contain any content so performing a list command using <code>ls</code> will output nothing until we add content to the directory.</p>
<p>Using the <code>touch</code> command here creates a file named <code>index.html</code> within the root directory of js-tutorial. Let's create the other files needed for this post while we are here.</p>
<pre class="language-shell"><code class="language-shell">spherical:js-tutorial TannerDolby$ <span class="token function">touch</span> index.html<br />spherical:js-tutorial TannerDolby$ <span class="token function">touch</span> style.css<br />spherical:js-tutorial TannerDolby$ <span class="token function">touch</span> script.js<br />spherical:js-tutorial TannerDolby$ <span class="token function">ls</span><br />index.html script.js style.css</code></pre>
<h2 class="post-heading">Lets write some code!</h2>
<p>Now we're ready to start putting code into these newly created files within the js-tutorial directory. Open up the js-tutorial folder in your preferred editor and navigate into the <code>index.html</code> file (it will be blank). I suggest using the <a href="https://marketplace.visualstudio.com/items?itemName=sidthesloth.html5-boilerplate">html5-boilerplate</a> VS Code plugin as I will be using it to generate a template of HTML boilerplate code. But getting familiar with typing out the basic markup for an <code>.html</code> page by hand is great practice.</p>
<p>Inside the <code>index.html</code> file, include the following HTML.</p>
<div class="filename-title"><span>Filename</span>: <em>index.html</em></div>
<pre class="language-html"><code class="language-html"><span class="token doctype"><span class="token punctuation"><!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>html</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>utf-8<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">http-equiv</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>X-UA-Compatible<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>IE=edge<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>title</span><span class="token punctuation">></span></span>Intro to client-side JS<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>title</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>description<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>A demo page<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>width=device-width, initial-scale=1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>style.css<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>script.js<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span></code></pre>
<p>Great! Now that the basic markup for <code>index.html</code> page is setup. Make sure you've provided the relevant document metadata inside the <code><head></code> tag. Ensure to include references to the custom CSS file using a <code><link></code> and custom JavaScript using a <code><script></code> tag.</p>
<h2 class="post-heading"> Putting it all together!</h2>
<p>Navigate to the <code>script.js</code> file in the home js-tutorial directory and lets start writing JS code for constructing a basic DOM tree. You will be utilizing everything mentioned so far to build a small web page with virtually created HTML elements.</p>
<h3>Step 1</h3>
<p>Create the <code><main></code> and <code><section></code> HTML elements with a <code>class</code> attribute then inject and set a value for each.</p>
<div class="filename-title"><span>Filename</span>: <em>script.js</em></div>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> main <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"main"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />main<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"class"</span><span class="token punctuation">,</span> <span class="token string">"page-wrapper"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">const</span> section <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"section"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />section<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"class"</span><span class="token punctuation">,</span> <span class="token string">"page-content"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3>Step 2</h3>
<p>Create the heading and paragraph elements and give them both some inner text.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> h1 <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"h1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />h1<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"class"</span><span class="token punctuation">,</span> <span class="token string">"section-title"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <br />h1<span class="token punctuation">.</span>innerText <span class="token operator">=</span> <span class="token string">"Hello world!"</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">const</span> p <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"p"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />p<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"class"</span><span class="token punctuation">,</span> <span class="token string">"section-text"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />p<span class="token punctuation">.</span>innerText <span class="token operator">=</span> <span class="token string">"lorem ipsum dorem dolor."</span><span class="token punctuation">;</span></code></pre>
<h3>Step 3</h3>
<p>Create an <code><img></code> element for the picture I grabbed from <a href="https://bukk.it/">bukk.it</a></p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> img <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"img"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />img<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"class"</span><span class="token punctuation">,</span> <span class="token string">"photo"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />img<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"src"</span><span class="token punctuation">,</span> <span class="token string">"cat-coding.jpg"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />img<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"alt"</span><span class="token punctuation">,</span> <span class="token string">"Cat, presumably coding a very complex system."</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />img<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"loading"</span><span class="token punctuation">,</span> <span class="token string">"lazy"</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<h3>Step 4</h3>
<p>Create a paragraph element for the image description.</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> p2 <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">"p"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />p2<span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">"class"</span><span class="token punctuation">,</span> <span class="token string">"caption"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br />p2<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>img<span class="token punctuation">.</span>alt<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">. This photo was found on bukk.it</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span></code></pre>
<h3>Step 5</h3>
<p>Bind virtually created HTML elements to the DOM Tree.</p>
<pre class="language-js"><code class="language-js">section<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>h1<span class="token punctuation">)</span><span class="token punctuation">;</span><br />section<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span><span class="token punctuation">;</span><br />section<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>img<span class="token punctuation">)</span><span class="token punctuation">;</span><br />section<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>p2<span class="token punctuation">)</span><span class="token punctuation">;</span><br />main<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>section<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token comment">// Append the first <main> element to the documents body.</span><br />document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>main<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Start up a local web server or open the <code>index.html</code> file using your web browser. If you have provided the proper <code><link></code> element for CSS, the HTML we created in <code>script.js</code> will render on the page with the exact DOM structure that was setup while binding the HTML elements.</p>
<p>I gave the page a bit more styling within the <a href="https://github.com/tannerdolby/intro-browser-js/blob/master/style.css">stylesheet</a> if you want to view the code. You could also apply the same styles as those present in the <code>.css</code> file by using JavaScript and <code>element.style.attributeNode = ""</code>, this will take a bit longer.</p>
<h2 class="post-heading">Conclusion</h2>
<p>If you read this far and followed each step, you should now have a very basic web page with a couple HTML elements built primarily with JS instead of using traditional markup directly inside an <code>.html</code> file.</p>
<p>For anyone wanting to start their journey with JavaScript, this is truly some of the best practice to become more familiar with the basics of browser JS. Have a look at the <a href="https://github.com/tannerdolby/intro-browser-js">source code on Github</a>. You can also checkout similar posts in the <a href="https://tannerdolby.com/writing/?filter=javascript">#javascript</a> or <a href="https://tannerdolby.com/writing/?filter=html">#html</a> categories.</p>
<p>Here's a link to <a href="https://browserjs-intro.netlify.app/">the live demo</a>.</p>
Getting Started with OverTheWire Bandit Security Games2020-10-05T00:00:00Zhttps://tannerdolby.com/writing/getting-started-with-overthewire-bandit-security-games/<p>How familiar are you with using SSH? If you hesitated to answer, don't fear as after reading this article you will understand how to perform a secure remote connection using SSH and work in the server environment. I'm by no means a security expert, but these challenges can be quite fun while providing some solid file system practice. Grab your favorite cup of coffee or tea and get ready to conquer some OverTheWire Bandit games!</p>
<h2 class="post-heading">What is SSH?</h2>
<p>The <a href="https://www.ssh.com/ssh/">SSH Protocol</a> (referred to as Secure Shell) is a method for remote secure login from one computer to another. It provides several options for strong remote authentication while also protecting the communications security and health via strong encryption.</p>
<p>Using SSH protocol is the most secure alternative to unprotected login protocols such as <a href="https://www.ssh.com/ssh/telnet">telnet</a> and <a href="https://www.ssh.com/ssh/rlogin">rlogin</a>, amongst other insecure file transfer methods like <a href="https://en.wikipedia.org/wiki/File_Transfer_Protocol">FTP</a>.</p>
<h2 class="post-heading">What is a shell?</h2>
<p>The <a href="https://en.wikipedia.org/wiki/Shell_(computing)">shell</a> is a user interface for performing system level operations. It's a user level program to start other user level programs, using calls to the operating system. The Terminal (macOS) and CMD (Windows) programs are “shells”.</p>
<h2 class="post-heading">Getting started with OverTheWire</h2>
<p>Every level offered by <a href="https://overthewire.org/">OverTheWire</a> can help you to learn and practice security concepts in the form of fun-filled games using the shell. The game server has its own SSH Port to use when connecting to specific OverTheWire games. This article will focus on the first five <a href="https://overthewire.org/wargames/bandit">Bandit</a> levels which run on port 2220.</p>
<h2 class="post-heading">Connecting to the Bandit Shell</h2>
<p>Open up a shell (Terminal for MacOS, CMD in Windows) program and write the following command for connecting to bandit level zero on port 2220. More information about connecting can be found on the <a href="https://overthewire.org/wargames/bandit/bandit0.html">Level Zero</a> OverTheWire webpage.</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">ssh</span> bandit0@bandit.labs.overthewire.org -p <span class="token number">2220</span></code></pre>
<p>After running the above command, your shell will prompt you to enter a password. The password for Bandit level 0 is <code>bandit0</code>. Once the correct passcode has been entered, you will have access to the root directories for the corresponding Bandit level. This process of authentication will be performed for every new instance you SSH into a Bandit level.</p>
<h2 class="post-heading">Let the games begin!</h2>
<p>The goal of level zero is for you to log into the game using SSH and become familiarized with the bandit shell. The host to which you need to connect is <code>bandit.labs.overthewire.org</code> on port 2220. We are told that the username and password are both <code>bandit0</code>. Once logged in, go to the <a href="https://overthewire.org/wargames/bandit/bandit1.html">Level One</a> page to find out how to beat this first Bandit level (or keep reading).</p>
<p>Once the correct credentials have been provided, you're sucessfully connected to Bandit level zero and will see a shell similar to below. You will have access to the root directory contents for the corresponding level.</p>
<pre class="language-bash"><code class="language-bash">bandit0@bandit:~$</code></pre>
<h2 class="post-heading">I've connected to a bandit shell with SSH, now what?</h2>
<p>When solving most of the Bandit games, I found myself repeatedly using a few shell commands. Since we're starting at the root directory for every new level, it's wise to list the directories contents with <code>ls</code> every time you connect to a new OverTheWire game server.</p>
<ul>
<li>Run the command <code>ls</code> to list all directory contents and files present on the server.</li>
</ul>
<p>After running <code>ls</code> in bandit level zero, the output returns all the directory contents. Within this level, there is only one file named <code>readme</code> existing inside the current directory.</p>
<pre class="language-bash"><code class="language-bash">bandit0@bandit:~$ <span class="token function">ls</span> <br />readme</code></pre>
<p>Next, use the command <code>ls</code> with flags <code>-la</code> to list all hidden files in long listing format within the bandit level root directory. To define the flags or options, take a look below.</p>
<ul>
<li><code>-l</code> provides a list of a directories content in long listing format.</li>
<li><code>-a</code> tells the computer to not ignore entries starting with a period.</li>
</ul>
<pre class="language-bash"><code class="language-bash">bandit0@bandit:~$ <span class="token function">ls</span> -la<br />total <span class="token number">24</span><br />drwxr-xr-x <span class="token number">2</span> root root <span class="token number">4096</span> Oct <span class="token number">16</span> <span class="token number">2018</span> <span class="token builtin class-name">.</span><br />drwxr-xr-x <span class="token number">41</span> root root <span class="token number">4096</span> Oct <span class="token number">16</span> <span class="token number">2018</span> <span class="token punctuation">..</span><br />-rw-r--r-- <span class="token number">1</span> root root <span class="token number">220</span> May <span class="token number">15</span> <span class="token number">2017</span> .bash_logout<br />-rw-r--r-- <span class="token number">1</span> root root <span class="token number">3526</span> May <span class="token number">15</span> <span class="token number">2017</span> .bashrc<br />-rw-r--r-- <span class="token number">1</span> root root <span class="token number">675</span> May <span class="token number">15</span> <span class="token number">2017</span> .profile<br />-rw-r----- <span class="token number">1</span> bandit1 bandit0 <span class="token number">33</span> Oct <span class="token number">16</span> <span class="token number">2018</span> readme<br />bandit0@bandit:~$</code></pre>
<p>You <em>should</em> see the above file structure in your corresponding shell when performing the <code>ls -la</code> command after connecting to Bandit level zero.</p>
<h2 class="post-heading">Level Zero to One</h2>
<p>The password needed to access Bandit level 1 via SSH is stored in a file called <code>readme</code> located in the root directory. Use the password you've uncoverered in the previous level to log into Bandit Level One. Whenever you find a new password. Copy it to your clipboard before using SSH (on port 2220) with the corresponding level username <code>bandit1</code> to log into the next level and continue bandit wargames.</p>
<p>For these first few levels, passwords are usually hidden in files that contain ASCII characters or are considered to be human-readable files. To find the first password for bandit level zero we will use the shell command <code>find</code>.</p>
<pre class="language-bash"><code class="language-bash">bandit0@bandit:~$ <span class="token function">find</span> <span class="token builtin class-name">.</span> -type f -exec <span class="token function">file</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token operator">|</span> <span class="token function">grep</span> ASCII<br />./readme: ASCII text<br />./.bash_logout: ASCII text<br />./.profile: ASCII text<br />./.bashrc: ASCII text<br />bandit0@bandit:~$</code></pre>
<p>To break down the above output: The shell told us that each of the files contained ASCII text and were executable. This intermediate step using <code>find</code> is not necessarily needed here as the password could be found via 'trial-and-error' by opening each file in the current directory. But, I thought it was good practice to show moving forward into the next levels.</p>
<p>You can proceed to opening each of the files using <code>cat filename</code> on macOS, but I have a good feeling about the first file in the output: <code>readme</code>. Lets open it.</p>
<pre class="language-bash"><code class="language-bash">bandit0@bandit:~$ <span class="token function">cat</span> ./readme<br />boJ9jbbUNNfk<span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span></code></pre>
<p>And Voilà! Copy the password you found to your clipboard or a place you wont forget. You will need to use it to SSH into the next bandit level. Use the <code>exit</code> command to disconnect from a bandit level after you're ready to move on.</p>
<h2 class="post-heading">Level One to Two</h2>
<p>Now that you've become relatively familiar with the Bandit shell and how to go about finding passwords. Lets jump right into connecting to Bandit level one and find the hidden password!</p>
<p>If you're following along through OverTheWire's website. We're told that the password for this level is stored inside a file named <code>-</code> located in the home directory.</p>
<p>The first order of business will be connecting to Bandit level one using <code>bandit1</code> as the username on port 2220. This levels password will be the characters you copied to clipboard after performing <code>cat ./readme</code> to open the file.</p>
<pre class="language-bash"><code class="language-bash">spherical:~ TannerDolby$ <span class="token function">ssh</span> bandit1@bandit.labs.overthewire.org -p <span class="token number">2220</span></code></pre>
<p>If the correct password is provided then you will have successfully connected to the bandit level one shell. You terminal or command line should display an output similar to the code snippet below.</p>
<pre class="language-bash"><code class="language-bash">bandit1@bandit:~$</code></pre>
<p>Now that your connected to the bandit server lets find the password stored in a file called <code>-</code>. Like always, lets list all of the root directories contents with <code>ls -la</code>. Refer to <a href="https://tannerdolby.com/writing/getting-started-with-overthewire-bandit-security-games/#listing-commands">ls options</a> for a refresher on why to use the <code>-la</code> options.</p>
<pre class="language-bash"><code class="language-bash">bandit1@bandit:~$ <span class="token function">ls</span> -la<br />total <span class="token number">24</span><br />-rw-r----- <span class="token number">1</span> bandit2 bandit1 <span class="token number">33</span> Oct <span class="token number">16</span> <span class="token number">2018</span> -<br />drwxr-xr-x <span class="token number">2</span> root root <span class="token number">4096</span> Oct <span class="token number">16</span> <span class="token number">2018</span> <span class="token builtin class-name">.</span><br />drwxr-xr-x <span class="token number">41</span> root root <span class="token number">4096</span> Oct <span class="token number">16</span> <span class="token number">2018</span> <span class="token punctuation">..</span><br />-rw-r--r-- <span class="token number">1</span> root root <span class="token number">220</span> May <span class="token number">15</span> <span class="token number">2017</span> .bash_logout<br />-rw-r--r-- <span class="token number">1</span> root root <span class="token number">3526</span> May <span class="token number">15</span> <span class="token number">2017</span> .bashrc<br />-rw-r--r-- <span class="token number">1</span> root root <span class="token number">675</span> May <span class="token number">15</span> <span class="token number">2017</span> .profile<br />bandit1@bandit:~$</code></pre>
<p>The file <code>-</code> is what we are looking for, which can be found on the first line. Next, it would be wise to check and make sure this file contains ASCII characters.</p>
<p>Utilizing the <code>find</code> command chained with a few other tools, we can check for files containing ASCII characters or that are considered to be "Human Readable".</p>
<h2 class="post-heading">What is Grep?</h2>
<p><a href="https://phoenixnap.com/kb/grep-command-linux-unix-examples">Grep</a> is an acronym that stands for Global Regular Expression Print. It's usage as a command line tool is to search for a pattern or string of text in a given file. The syntax of using <code>grep</code> calls for the pattern or string your searching for and the filename you'd like to search in.</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">grep</span> <span class="token operator"><</span>string to match<span class="token operator">></span> <span class="token operator"><</span>filename to search for<span class="token operator">></span></code></pre>
<p>The other helpful options to use here would be, <code>type -f</code> to find all regular files, and <code>-exec file</code> for finding all executable files.</p>
<pre class="language-bash"><code class="language-bash">bandit1@bandit:~$ <span class="token function">find</span> <span class="token builtin class-name">.</span> -type f -exec <span class="token function">file</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token operator">|</span> <span class="token function">grep</span> ASCII<br />./.bash_logout: ASCII text<br />./.bashrc: ASCII text<br />./-: ASCII text<br />bandit1@bandit:~$</code></pre>
<p>And would you look at that, the <code>/-</code> file indeed contains ASCII text. Lets open it with the <code>cat</code> command and find the password.</p>
<pre class="language-shell"><code class="language-shell">bandit1@bandit:~$ <span class="token function">cat</span> ./-<br />CV1DtqXWVF<span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span></code></pre>
<p>Make sure to copy the password to clipboard from opening the above file and exit the current bandit shell. Onward!</p>
<h2 class="post-heading">Level Two to Three</h2>
<p>OverTheWire tells us that the password for the next level is stored in a file called <code>spaces in this filename</code> located in the home directory.</p>
<p>Before you can start searching for the above file, you must first connect to Bandit level two on port 2220 with the username <code>bandit2</code> and password copied to clipboard from last level. The connection process in terminal should be:</p>
<pre class="language-bash"><code class="language-bash"><span class="token function">ssh</span> bandit2@bandit.labs.overthewire.org -p <span class="token number">2220</span></code></pre>
<p>After you've connected, whats the first thing you thought to do? If you were thinking what I was, then you might have beat me to it by using an <code>ls -la</code> command in the shell to perform a long listing format of all the current directories content.</p>
<pre class="language-bash"><code class="language-bash">bandit2@bandit:~$ <span class="token function">ls</span> -la<br />total <span class="token number">24</span><br />drwxr-xr-x <span class="token number">2</span> root root <span class="token number">4096</span> Oct <span class="token number">16</span> <span class="token number">2018</span> <span class="token builtin class-name">.</span><br />drwxr-xr-x <span class="token number">41</span> root root <span class="token number">4096</span> Oct <span class="token number">16</span> <span class="token number">2018</span> <span class="token punctuation">..</span><br />-rw-r--r-- <span class="token number">1</span> root root <span class="token number">220</span> May <span class="token number">15</span> <span class="token number">2017</span> .bash_logout<br />-rw-r--r-- <span class="token number">1</span> root root <span class="token number">3526</span> May <span class="token number">15</span> <span class="token number">2017</span> .bashrc<br />-rw-r--r-- <span class="token number">1</span> root root <span class="token number">675</span> May <span class="token number">15</span> <span class="token number">2017</span> .profile<br />-rw-r----- <span class="token number">1</span> bandit3 bandit2 <span class="token number">33</span> Oct <span class="token number">16</span> <span class="token number">2018</span> spaces <span class="token keyword">in</span> this filename<br />bandit2@bandit:~$</code></pre>
<p>The file <code>spaces in this filename</code> indeed exists, so lets open it up and see the file contents using the <code>cat</code> command. If a filename contains spaces in between characters, try wrapping filename in double quotes so then the <code>cat</code> command ignores spaces inside filenames.</p>
<pre class="language-bash"><code class="language-bash">bandit2@bandit:~$ <span class="token function">cat</span> <span class="token string">"spaces in this filename"</span><br />UmHadQclWmgd<span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><br />bandit2@bandit:~$ <span class="token builtin class-name">exit</span></code></pre>
<p>Make sure to copy the password to clipboard or make note of it as we will need it handy when accessing the next bandit level.</p>
<h2 class="post-heading">Level Three to Four</h2>
<p>OverTheWire tells us that the password to access the next level is stored in a hidden file within the <code>inhere</code> directory. Now that the process of using SSH to connect to new OverTheWire Bandit Servers has been repeated a few times, I will just show my terminal command to SSH into Bandit level three on port 2220 with username bandit3 and the password found in the previous level.</p>
<pre class="language-bash"><code class="language-bash">spherical:~ TannerDolby$ <span class="token function">ssh</span> bandit3@bandit.labs.overthewire.org -p <span class="token number">2220</span></code></pre>
<p>Quick listing of the root directory contents.</p>
<pre class="language-bash"><code class="language-bash">bandit3@bandit:~$ <span class="token function">ls</span><br />inhere</code></pre>
<p>Remember! We have been told there is a password hidden in a file within the <code>inhere</code> directory. Lets change to that directory using the <code>cd</code> command and inspect the directories contents.</p>
<pre class="language-bash"><code class="language-bash">bandit3@bandit:~$ <span class="token builtin class-name">cd</span> inhere<br />bandit3@bandit:~/inhere$ <span class="token function">ls</span> -la<br />total <span class="token number">12</span><br />drwxr-xr-x <span class="token number">2</span> root root <span class="token number">4096</span> Oct <span class="token number">16</span> <span class="token number">2018</span> <span class="token builtin class-name">.</span><br />drwxr-xr-x <span class="token number">3</span> root root <span class="token number">4096</span> Oct <span class="token number">16</span> <span class="token number">2018</span> <span class="token punctuation">..</span><br />-rw-r----- <span class="token number">1</span> bandit4 bandit3 <span class="token number">33</span> Oct <span class="token number">16</span> <span class="token number">2018</span> .hidden<br />bandit3@bandit:~/inhere$</code></pre>
<p>There it is, a file called <code>.hidden</code> with user or groups related to bandit3 and bandit4. In order to make sure the file contains ASCII characters, try using a <code>find</code> command to uncover any executable file types that contain ASCII text.</p>
<pre class="language-bash"><code class="language-bash">bandit3@bandit:~/inhere$ <span class="token function">find</span> <span class="token builtin class-name">.</span> -type f -exec <span class="token function">file</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token operator">|</span> <span class="token function">grep</span> ASCII<br />./.hidden: ASCII text<br />bandit3@bandit:~/inhere$</code></pre>
<p>The <code>./.hidden</code> file is found within the inhere directory. Proceed to open it and see if there is a password inside.</p>
<pre class="language-bash"><code class="language-bash">bandit3@bandit:~/inhere$ <span class="token function">cat</span> ./.hidden<br />pIwrPrtPN36QITS<span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><br />bandit3@bandit:~/inhere$ <span class="token builtin class-name">exit</span></code></pre>
<h2 class="post-heading">Level Four to Five</h2>
<p>The password for the next level is stored in the only human-readable file inside the <code>inhere</code> directory. If your shell is cluttered up with all the previous levels content, try using the <code>reset</code> or <code>clear</code> command.</p>
<p>Next, connect to the level 4 bandit server on port 2220 via SSH. Using bandit4 as the username and the last levels hidden password.</p>
<pre class="language-bash"><code class="language-bash">spherical:~ TannerDolby$ <span class="token function">ssh</span> bandit4@bandit.labs.overthewire.org -p <span class="token number">2220</span></code></pre>
<p>Since OTW tells you the password is stored in the only human-readable file within the inhere directory. Lets change directory to <code>inhere</code> and then perform a long listing operation of all the current directories contents.</p>
<pre class="language-bash"><code class="language-bash">bandit4@bandit:~$ <span class="token builtin class-name">cd</span> inhere<br />bandit4@bandit:~/inhere$ <span class="token function">ls</span> -la<br />total <span class="token number">48</span><br />drwxr-xr-x <span class="token number">2</span> root root <span class="token number">4096</span> Oct <span class="token number">16</span> <span class="token number">2018</span> <span class="token builtin class-name">.</span><br />drwxr-xr-x <span class="token number">3</span> root root <span class="token number">4096</span> Oct <span class="token number">16</span> <span class="token number">2018</span> <span class="token punctuation">..</span><br />-rw-r----- <span class="token number">1</span> bandit5 bandit4 <span class="token number">33</span> Oct <span class="token number">16</span> <span class="token number">2018</span> -file00<br /><span class="token punctuation">..</span>.</code></pre>
<p>For length purposes, I truncated off the listing content from the above output after <code>-file00</code>. There are many files in this directory so why not simply use the <code>find</code> command to help match any files containing ASCII characters.</p>
<pre class="language-bash"><code class="language-bash">bandit4@bandit:~/inhere$ <span class="token function">find</span> <span class="token builtin class-name">.</span> -type f -exec <span class="token function">file</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token operator">|</span> <span class="token function">grep</span> ASCII<br />./-file07: ASCII text</code></pre>
<p>And there it is, the only human-readable file that is stored in the <code>inhere</code> directory. Lets open it and find the last password of this article!</p>
<pre class="language-bash"><code class="language-bash">bandit4@bandit:~/inhere$ <span class="token function">cat</span> ./-file07<br />koReBOKuIDDe<span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span><span class="token punctuation">..</span>.<br />bandit4@bandit:~/inhere$ <span class="token builtin class-name">exit</span></code></pre>
<h2 class="post-heading">Conclusion</h2>
<p>Thank you for reading this far! I hope your experience with using the shell has improved by completing bandit levels 1-5 via OverTheWire. If you noticed all of the passwords for each level are not provided, you saw right! I will not provide any of the complete passwords as you are capable of following this tutorial and finding them for yourself! Until next time.</p>
<p>If you'd like to read another post like this one, have a look at <a href="https://tannerdolby.com/writing/?filter=security">#security</a> or <a href="https://tannerdolby.com/writing/?filter=shell">#shell</a> tags.</p>