<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Hugo on Techformist</title>
    <link>https://techformist.com/tags/hugo/</link>
    <description>Recent content in Hugo on Techformist</description>
    <image>
      <url>https://techformist.com/logo.svg</url>
      <link>https://techformist.com/logo.svg</link>
    </image>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 25 Nov 2019 18:30:00 +0000</lastBuildDate><atom:link href="https://techformist.com/tags/hugo/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Simple Site Summary in Hugo</title>
      <link>https://techformist.com/simple-site-summary-hugo/</link>
      <pubDate>Mon, 25 Nov 2019 18:30:00 +0000</pubDate>
      
      <guid>https://techformist.com/simple-site-summary-hugo/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s a simple way to organize your taxonomies and have a bird&amp;rsquo;s eye view of the number of posts per category/tag in Hugo.&lt;/p&gt;
&lt;h2 id=&#34;the-problem&#34;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;As techformist.com grew, I became more and more disorganised in maintaining taxonomies. I had some interesting situations -&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a &amp;ldquo;static-site&amp;rdquo; category coexist with &amp;ldquo;static sites&amp;rdquo; category&lt;/li&gt;
&lt;li&gt;confusion b/w why I chose a few terms to be tags rather than categories in their own right&lt;/li&gt;
&lt;li&gt;the recurring need to &amp;ldquo;rethink taxonomy structure&amp;rdquo; depending on the flavour of the month and time of the day&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This often required me to go back and change a few taxonomy terms, or to reorganize site structure in order to provide better visibility to chosen topics.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Here&rsquo;s a simple way to organize your taxonomies and have a bird&rsquo;s eye view of the number of posts per category/tag in Hugo.</p>
<h2 id="the-problem">The Problem</h2>
<p>As techformist.com grew, I became more and more disorganised in maintaining taxonomies. I had some interesting situations -</p>
<ul>
<li>a &ldquo;static-site&rdquo; category coexist with &ldquo;static sites&rdquo; category</li>
<li>confusion b/w why I chose a few terms to be tags rather than categories in their own right</li>
<li>the recurring need to &ldquo;rethink taxonomy structure&rdquo; depending on the flavour of the month and time of the day</li>
</ul>
<p>This often required me to go back and change a few taxonomy terms, or to reorganize site structure in order to provide better visibility to chosen topics.</p>
<p>I also developed this habit of referring back to the older topics with a site search / VSCode search just to copy/paste tags and categories from an older post.</p>
<p>This was frustrating.</p>
<h2 id="the-solution">The Solution</h2>
<p>There were couple of simple solution options -</p>
<ol>
<li>Create a summary page on the site</li>
<li>Include counts in the manually maintained writing/editorial calendar (and bring some automation to that side of the world while at it)</li>
<li>Analyse sitemap to get a nice summary and maintain that analysis somewhere</li>
</ol>
<p>In the end, I felt it would be easier to create a quick summary page on the site and refer back to it, rather than over-engineer a solution.</p>
<p>So, I created this summary page with just a few lines of code for layout.</p>
<p><img loading="lazy" src="/misc/hugo-site-summary.jpg" type="" alt="hugo-summary-count-posts-categories-tags"  /></p>
<p>I can now -</p>
<ol>
<li>Quickly check the categories / tags and select relevant combination for a new post</li>
<li>Keep an eye on the counts and refocus on things that I have to write more about</li>
<li>Satisfy my ego by showing the post counts and by hiding away more useful statistics such as the usefulness &amp; longevity of the content</li>
</ol>
<h2 id="how-to-implement-this-in-your-own-hugo-site">How to implement this in your own Hugo site?</h2>
<p>Create a file called &ldquo;summary.html&rdquo; in your <code>layouts</code> folder.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">{{ partial &#34;header&#34; . }} 
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">{{ partial &#34;header/header&#34; . }}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">{{/*-- post count */}}
</span></span><span class="line"><span class="cl">{{ $posts := (where .Site.RegularPages &#34;Section&#34; &#34;==&#34; &#34;posts&#34;) }}
</span></span><span class="line"><span class="cl">{{ $postCount := len $posts }}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">{{/*-- page count */}}
</span></span><span class="line"><span class="cl">{{ $pages := (where .Site.RegularPages &#34;Section&#34; &#34;==&#34; &#34;page&#34;) }}
</span></span><span class="line"><span class="cl">{{ $pageCount := len $pages }}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">&#34;overflow: auto;&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">table</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">thead</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">td</span> <span class="na">style</span><span class="o">=</span><span class="s">&#34;text-align:center;font-weight: bold;width: 10em;&#34;</span><span class="p">&gt;</span>Description<span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">td</span> <span class="na">style</span><span class="o">=</span><span class="s">&#34;text-align:center;font-weight: bold;&#34;</span><span class="p">&gt;</span>Value<span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">thead</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">tbody</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;&lt;</span><span class="nt">td</span><span class="p">&gt;</span>Pages<span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;&lt;</span><span class="nt">td</span><span class="p">&gt;</span>{{ $pageCount }}<span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;&lt;</span><span class="nt">td</span><span class="p">&gt;</span>Posts<span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;&lt;</span><span class="nt">td</span><span class="p">&gt;</span>{{ $postCount }}<span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;&lt;</span><span class="nt">td</span><span class="p">&gt;</span>Post by Categories<span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          {{ range $name, $taxonomy := .Site.Taxonomies.categories }}
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;/categories/{{ $name | urlize }}&#34;</span><span class="p">&gt;</span>{{ $name | humanize }} ({{ $taxonomy.Count }})<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="ni">&amp;nbsp;</span>
</span></span><span class="line"><span class="cl">          {{end}}
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;&lt;</span><span class="nt">td</span><span class="p">&gt;</span>Post by Tags<span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          {{ range $name, $taxonomy := .Site.Taxonomies.tags }}
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;/tags/{{ $name | urlize }}&#34;</span><span class="p">&gt;</span>#{{ $name | humanize }} ({{ $taxonomy.Count }})<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="ni">&amp;nbsp;</span>
</span></span><span class="line"><span class="cl">          {{end}}
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">tbody</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">table</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">{{ partial &#34;footer&#34; . }}
</span></span></code></pre></div><p>As you can see, I am no where near an expert on Hugo. Or, even basic styling in HTML :)</p>
<p>Next, create a content page in <code>pages</code> folder. This is to better organize structure in the future.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-md" data-lang="md"><span class="line"><span class="cl">---
</span></span><span class="line"><span class="cl">title: Summary of Posts
</span></span><span class="line"><span class="cl">url: summary
</span></span><span class="line"><span class="cl">type: page
</span></span><span class="line"><span class="cl">layout: summary
</span></span><span class="line"><span class="cl">date: 2020-02-20 20:20:20
</span></span><span class="line"><span class="cl">comments: false
</span></span><span class="line"><span class="cl">---
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">This is a summary of the site that lists categories, tags and what not alongside the number of posts. Not quite useful for anyone other than the publishers.
</span></span></code></pre></div><p>Navigate to <code>&lt;your site&gt;/summary</code>.</p>
<p>Have fun.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Include full content in site feed in Hugo</title>
      <link>https://techformist.com/full-post-feed-hugo/</link>
      <pubDate>Thu, 17 Oct 2019 06:30:00 +0000</pubDate>
      
      <guid>https://techformist.com/full-post-feed-hugo/</guid>
      <description>&lt;p&gt;Include all content of your posts in your site feed when using Hugo static site generator.&lt;/p&gt;
&lt;p&gt;By default Hugo will include only summary in your website feed (e.g. in &lt;code&gt;/index.xml&lt;/code&gt;). Your theme may already provide a way to provide full content instead of just the summary. If it doesn&amp;rsquo;t, you can make those simple changes yourself.&lt;/p&gt;
&lt;p&gt;Create a new file &lt;code&gt;rss.xml&lt;/code&gt; in &lt;code&gt;layouts\_default\&lt;/code&gt; folder in your site root directory. Include following content (as of v0.58) -&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Include all content of your posts in your site feed when using Hugo static site generator.</p>
<p>By default Hugo will include only summary in your website feed (e.g. in <code>/index.xml</code>). Your theme may already provide a way to provide full content instead of just the summary. If it doesn&rsquo;t, you can make those simple changes yourself.</p>
<p>Create a new file <code>rss.xml</code> in <code>layouts\_default\</code> folder in your site root directory. Include following content (as of v0.58) -</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="c">&lt;!-- layouts\_default\rss.xml --&gt;</span>
</span></span><span class="line"><span class="cl">{{ printf &#34;<span class="cp">&lt;?xml version=\&#34;1.0\&#34; encoding=\&#34;utf-8\&#34; standalone=\&#34;yes\&#34; ?&gt;</span>&#34; | safeHTML }}
</span></span><span class="line"><span class="cl"><span class="nt">&lt;rss</span> <span class="na">version=</span><span class="s">&#34;2.0&#34;</span> <span class="na">xmlns:atom=</span><span class="s">&#34;http://www.w3.org/2005/Atom&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&lt;channel&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;title&gt;</span>{{ if eq  .Title  .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}<span class="nt">&lt;/title&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;link&gt;</span>{{ .Permalink }}<span class="nt">&lt;/link&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;description&gt;</span>Recent content {{ if ne  .Title  .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}<span class="nt">&lt;/description&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;generator&gt;</span>Hugo -- gohugo.io<span class="nt">&lt;/generator&gt;</span>{{ with .Site.LanguageCode }}
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;language&gt;</span>{{.}}<span class="nt">&lt;/language&gt;</span>{{end}}{{ with .Site.Author.email }}
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;managingEditor&gt;</span>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}<span class="nt">&lt;/managingEditor&gt;</span>{{end}}{{ with .Site.Author.email }}
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;webMaster&gt;</span>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}<span class="nt">&lt;/webMaster&gt;</span>{{end}}{{ with .Site.Copyright }}
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;copyright&gt;</span>{{.}}<span class="nt">&lt;/copyright&gt;</span>{{end}}{{ if not .Date.IsZero }}
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;lastBuildDate&gt;</span>{{ .Date.Format &#34;2006-01-02&#34; | safeHTML }}<span class="nt">&lt;/lastBuildDate&gt;</span>{{ end }}
</span></span><span class="line"><span class="cl">    {{ with .OutputFormats.Get &#34;RSS&#34; }}
</span></span><span class="line"><span class="cl">        {{ printf &#34;<span class="nt">&lt;atom:link</span> <span class="na">href=</span><span class="s">%q</span> <span class="na">rel=</span><span class="s">\&#34;self\&#34;</span> <span class="na">type=</span><span class="s">%q</span> <span class="nt">/&gt;</span>&#34; .Permalink .MediaType | safeHTML }}
</span></span><span class="line"><span class="cl">    {{ end }}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    {{- range first 10 (where .Site.RegularPages &#34;Type&#34; &#34;not in&#34; &#34;pages&#34; ) -}}
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;item&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&lt;title&gt;</span>{{ .Title }}<span class="nt">&lt;/title&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&lt;link&gt;</span>{{ .Permalink }}<span class="nt">&lt;/link&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&lt;pubDate&gt;</span>{{ .Date.Format &#34;2006-01-02&#34; | safeHTML }}<span class="nt">&lt;/pubDate&gt;</span>
</span></span><span class="line"><span class="cl">      {{ with .Site.Author.email }}<span class="nt">&lt;author&gt;</span>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}<span class="nt">&lt;/author&gt;</span>{{end}}
</span></span><span class="line"><span class="cl">      <span class="nt">&lt;guid&gt;</span>{{ .Permalink }}<span class="nt">&lt;/guid&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&lt;description&gt;</span>{{ .Content | html }}<span class="nt">&lt;/description&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/item&gt;</span>
</span></span><span class="line"><span class="cl">    {{ end }}
</span></span><span class="line"><span class="cl">  <span class="nt">&lt;/channel&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/rss&gt;</span>
</span></span></code></pre></div><p>The content of the file is almost same as the <a href="https://gohugo.io/templates/rss/#the-embedded-rss-xml">embedded <code>rss.xml</code> used in Hugo</a>.</p>
<p>.. except for two crucial differences -</p>
<ol>
<li>
<p>Include full content in RSS feed</p>
<pre tabindex="0"><code>&lt;description&gt;{{ .Content | html }}&lt;/description&gt;
</code></pre></li>
<li>
<p>Fetch only 10 articles in the feed. You can get this 10 from the site config as well.</p>
<pre tabindex="0"><code>{{- range first 10 (where .Site.RegularPages &#34;Type&#34; &#34;not in&#34; &#34;pages&#34; ) -}}
</code></pre></li>
</ol>
]]></content:encoded>
    </item>
    
    <item>
      <title>Add PWA to your Hugo site</title>
      <link>https://techformist.com/add-pwa-hugo/</link>
      <pubDate>Wed, 11 Sep 2019 06:30:00 +0000</pubDate>
      
      <guid>https://techformist.com/add-pwa-hugo/</guid>
      <description>&lt;p&gt;Adding PWA to your Hugo static site is quite easy.&lt;/p&gt;
&lt;h3 id=&#34;what-is-pwa-and-why-should-i-add-it&#34;&gt;What is PWA and why should I add it?&lt;/h3&gt;
&lt;p&gt;Progressive web applications (PWA) are a nice way to give your websites an &amp;ldquo;app makeover&amp;rdquo;. Using PWAs your sites are perceived to load faster, are available offline, and in general improve user experience.&lt;/p&gt;
&lt;p&gt;PWAs are supported by all web browsers. Using PWAs on single page applications have shown remarkable improvement in site speed and have provided us the ability to continuing to serve static content even when the connectivity is down.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Adding PWA to your Hugo static site is quite easy.</p>
<h3 id="what-is-pwa-and-why-should-i-add-it">What is PWA and why should I add it?</h3>
<p>Progressive web applications (PWA) are a nice way to give your websites an &ldquo;app makeover&rdquo;. Using PWAs your sites are perceived to load faster, are available offline, and in general improve user experience.</p>
<p>PWAs are supported by all web browsers. Using PWAs on single page applications have shown remarkable improvement in site speed and have provided us the ability to continuing to serve static content even when the connectivity is down.</p>
<p>Back to Hugo - although I can see incremental gains, nothing jumped out to make up for a compelling case for PWA. The sites generated by Hugo are static - pages are already generated and waiting to be loaded. Depending on the theme, you may already be seeing the best load times that your site can achieve. So, YMMV.</p>
<h3 id="how-do-i-add-pwa-to-hugo">How do I add PWA to Hugo?</h3>
<p>At a minimum a PWA needs a manifest and service worker. We will use a offline-first cache strategy to enable PWA.</p>
<h5 id="create-your-icons">Create your icons</h5>
<p>PWAs are available offline and can be installed on the phone. This requires icons of different sizes for your website. Just pluck your logo, remove the text if necessary and generate icons of all popular sizes. You can use a service like <a href="https://favicomatic.com/">Favicomatic</a> to make that a one-click process.</p>
<h5 id="create-manifest">Create manifest</h5>
<p>Create a new file called <code>manifest.json</code> in your <code>/static</code> folder and add content similar to below</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;Techformist&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;short_name&#34;</span><span class="p">:</span> <span class="s2">&#34;techformist&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;icons&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;src&#34;</span><span class="p">:</span> <span class="s2">&#34;/appicons/favicon-128.png&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;sizes&#34;</span><span class="p">:</span> <span class="s2">&#34;128x128&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;image/png&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;src&#34;</span><span class="p">:</span> <span class="s2">&#34;/appicons/apple-touch-icon-144x144.png&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;sizes&#34;</span><span class="p">:</span> <span class="s2">&#34;144x144&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;image/png&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;src&#34;</span><span class="p">:</span> <span class="s2">&#34;/appicons/apple-touch-icon-152x152.png&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;sizes&#34;</span><span class="p">:</span> <span class="s2">&#34;152x152&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;image/png&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;src&#34;</span><span class="p">:</span> <span class="s2">&#34;/appicons/favicon-196x196.png&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;sizes&#34;</span><span class="p">:</span> <span class="s2">&#34;196x196&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;image/png&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;src&#34;</span><span class="p">:</span> <span class="s2">&#34;/appicons/splash.png&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;sizes&#34;</span><span class="p">:</span> <span class="s2">&#34;512x512&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;image/png&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">],</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;start_url&#34;</span><span class="p">:</span> <span class="s2">&#34;/&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;display&#34;</span><span class="p">:</span> <span class="s2">&#34;standalone&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;orientation&#34;</span><span class="p">:</span> <span class="s2">&#34;portrait&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;background_color&#34;</span><span class="p">:</span> <span class="s2">&#34;#FFFFFF&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;theme_color&#34;</span><span class="p">:</span> <span class="s2">&#34;#FFFFFF&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><h5 id="create-service-worker">Create service worker</h5>
<p>Create a new javascript file <code>sw.js</code> in <code>/static</code>. This script does all the heavy lifting like maintaining cache and enabling your site to be treated like an app.</p>
<p>I just copied the code from the sample service worker script available at [https://github.com/wildhaber/offline-first-sw].</p>
<p>Modify the file and choose to make some or all files available offline - I typically include CSS, common Javascript files and images. See the end of this article for the file used by this blog.</p>
<h5 id="include-manifest-in-head">Include manifest in <code>head</code></h5>
<p>Include a link to your manifest in your header.</p>
<p>I use Minimo theme and included the following line in <code>&lt;root&gt;/layouts/partials/head/extra.html</code>. Note that I am not over-writing the file in the theme folder, but overriding it using my own version (as is typical to Hugo themes).</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;manifest&#34;</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;/manifest.json&#34;</span><span class="p">&gt;</span>
</span></span></code></pre></div><h5 id="include-sw-in-footer">Include SW in footer</h5>
<p>Include the service worker JS file reference in your footer. For some strange reason, I chose to be different and included that in my <code>sidebar.html</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span><span class="p">(</span><span class="s1">&#39;serviceWorker&#39;</span> <span class="k">in</span> <span class="nx">navigator</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nx">navigator</span><span class="p">.</span><span class="nx">serviceWorker</span>
</span></span><span class="line"><span class="cl">          <span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="s1">&#39;/sw.js&#39;</span><span class="p">,</span> <span class="p">{</span> <span class="nx">scope</span><span class="o">:</span> <span class="s1">&#39;/&#39;</span> <span class="p">})</span>
</span></span><span class="line"><span class="cl">          <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">registration</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">              <span class="c1">//console.log(&#39;Service Worker Registered&#39;);
</span></span></span><span class="line"><span class="cl">          <span class="p">});</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="nx">navigator</span><span class="p">.</span><span class="nx">serviceWorker</span>
</span></span><span class="line"><span class="cl">          <span class="p">.</span><span class="nx">ready</span>
</span></span><span class="line"><span class="cl">          <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">registration</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">              <span class="c1">//console.log(&#39;Service Worker Ready&#39;);
</span></span></span><span class="line"><span class="cl">          <span class="p">});</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span></code></pre></div><h3 id="see-the-results">See the Results</h3>
<p>That is it. Your site automagically is a PWA now.</p>
<p>Check out Chrome developer tools -</p>
<h5 id="a-site-or-an-app">A site or an app?</h5>
<p>Go to <code>Application</code> tab.</p>
<p>You should see details provided in your manifest including the different icons. You will also see the different offline files you specified in the <code>Cache Storage</code> section.</p>
<h5 id="lighthouse-scores">Lighthouse scores</h5>
<p>Go to <code>Audit</code> tab and do a Lighthouse audit for your site.</p>
<p>Mobile Lighthouse score for home page -</p>
<p><img loading="lazy" src="/misc/lighthouse-score-home-page.jpg" type="" alt="lighthouse-score-home-page"  /></p>
<p>Lighthouse score for an article -</p>
<p><img loading="lazy" src="/misc/lighthouse-score-article.jpg" type="" alt="lighthouse-score-article"  /></p>
<p>Rejoice.</p>
<h3 id="conclusion">Conclusion</h3>
<p>Adding and setting up PWA to Hugo is trivial. But, I did not clearly make out any significant advantages of enabling PWA on my blog - given that I am not after providing a read-offline feature.</p>
<h3 id="post-script">Post Script</h3>
<h5 id="swjs-code">sw.js code</h5>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">CACHE_VERSION</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">BASE_CACHE_FILES</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/css/custom.css&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/js/custom.js&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/search/index.json&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/manifest.json&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/favicon.png&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/images/logo.png&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/techformist-logo-no-text.png&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/assets/css/main.6a060eb7.css&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/assets/js/main.67d669ac.js&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/assets/js/sidebar.9ea42a6e.js&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/assets/js/fuse_search.1ada4bca.js&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">OFFLINE_CACHE_FILES</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/images/logo.png&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/techformist-logo-no-text.png&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/assets/css/main.6a060eb7.css&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/assets/js/main.67d669ac.js&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/assets/js/sidebar.9ea42a6e.js&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/assets/js/fuse_search.1ada4bca.js&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">NOT_FOUND_CACHE_FILES</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/404.html&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">OFFLINE_PAGE</span> <span class="o">=</span> <span class="s1">&#39;/offline/index.html&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">NOT_FOUND_PAGE</span> <span class="o">=</span> <span class="s1">&#39;/404.html&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">CACHE_VERSIONS</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">assets</span><span class="o">:</span> <span class="s1">&#39;assets-v&#39;</span> <span class="o">+</span> <span class="nx">CACHE_VERSION</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">content</span><span class="o">:</span> <span class="s1">&#39;content-v&#39;</span> <span class="o">+</span> <span class="nx">CACHE_VERSION</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">offline</span><span class="o">:</span> <span class="s1">&#39;offline-v&#39;</span> <span class="o">+</span> <span class="nx">CACHE_VERSION</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">notFound</span><span class="o">:</span> <span class="s1">&#39;404-v&#39;</span> <span class="o">+</span> <span class="nx">CACHE_VERSION</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Define MAX_TTL&#39;s in SECONDS for specific file extensions
</span></span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">MAX_TTL</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;/&#39;</span><span class="o">:</span> <span class="mi">3600</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">html</span><span class="o">:</span> <span class="mi">3600</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">json</span><span class="o">:</span> <span class="mi">86400</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">js</span><span class="o">:</span> <span class="mi">86400</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nx">css</span><span class="o">:</span> <span class="mi">86400</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">CACHE_BLACKLIST</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nx">str</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">       <span class="k">return</span> <span class="o">!</span><span class="nx">str</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="s1">&#39;http://localhost&#39;</span><span class="p">)</span> <span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">SUPPORTED_METHODS</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;GET&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * isBlackListed
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @param {string} url
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @returns {boolean}
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">isBlacklisted</span><span class="p">(</span><span class="nx">url</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="nx">CACHE_BLACKLIST</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="o">?</span> <span class="o">!</span><span class="nx">CACHE_BLACKLIST</span><span class="p">.</span><span class="nx">filter</span><span class="p">((</span><span class="nx">rule</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">rule</span> <span class="o">===</span> <span class="s1">&#39;function&#39;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="o">!</span><span class="nx">rule</span><span class="p">(</span><span class="nx">url</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}).</span><span class="nx">length</span> <span class="o">:</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * getFileExtension
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @param {string} url
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @returns {string}
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">getFileExtension</span><span class="p">(</span><span class="nx">url</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">let</span> <span class="nx">extension</span> <span class="o">=</span> <span class="nx">url</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">).</span><span class="nx">reverse</span><span class="p">()[</span><span class="mi">0</span><span class="p">].</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;?&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="nx">extension</span><span class="p">.</span><span class="nx">endsWith</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">))</span> <span class="o">?</span> <span class="s1">&#39;/&#39;</span> <span class="o">:</span> <span class="nx">extension</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * getTTL
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @param {string} url
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">getTTL</span><span class="p">(</span><span class="nx">url</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">url</span> <span class="o">===</span> <span class="s1">&#39;string&#39;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="kd">let</span> <span class="nx">extension</span> <span class="o">=</span> <span class="nx">getFileExtension</span><span class="p">(</span><span class="nx">url</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">MAX_TTL</span><span class="p">[</span><span class="nx">extension</span><span class="p">]</span> <span class="o">===</span> <span class="s1">&#39;number&#39;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="nx">MAX_TTL</span><span class="p">[</span><span class="nx">extension</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * installServiceWorker
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @returns {Promise}
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">installServiceWorker</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">Promise</span><span class="p">.</span><span class="nx">all</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="nx">caches</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="nx">CACHE_VERSIONS</span><span class="p">.</span><span class="nx">assets</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="nx">then</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                    <span class="p">(</span><span class="nx">cache</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="k">return</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">addAll</span><span class="p">(</span><span class="nx">BASE_CACHE_FILES</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="nx">caches</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="nx">CACHE_VERSIONS</span><span class="p">.</span><span class="nx">offline</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="nx">then</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                    <span class="p">(</span><span class="nx">cache</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="k">return</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">addAll</span><span class="p">(</span><span class="nx">OFFLINE_CACHE_FILES</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="nx">caches</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="nx">CACHE_VERSIONS</span><span class="p">.</span><span class="nx">notFound</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="nx">then</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                    <span class="p">(</span><span class="nx">cache</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="k">return</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">addAll</span><span class="p">(</span><span class="nx">NOT_FOUND_CACHE_FILES</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="cl"><span class="cm"> * cleanupLegacyCache
</span></span></span><span class="line"><span class="cl"><span class="cm"> * @returns {Promise}
</span></span></span><span class="line"><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="cl"><span class="kd">function</span> <span class="nx">cleanupLegacyCache</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">let</span> <span class="nx">currentCaches</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">CACHE_VERSIONS</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="nx">map</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="nx">CACHE_VERSIONS</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="nx">caches</span><span class="p">.</span><span class="nx">keys</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="nx">then</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                    <span class="p">(</span><span class="nx">keys</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="k">return</span> <span class="nx">legacyKeys</span> <span class="o">=</span> <span class="nx">keys</span><span class="p">.</span><span class="nx">filter</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                            <span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                <span class="k">return</span> <span class="o">!~</span><span class="nx">currentCaches</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                            <span class="p">}</span>
</span></span><span class="line"><span class="cl">                        <span class="p">);</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="nx">then</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                    <span class="p">(</span><span class="nx">legacy</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="k">if</span> <span class="p">(</span><span class="nx">legacy</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                            <span class="nb">Promise</span><span class="p">.</span><span class="nx">all</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                <span class="nx">legacy</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                    <span class="p">(</span><span class="nx">legacyKey</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                        <span class="k">return</span> <span class="nx">caches</span><span class="p">.</span><span class="k">delete</span><span class="p">(</span><span class="nx">legacyKey</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                <span class="p">)</span>
</span></span><span class="line"><span class="cl">                            <span class="p">)</span>
</span></span><span class="line"><span class="cl">                                <span class="p">.</span><span class="nx">then</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                    <span class="p">()</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                        <span class="nx">resolve</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">                                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                <span class="p">)</span>
</span></span><span class="line"><span class="cl">                                <span class="p">.</span><span class="k">catch</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                    <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                        <span class="nx">reject</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                <span class="p">);</span>
</span></span><span class="line"><span class="cl">                        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                            <span class="nx">resolve</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">                        <span class="p">}</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="k">catch</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                    <span class="p">()</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="nx">reject</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;install&#39;</span><span class="p">,</span> <span class="nx">event</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">event</span><span class="p">.</span><span class="nx">waitUntil</span><span class="p">(</span><span class="nx">installServiceWorker</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// The activate handler takes care of cleaning up old caches.
</span></span></span><span class="line"><span class="cl"><span class="nx">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;activate&#39;</span><span class="p">,</span> <span class="nx">event</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">event</span><span class="p">.</span><span class="nx">waitUntil</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="nb">Promise</span><span class="p">.</span><span class="nx">all</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                <span class="p">[</span>
</span></span><span class="line"><span class="cl">                    <span class="nx">cleanupLegacyCache</span><span class="p">(),</span>
</span></span><span class="line"><span class="cl">                <span class="p">]</span>
</span></span><span class="line"><span class="cl">            <span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="k">catch</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                    <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="nx">event</span><span class="p">.</span><span class="nx">skipWaiting</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="s1">&#39;fetch&#39;</span><span class="p">,</span> <span class="nx">event</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nx">event</span><span class="p">.</span><span class="nx">respondWith</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="nx">caches</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="nx">CACHE_VERSIONS</span><span class="p">.</span><span class="nx">content</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">.</span><span class="nx">then</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                    <span class="p">(</span><span class="nx">cache</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                        <span class="k">return</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                            <span class="p">.</span><span class="nx">then</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                <span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                                    <span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                                        <span class="kd">let</span> <span class="nx">headers</span> <span class="o">=</span> <span class="nx">response</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">entries</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">                                        <span class="kd">let</span> <span class="nx">date</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                                        <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">pair</span> <span class="k">of</span> <span class="nx">headers</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                            <span class="k">if</span> <span class="p">(</span><span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">===</span> <span class="s1">&#39;date&#39;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                <span class="nx">date</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">(</span><span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">                                            <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                                        <span class="k">if</span> <span class="p">(</span><span class="nx">date</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                            <span class="kd">let</span> <span class="nx">age</span> <span class="o">=</span> <span class="nb">parseInt</span><span class="p">((</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">()</span> <span class="o">-</span> <span class="nx">date</span><span class="p">.</span><span class="nx">getTime</span><span class="p">())</span> <span class="o">/</span> <span class="mi">1000</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                                            <span class="kd">let</span> <span class="nx">ttl</span> <span class="o">=</span> <span class="nx">getTTL</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">.</span><span class="nx">url</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                                            <span class="k">if</span> <span class="p">(</span><span class="nx">ttl</span> <span class="o">&amp;&amp;</span> <span class="nx">age</span> <span class="o">&gt;</span> <span class="nx">ttl</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                                                <span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                                    <span class="p">(</span><span class="nx">resolve</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                                                        <span class="k">return</span> <span class="nx">fetch</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                                                            <span class="p">.</span><span class="nx">then</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                                                <span class="p">(</span><span class="nx">updatedResponse</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                                    <span class="k">if</span> <span class="p">(</span><span class="nx">updatedResponse</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                                        <span class="nx">cache</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">,</span> <span class="nx">updatedResponse</span><span class="p">.</span><span class="nx">clone</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">                                                                        <span class="nx">resolve</span><span class="p">(</span><span class="nx">updatedResponse</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                                                                    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                                        <span class="nx">resolve</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                                                                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                                                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                                            <span class="p">)</span>
</span></span><span class="line"><span class="cl">                                                            <span class="p">.</span><span class="k">catch</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                                                <span class="p">()</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                                    <span class="nx">resolve</span><span class="p">(</span><span class="nx">response</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                                                                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                                            <span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                                                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                                <span class="p">)</span>
</span></span><span class="line"><span class="cl">                                                    <span class="p">.</span><span class="k">catch</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                                        <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                            <span class="k">return</span> <span class="nx">response</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                                                        <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                                    <span class="p">);</span>
</span></span><span class="line"><span class="cl">                                            <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                <span class="k">return</span> <span class="nx">response</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                                            <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                                        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                            <span class="k">return</span> <span class="nx">response</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                                        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                                    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                        <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                            <span class="p">)</span>
</span></span><span class="line"><span class="cl">                            <span class="p">.</span><span class="nx">then</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                <span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                    <span class="k">if</span> <span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                        <span class="k">return</span> <span class="nx">response</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                                    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                        <span class="k">return</span> <span class="nx">fetch</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">)</span> 
</span></span><span class="line"><span class="cl">                                            <span class="p">.</span><span class="nx">then</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                                <span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                                                    <span class="k">if</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">status</span> <span class="o">&lt;</span> <span class="mi">400</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                        <span class="k">if</span> <span class="p">(</span><span class="o">~</span><span class="nx">SUPPORTED_METHODS</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">.</span><span class="nx">method</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="nx">isBlacklisted</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">.</span><span class="nx">url</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                            <span class="nx">cache</span><span class="p">.</span><span class="nx">put</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">request</span><span class="p">,</span> <span class="nx">response</span><span class="p">.</span><span class="nx">clone</span><span class="p">());</span>
</span></span><span class="line"><span class="cl">                                                        <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                                        <span class="k">return</span> <span class="nx">response</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                                                    <span class="p">}</span> 
</span></span><span class="line"><span class="cl">                                                    <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                        <span class="k">return</span> <span class="nx">caches</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="nx">CACHE_VERSIONS</span><span class="p">.</span><span class="nx">notFound</span><span class="p">).</span><span class="nx">then</span><span class="p">((</span><span class="nx">cache</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                            <span class="k">return</span> <span class="nx">cache</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">NOT_FOUND_PAGE</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                                                        <span class="p">})</span>
</span></span><span class="line"><span class="cl">                                                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                            <span class="p">)</span>
</span></span><span class="line"><span class="cl">                                            <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">response</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                <span class="k">if</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                    <span class="k">return</span> <span class="nx">response</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                                                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                            <span class="p">})</span>
</span></span><span class="line"><span class="cl">                                            <span class="p">.</span><span class="k">catch</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                                <span class="p">()</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                                                    <span class="k">return</span> <span class="nx">caches</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="nx">CACHE_VERSIONS</span><span class="p">.</span><span class="nx">offline</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                                                        <span class="p">.</span><span class="nx">then</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                                            <span class="p">(</span><span class="nx">offlineCache</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                                                <span class="k">return</span> <span class="nx">offlineCache</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">OFFLINE_PAGE</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                                                            <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                                        <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">                                                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                            <span class="p">)</span>
</span></span><span class="line"><span class="cl">                                        
</span></span><span class="line"><span class="cl">                                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                            <span class="p">)</span>
</span></span><span class="line"><span class="cl">                            <span class="p">.</span><span class="k">catch</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                                <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                                    <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="s1">&#39;  Error in fetch handler:&#39;</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                                    <span class="k">throw</span> <span class="nx">error</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                                <span class="p">}</span>
</span></span><span class="line"><span class="cl">                            <span class="p">);</span>
</span></span><span class="line"><span class="cl">                    <span class="p">}</span>
</span></span><span class="line"><span class="cl">                <span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">);</span>
</span></span></code></pre></div>]]></content:encoded>
    </item>
    
    <item>
      <title>Format Hugo markdown and code</title>
      <link>https://techformist.com/format-hugo-markdown-code/</link>
      <pubDate>Fri, 09 Aug 2019 06:30:00 +0000</pubDate>
      
      <guid>https://techformist.com/format-hugo-markdown-code/</guid>
      <description>&lt;p&gt;Format your markdown using &lt;code&gt;prettier&lt;/code&gt; and you are off to the races.&lt;/p&gt;
&lt;p&gt;Hugo static site generator keeps everything simple. I just love the power of typing in something in markdown, and seeing the finished HTML pages and blog formatted to specs (in no time, I might add).&lt;/p&gt;
&lt;p&gt;I use VSCode for writing markdown text. This works out beautifully - I can save markdown files and prettier kicks in to format everything - the markdown within those files and the code within markdown.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Format your markdown using <code>prettier</code> and you are off to the races.</p>
<p>Hugo static site generator keeps everything simple. I just love the power of typing in something in markdown, and seeing the finished HTML pages and blog formatted to specs (in no time, I might add).</p>
<p>I use VSCode for writing markdown text. This works out beautifully - I can save markdown files and prettier kicks in to format everything - the markdown within those files and the code within markdown.</p>
<h3 id="why-use-vscode">Why use VSCode?</h3>
<p>I keep markdown and code typing similar - no brain-freeze. And, the formatting is a huge bonus as you see below.</p>
<p>What I type -</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-md" data-lang="md"><span class="line"><span class="cl"><span class="gu">###   Header 3
</span></span></span><span class="line"><span class="cl"> Hello World
</span></span><span class="line"><span class="cl">``<span class="sb">`js
</span></span></span><span class="line"><span class="cl"><span class="sb">  if (true){
</span></span></span><span class="line"><span class="cl"><span class="sb">console.log(&#34;hello world&#34;)
</span></span></span><span class="line"><span class="cl"><span class="sb">}
</span></span></span><span class="line"><span class="cl"><span class="sb">  `</span>``
</span></span></code></pre></div><p>What the content gets automatically formatted to -</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-md" data-lang="md"><span class="line"><span class="cl"><span class="gu">### Header 3
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Hello World
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="s">```js
</span></span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&#34;hello world&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="s">```</span>
</span></span></code></pre></div><p>You may see that -</p>
<ul>
<li><code>###</code> line has extra spaces removed</li>
<li>a blank line has been added between header and content</li>
<li>another blank line added between content and the beginning of code block</li>
<li>the <code>js</code> block has been changed to -
<ul>
<li>format <code>if</code> statement as a code-block</li>
<li>semicolons at logical end</li>
</ul>
</li>
</ul>
<p>If you have been typing in markdown, you would have recognized how valuable adding blank line can be. While it is easier for prettier, markdown does not &ldquo;see&rdquo; what you meant and format the entire block of content in an altogether different way.</p>
<p>Another crucial advantage for me - I can type in code-blocks within markdown and let it automatically format. I also get to know any silly mistakes (e.g. a bracket not closed) since Prettier parser will not format the code.</p>
<h3 id="the-alternative">The Alternative</h3>
<p>If VSCode is working so well with a couple of extensions, why change that? Two reasons -</p>
<ol>
<li>I had been trying to make my workflow even more seamless</li>
<li>VSCode gobbles up a lot of memory. I want to minimise stuff I do on VSCode other than main-stream programming. Obviously all those windows are going to be open all the time, which is a big problem</li>
</ol>
<p>I wanted to retain VSCode&rsquo;s fantastic formatting support, and I can do that in just a couple of steps - thanks to Hugo.</p>
<ol>
<li>Go to your Hugo site root directory</li>
<li>If your theme does not use any kind of packages today - do <code>npm init</code>. (in other words, ignore this step if you already have <code>package.json</code> in your Hugo site root directory)</li>
<li>Install husky, lint-staged, and prettier packages -
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmd" data-lang="cmd"><span class="line"><span class="cl">  npm install husky lint-staged prettier
</span></span></code></pre></div></li>
<li>Change your <code>package.json</code> to-
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;scripts&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;precommit&#34;</span><span class="p">:</span> <span class="s2">&#34;lint-staged&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;lint-staged&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;*.md&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;prettier --parser markdown --write&#34;</span><span class="p">,</span> <span class="s2">&#34;git add&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></li>
</ol>
<p>We parse markdown file with <code>lint-staged</code> and use <code>prettier</code> to format files. <code>husky</code> enables us to prevent accidental commits before running pre-commit hook.</p>
<p>That&rsquo;s it - now you can see your files nicely formatted no matter which editor you use.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Web Inspector to design static sites</title>
      <link>https://techformist.com/web-inspector-to-design-static-sites/</link>
      <pubDate>Wed, 06 Feb 2019 15:30:00 +0000</pubDate>
      
      <guid>https://techformist.com/web-inspector-to-design-static-sites/</guid>
      <description>&lt;p&gt;Chrome and Firefox web inspectors are my new best friends in my quest to develop static sites. I never took the time to appreciate the complete power of web inspection - until I actually started changing the design of this very site.&lt;/p&gt;
&lt;p&gt;I have been redesigning &lt;a href=&#34;https://techformist.com&#34;&gt;techformist.com&lt;/a&gt; website on Hugo. The plan is to migrate from Jekyll and design a simpler site that can easily showcase what I have to offer (ahem..).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Chrome and Firefox web inspectors are my new best friends in my quest to develop static sites. I never took the time to appreciate the complete power of web inspection - until I actually started changing the design of this very site.</p>
<p>I have been redesigning <a href="https://techformist.com">techformist.com</a> website on Hugo. The plan is to migrate from Jekyll and design a simpler site that can easily showcase what I have to offer (ahem..).</p>
<p>While there are excellent ways to develop Go templates on my own, I always appreciate the opportunity to stand on the shoulders of giants. I selected the <a href="https://minimo.netlify.com/">Minimo theme</a> for the purpose and started customizing CSS alongside a few changes in the layouts and templates.</p>
<p>It was then and only then I could completely and deeply commit myself to the inspectors.</p>
<p>You see - all of my &lsquo;professional&rsquo; web development life has been spent using UI standards and libraries like Materialize, Bulma and Bootstrap. These offer a million ways of personalizing stuff but, at the same time, stay abstract from targeting CSS changes for specific, individual elements / ids / classes.</p>
<p>This changed when I started personalizing fonts, colours, borders et. al. on a static site theme like Minimo that did not use these standards. I had to start identifying the individual tags, ids and elements in the CSS path so that they can be over-ridden in <code>custom.css</code> file provided by the theme.</p>
<p>While this seemed trivial from my experience with other themes, Minimo had a slightly different approach and had an arguably better hierarchical structure in CSS. (Actually, the theme used SCSS that I did not bother to override, I chose the easier path.)</p>
<p>After about 10 minutes of wrangling with elements, I was seriously contemplating on switching to another generator altogether. It was then I started using the web inspector in the way it was supposed to be used.</p>
<p>Click, find CSS path and use the path in <code>custom.css</code> to override the style. This was so efficient and easy.</p>
<p>In a span of 4-6 hours over 2 days I had done multiple iterations of the site including a few template/layout changes. What you see may be that, or may be a few more changes. The point is - such changes to styles on a SSG is much much more simplified if you use web inspector.</p>
<p>But wait - that is not my final advice. If I would redo anything, I would probably use a starter theme based on Bulma or Tailwind and start customizing from that baseline. I believe that will be an easier, more intuitive customization option than the &ldquo;start from scratch&rdquo; approach.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Copy/paste Datatable Issues in Hugo</title>
      <link>https://techformist.com/copy-paste-datatable-issues-in-hugo/</link>
      <pubDate>Fri, 26 Oct 2018 15:38:00 +0000</pubDate>
      
      <guid>https://techformist.com/copy-paste-datatable-issues-in-hugo/</guid>
      <description>&lt;p&gt;It is interesting how the minor things eat away a lot of your time. Especially if you happen to be like me, one of the greater idiots on a planet full of idiots.&lt;/p&gt;
&lt;p&gt;One of the days, I had to create website really fast to demonstrate to a potential customer. I abandoned my dear old friend Jekyll since - well, I had to create something in Hugo.&lt;/p&gt;
&lt;p&gt;There was a requirement to show a data list (phone numbers and some related information) on one of the pages.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>It is interesting how the minor things eat away a lot of your time. Especially if you happen to be like me, one of the greater idiots on a planet full of idiots.</p>
<p>One of the days, I had to create website really fast to demonstrate to a potential customer. I abandoned my dear old friend Jekyll since - well, I had to create something in Hugo.</p>
<p>There was a requirement to show a data list (phone numbers and some related information) on one of the pages.</p>
<pre tabindex="0"><code>|Phone | Active|
|+91 1029292122 | Y|
|+91 1298329929 | Y|
|+91 1192389292 | Y|
</code></pre><p>Easy enough.</p>
<p>But, this data had to be changed by the end user - who is not super computer-savvy) and does not want to mess around with templates or <code>md</code> files.</p>
<p>There is Hugo feature called <a href="https://gohugo.io/templates/data-templates/#data-driven-content">Data Driven Content</a> to help in those situations.</p>
<p>So this..</p>
<h4 id="step-1">Step 1:</h4>
<p>Create CSV file in the static (static/csv) under my root folder.</p>
<h4 id="step-2">Step 2:</h4>
<p>Create a new partial in <code>Layouts</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">section</span> <span class="na">id</span><span class="o">=</span><span class="s">&#34;basic-content&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;container&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="nx">$</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">ready</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">$</span><span class="p">(</span><span class="s2">&#34;#csvnum&#34;</span><span class="p">).</span><span class="nx">dataTable</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">      <span class="p">});</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">table</span>
</span></span><span class="line"><span class="cl">      <span class="na">id</span><span class="o">=</span><span class="s">&#34;csvnum&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="na">class</span><span class="o">=</span><span class="s">&#34;table table-striped table-bordered&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="na">style</span><span class="o">=</span><span class="s">&#34;width:100%&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">thead</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">th</span><span class="p">&gt;</span>Phone<span class="p">&lt;/</span><span class="nt">th</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">th</span><span class="p">&gt;</span>Active<span class="p">&lt;/</span><span class="nt">th</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">thead</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">tbody</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        {{ $url := &#34;static/csv/phone_active.csv&#34; }} {{ $sep := &#34;,&#34; }} {{ range
</span></span><span class="line"><span class="cl">        $i, $r := getCSV $sep $url }}
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">tr</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;</span>{{ index $r 0 }}<span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">td</span><span class="p">&gt;</span>{{ index $r 1 }}<span class="p">&lt;/</span><span class="nt">td</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">tr</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        {{ end }}
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">tbody</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">table</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">section</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>So far so good. Except, the outcome isn&rsquo;t anything but what I expect.</p>
<p>I get following errors depending on whether I refresh the browser during an even second or an odd second.</p>
<pre tabindex="0"><code>TypeError: c is undefined
</code></pre><p>OR</p>
<pre tabindex="0"><code>TypeError: col is undefined
</code></pre><p>I don&rsquo;t claim to be an expert on JS, but did a fair bit of debugging here. My interim thoughts were focused on investigating how <code>$(document).ready</code> was called even though the data was not ready yet. I assumed this was the sole reason since the static table was getting rendered but the data from file wasn&rsquo;t. What other reason could there be?</p>
<p>It turns out there are many valid reasons for the problem. And, I should not blame the collective wisdom of Javascript at every second error.</p>
<p>Excel and some formatting issues had introduced a third phantom column in the CSV. For good or for worse (mostly the latter), this did not show up in Excel, or in Notepad.</p>
<p>Datatable was all weird since <code>&lt;th&gt;</code> defines two columns while <code>&lt;td&gt;</code> has three.</p>
<p>The debugging of this problem should have ideally taken less than five minutes, and there I was exploring why the data table would not work after two hours of reading email, debugging stuff, checking Feedly, and so forth.</p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
