950 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			950 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!doctype html>
 | ||
| <head><script src="/livereload.js?mindelay=10&v=2&port=1313&path=livereload" data-no-instant defer></script>
 | ||
|   
 | ||
|   
 | ||
|   
 | ||
|   <link rel="stylesheet" href="http://localhost:1313/css/main.min.f77a4050bafcd273d43d6737e174f344bd91a213d9bc92b097cb31fc7dbe1cb9.css">
 | ||
| </head>
 | ||
| <html lang="en">
 | ||
|   
 | ||
| <head>
 | ||
|   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 | ||
|   <meta name="theme-color" media="(prefers-color-scheme: light)" content="#f7f7f7">
 | ||
|   <meta name="theme-color" media="(prefers-color-scheme: dark)" content="#1b1b1e">
 | ||
|   <meta name="mobile-web-app-capable" content="yes">
 | ||
|   <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
 | ||
|   <meta
 | ||
|     name="viewport"
 | ||
|     content="width=device-width, user-scalable=no, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"
 | ||
|   >
 | ||
| 
 | ||
|   <meta property="og:url" content="http://localhost:1313/about/">
 | ||
|   <meta property="og:site_name" content="Comprofix">
 | ||
|   <meta property="og:title" content="About">
 | ||
|   <meta property="og:description" content="Chirpy is a blog theme originally based on Jekyll. Due to Jekyll’s design limitations, it does not natively support internationalization (i18n) and requires third-party plugins for i18n functionality. To enable i18n support for Chirpy without the hassle of relying on third-party plugins, the hugo-theme-chirpy project migrated the Chirpy theme to Hugo with minimal adaptations. All features of Chirpy are available in hugo-theme-chirpy (though some functionalities may operate differently within the Hugo framework).
 | ||
| Follow the posts in the demo site to quickly set up a free personal blog!">
 | ||
|   <meta property="og:locale" content="en">
 | ||
|   <meta property="og:type" content="article">
 | ||
|     <meta property="article:published_time" content="2023-04-20T00:00:00+00:00">
 | ||
|     <meta property="article:modified_time" content="2023-04-20T00:00:00+00:00">
 | ||
| 
 | ||
|   
 | ||
|   <meta name="twitter:card" content="summary">
 | ||
|   <meta name="twitter:title" content="About">
 | ||
|   <meta name="twitter:description" content="Chirpy is a blog theme originally based on Jekyll. Due to Jekyll’s design limitations, it does not natively support internationalization (i18n) and requires third-party plugins for i18n functionality. To enable i18n support for Chirpy without the hassle of relying on third-party plugins, the hugo-theme-chirpy project migrated the Chirpy theme to Hugo with minimal adaptations. All features of Chirpy are available in hugo-theme-chirpy (though some functionalities may operate differently within the Hugo framework).
 | ||
| Follow the posts in the demo site to quickly set up a free personal blog!">
 | ||
| 
 | ||
|   
 | ||
|   <meta itemprop="name" content="About">
 | ||
|   <meta itemprop="description" content="Chirpy is a blog theme originally based on Jekyll. Due to Jekyll’s design limitations, it does not natively support internationalization (i18n) and requires third-party plugins for i18n functionality. To enable i18n support for Chirpy without the hassle of relying on third-party plugins, the hugo-theme-chirpy project migrated the Chirpy theme to Hugo with minimal adaptations. All features of Chirpy are available in hugo-theme-chirpy (though some functionalities may operate differently within the Hugo framework).
 | ||
| Follow the posts in the demo site to quickly set up a free personal blog!">
 | ||
|   <meta itemprop="datePublished" content="2023-04-20T00:00:00+00:00">
 | ||
|   <meta itemprop="dateModified" content="2023-04-20T00:00:00+00:00">
 | ||
|   <meta itemprop="wordCount" content="171">
 | ||
| 
 | ||
|   <title>
 | ||
|     
 | ||
|       About | 
 | ||
|     
 | ||
|     Comprofix
 | ||
|   </title>
 | ||
| 
 | ||
|   <link rel="apple-touch-icon" sizes="180x180" href="/img/favicons/apple-touch-icon.png">
 | ||
| <link rel="icon" type="image/png" sizes="32x32" href="/img/favicons/favicon-32x32.png">
 | ||
| <link rel="icon" type="image/png" sizes="16x16" href="/img/favicons/favicon-16x16.png">
 | ||
| 
 | ||
| <link rel="shortcut icon" href="/img/favicons/favicon.ico">
 | ||
| <meta name="apple-mobile-web-app-title" content="Comprofix">
 | ||
| <meta name="application-name" content="Comprofix">
 | ||
| <meta name="msapplication-TileColor" content="#da532c">
 | ||
| <meta name="msapplication-config" content="/img/favicons/browserconfig.xml">
 | ||
| <meta name="theme-color" content="#ffffff">
 | ||
| 
 | ||
|   
 | ||
|   
 | ||
|     
 | ||
|       
 | ||
|       
 | ||
|         <link rel="preconnect" href="https://fonts.googleapis.com" >
 | ||
|       
 | ||
|         <link rel="dns-prefetch" href="https://fonts.googleapis.com" >
 | ||
|       
 | ||
|     
 | ||
|       
 | ||
|       
 | ||
|         <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
 | ||
|       
 | ||
|         <link rel="dns-prefetch" href="https://fonts.gstatic.com" >
 | ||
|       
 | ||
|     
 | ||
|       
 | ||
|       
 | ||
|         <link rel="preconnect" href="https://cdn.jsdelivr.net" >
 | ||
|       
 | ||
|         <link rel="dns-prefetch" href="https://cdn.jsdelivr.net" >
 | ||
|       
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|   
 | ||
|     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|   
 | ||
|   
 | ||
|   
 | ||
|   <link rel="stylesheet" href="http://localhost:1313/css/main.min.f77a4050bafcd273d43d6737e174f344bd91a213d9bc92b097cb31fc7dbe1cb9.css">
 | ||
| 
 | ||
|   
 | ||
|   <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400&family=Source+Sans+Pro:wght@400;600;700;900&display=swap">
 | ||
| 
 | ||
|   
 | ||
|   <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.7.1/css/all.min.css">
 | ||
| 
 | ||
|   
 | ||
|   
 | ||
|     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tocbot@4.32.2/dist/tocbot.min.css">
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     <link rel="stylesheet" href="/">
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/glightbox@3.3.0/dist/css/glightbox.min.css">
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|   <script src="/js/modules/theme.js"></script>
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|     
 | ||
|       
 | ||
|     
 | ||
|     
 | ||
|       
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|       
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|   <script src="https://cdn.jsdelivr.net/npm/glightbox@3.3.0/dist/js/glightbox.min.js"></script>
 | ||
| 
 | ||
|   <script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js"></script>
 | ||
| 
 | ||
|   <script src="https://cdn.jsdelivr.net/npm/tocbot@4.32.2/dist/tocbot.min.js"></script>
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|   
 | ||
| <script defer src="/js/page.js"></script>
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
| </head>
 | ||
|   <body>
 | ||
|     
 | ||
| <aside aria-label="Sidebar" id="sidebar" class="d-flex flex-column align-items-end">
 | ||
|   <header class="profile-wrapper">
 | ||
|     <a href="/" id="avatar" class="rounded-circle"><img src="/img/man-logo.png" width="112" height="112" alt="avatar" onerror="this.style.display='none'"></a>
 | ||
| 
 | ||
|     <a class="site-title d-block" href="/">Comprofix</a>
 | ||
|     
 | ||
|       <p class="site-subtitle fst-italic mb-0">Geek | Nerd | Systems Administrator | IT Specialist</p>
 | ||
|     
 | ||
|   </header>
 | ||
|   
 | ||
| 
 | ||
|   <nav class="flex-column flex-grow-1 w-100 ps-0">
 | ||
|     <ul class="nav">
 | ||
|       
 | ||
|         
 | ||
|         
 | ||
|         <li class="nav-item">
 | ||
|           <a href="/" class="nav-link">
 | ||
|             <i class="fa-fw fas fa-house"></i>
 | ||
|             <span>HOME</span>
 | ||
|           </a>
 | ||
|         </li>
 | ||
|         
 | ||
|       
 | ||
|         
 | ||
|         
 | ||
|         <li class="nav-item">
 | ||
|           <a href="/categories/" class="nav-link">
 | ||
|             <i class="fa-fw fas fa-stream"></i>
 | ||
|             <span>CATEGORIES</span>
 | ||
|           </a>
 | ||
|         </li>
 | ||
|         
 | ||
|       
 | ||
|         
 | ||
|         
 | ||
|         <li class="nav-item">
 | ||
|           <a href="/tags/" class="nav-link">
 | ||
|             <i class="fa-fw fas fa-tags"></i>
 | ||
|             <span>TAGS</span>
 | ||
|           </a>
 | ||
|         </li>
 | ||
|         
 | ||
|       
 | ||
|         
 | ||
|         
 | ||
|         <li class="nav-item">
 | ||
|           <a href="/archives/" class="nav-link">
 | ||
|             <i class="fa-fw fas fa-archive"></i>
 | ||
|             <span>ARCHIVES</span>
 | ||
|           </a>
 | ||
|         </li>
 | ||
|         
 | ||
|       
 | ||
|         
 | ||
|         
 | ||
|           
 | ||
|         
 | ||
|         <li class="nav-item active">
 | ||
|           <a href="/about/" class="nav-link">
 | ||
|             <i class="fa-fw fas fa-info-circle"></i>
 | ||
|             <span>ABOUT</span>
 | ||
|           </a>
 | ||
|         </li>
 | ||
|         
 | ||
|       
 | ||
| 
 | ||
|       
 | ||
|     </ul>
 | ||
|   </nav>
 | ||
| 
 | ||
|   <div class="sidebar-bottom d-flex flex-wrap align-items-center w-100">
 | ||
|     
 | ||
|       <button type="button" class="btn btn-link nav-link" aria-label="Switch Mode" id="mode-toggle">
 | ||
|         <i class="fas fa-adjust"></i>
 | ||
|       </button>
 | ||
| 
 | ||
|       
 | ||
|         <span class="icon-border"></span>
 | ||
|       
 | ||
|     
 | ||
| 
 | ||
|     
 | ||
|       
 | ||
|       
 | ||
| 
 | ||
|       
 | ||
|         
 | ||
|       
 | ||
| 
 | ||
|       
 | ||
|         <a
 | ||
|           href="https://git.comprofix.com/mmckinnon"
 | ||
|           aria-label="custom"
 | ||
|           target="_blank" rel="noopener noreferrer"
 | ||
|           
 | ||
|         >
 | ||
|           <i class="fab fa-git-alt"></i>
 | ||
|         </a>
 | ||
|       
 | ||
|     
 | ||
|       
 | ||
|       
 | ||
| 
 | ||
|       
 | ||
|         
 | ||
|       
 | ||
| 
 | ||
|       
 | ||
|         <a
 | ||
|           href="https://twitter.com/mckinnon81"
 | ||
|           aria-label="twitter"
 | ||
|           target="_blank" rel="noopener noreferrer"
 | ||
|           
 | ||
|         >
 | ||
|           <i class="fab fa-twitter"></i>
 | ||
|         </a>
 | ||
|       
 | ||
|     
 | ||
|       
 | ||
|       
 | ||
| 
 | ||
|       
 | ||
|         
 | ||
|       
 | ||
| 
 | ||
|       
 | ||
|         <a
 | ||
|           href="http://localhost:1313/index.xml"
 | ||
|           aria-label="rss"
 | ||
|           
 | ||
|           
 | ||
|         >
 | ||
|           <i class="fas fa-rss"></i>
 | ||
|         </a>
 | ||
|       
 | ||
|     
 | ||
|   </div>
 | ||
|   
 | ||
| </aside>
 | ||
| 
 | ||
|     <div id="main-wrapper" class="d-flex justify-content-center">
 | ||
|       <div class="container d-flex flex-column px-xxl-5">
 | ||
|         
 | ||
| <header id="topbar-wrapper" class="flex-shrink-0" aria-label="Top Bar">
 | ||
|   <div id="topbar" class="d-flex align-items-center justify-content-between px-lg-3 h-100">
 | ||
|     <nav id="breadcrumb" aria-label="Breadcrumb">
 | ||
|       
 | ||
|       
 | ||
|       
 | ||
|       
 | ||
| 
 | ||
|       
 | ||
|         <span>
 | ||
|           <a href="/">Home</a>
 | ||
|         </span>
 | ||
|         
 | ||
|         
 | ||
|           
 | ||
|           
 | ||
|             
 | ||
|           
 | ||
|             
 | ||
|           
 | ||
|             
 | ||
|           
 | ||
|             
 | ||
|           
 | ||
|             
 | ||
|               
 | ||
|             
 | ||
|           
 | ||
| 
 | ||
|           
 | ||
|           
 | ||
|             <span>About</span>
 | ||
|           
 | ||
| 
 | ||
| 
 | ||
|         
 | ||
|       
 | ||
|     </nav>
 | ||
|     
 | ||
| 
 | ||
|     <button type="button" id="sidebar-trigger" class="btn btn-link" aria-label="Sidebar">
 | ||
|       <i class="fas fa-bars fa-fw"></i>
 | ||
|     </button>
 | ||
| 
 | ||
|     <div id="topbar-title">
 | ||
|       About
 | ||
|     </div>
 | ||
| 
 | ||
|     <button type="button" id="search-trigger" class="btn btn-link" aria-label="Search">
 | ||
|       <i class="fas fa-search fa-fw"></i>
 | ||
|     </button>
 | ||
| 
 | ||
|     <search id="search" class="align-items-center ms-3 ms-lg-0">
 | ||
|       <i class="fas fa-search fa-fw"></i>
 | ||
|       <input
 | ||
|         class="form-control"
 | ||
|         id="search-input"
 | ||
|         type="search"
 | ||
|         aria-label="search"
 | ||
|         autocomplete="off"
 | ||
|         placeholder="Search..."
 | ||
|       >
 | ||
|     </search>
 | ||
|     <button type="button" class="btn btn-link text-decoration-none" id="search-cancel">Cancel</button>
 | ||
|   </div>
 | ||
| </header>
 | ||
|         <div class="row flex-grow-1">
 | ||
|           <main aria-label="Main Content" class="col-12 col-lg-11 col-xl-9 px-md-4">
 | ||
|             
 | ||
|   <article class="px-1">
 | ||
|     
 | ||
|       
 | ||
|       
 | ||
|       <h1 class="dynamic-title">
 | ||
|         About
 | ||
|       </h1>
 | ||
|       <div class="content">
 | ||
|         <p><a href="https://github.com/cotes2020/jekyll-theme-chirpy">Chirpy</a> is a blog theme originally based on <a href="https://jekyllrb.com/">Jekyll</a>. Due to Jekyll’s design limitations, it does not natively support internationalization (i18n) and requires third-party plugins for i18n functionality. To enable i18n support for Chirpy without the hassle of relying on third-party plugins, the <a href="https://github.com/geekifan/hugo-theme-chirpy">hugo-theme-chirpy</a> project migrated the Chirpy theme to <a href="https://gohugo.io/">Hugo</a> with minimal adaptations. All features of Chirpy are available in hugo-theme-chirpy (though some functionalities may operate differently within the Hugo framework).</p>
 | ||
| <p>Follow the posts in the demo site to quickly set up a free personal blog!</p>
 | ||
| <h2 id="features" id=features>
 | ||
|   
 | ||
|     <span class="me-2">Features</span>
 | ||
|     <a href="#features" class="anchor text-muted"><i class="fas fa-hashtag"></i></a>
 | ||
|   
 | ||
| </h2><ul>
 | ||
| <li><strong>Dark Mode</strong>: Enhanced readability in low-light environments.</li>
 | ||
| <li><strong>Multilingual UI:</strong> Easily switch between different languages.</li>
 | ||
| <li><strong>Efficient Post Organization:</strong> Use hierarchical categories, trending tags, recommended reading, and search functionalities.</li>
 | ||
| <li><strong>Optimized Layout:</strong> Includes TOC, syntax highlighting, prompts, and more.</li>
 | ||
| <li><strong>Rich Writing Extensions:</strong> Support for mathematical formulas, charts, flowcharts, and embedded media.</li>
 | ||
| <li><strong>Multiple Comment Systems:</strong> Choose from various commenting options.</li>
 | ||
| <li><strong>Web Analysis Tools:</strong> Integrated with multiple analytics tools.</li>
 | ||
| <li><strong>Modern Web Technologies:</strong> Built for SEO and web performance.</li>
 | ||
| <li><strong>RSS Feed Support:</strong> Keep your readers updated with RSS feeds.</li>
 | ||
| </ul>
 | ||
| 
 | ||
|       </div>
 | ||
|     
 | ||
|   </article>
 | ||
| 
 | ||
|           </main>
 | ||
| 
 | ||
|           
 | ||
|           <aside aria-label="Panel" id="panel-wrapper" class="col-xl-3 ps-2 text-muted">
 | ||
|             <div class="access">
 | ||
|               
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|   
 | ||
|   
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|   
 | ||
|   
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|   <section id="access-lastmod">
 | ||
|     <h2 class="panel-heading">Recently Updated</h2>
 | ||
|     <ul class="content list-unstyled ps-0 pb-1 ms-1 mt-2">
 | ||
|       
 | ||
|         
 | ||
|         
 | ||
|         
 | ||
|         <li class="text-truncate lh-lg">
 | ||
|           <a href="/post/2024-09-21-websitedeployment/">Continuous Integration & Continuous Deployment</a>
 | ||
|         </li>
 | ||
|       
 | ||
|         
 | ||
|         
 | ||
|         
 | ||
|         <li class="text-truncate lh-lg">
 | ||
|           <a href="/post/2024-09-05-resetrestart/">Reset and Restart</a>
 | ||
|         </li>
 | ||
|       
 | ||
|     </ul>
 | ||
|   </section>
 | ||
|   
 | ||
| 
 | ||
|               
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|   <section>
 | ||
|     <h2 class="panel-heading">Trending Tags</h2>
 | ||
|     <div class="d-flex flex-wrap mt-3 mb-1 me-3">
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/cd/">cd</a>
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/ci/">ci</a>
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/continuous-deployment/">continuous deployment</a>
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/continuous-integration/">continuous integration</a>
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/docker/">docker</a>
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/git/">git</a>
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/homelab/">homelab</a>
 | ||
|       
 | ||
|     </div>
 | ||
|   </section>
 | ||
| 
 | ||
|             </div>
 | ||
|             
 | ||
|           </aside>
 | ||
|         </div>
 | ||
| 
 | ||
|         <div class="row">
 | ||
|           
 | ||
|           <div id="tail-wrapper" class="col-12 col-lg-11 col-xl-9 px-md-4">
 | ||
|             
 | ||
|             
 | ||
| <footer
 | ||
|   aria-label="Site Info"
 | ||
|   class="
 | ||
|     d-flex flex-column justify-content-center text-muted
 | ||
|     flex-lg-row justify-content-lg-between align-items-lg-center pb-lg-3
 | ||
|   "
 | ||
| >
 | ||
|   <p>
 | ||
|     ©
 | ||
|     <time>2025</time>
 | ||
| 
 | ||
|     
 | ||
|       
 | ||
|         <a href="https://comprofix.com">Comprofix</a>.
 | ||
|       
 | ||
|     
 | ||
| 
 | ||
|     <span
 | ||
|       data-bs-toggle="tooltip"
 | ||
|       data-bs-placement="top"
 | ||
|       title="Except where otherwise noted, the blog posts on this site are licensed under the Creative Commons Attribution 4.0 International (CC BY 4.0) License by the author."
 | ||
|     >Some rights reserved.</span>
 | ||
|   </p>
 | ||
| 
 | ||
|   <p>Using the <a
 | ||
|         data-bs-toggle="tooltip"
 | ||
|         data-bs-placement="top"
 | ||
|         title="v1.0.2"
 | ||
|         href="https://github.com/geekifan/hugo-theme-chirpy"
 | ||
|         target="_blank"
 | ||
|         rel="noopener"
 | ||
|       >Chirpy</a> theme for <a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a>.
 | ||
|   </p>
 | ||
| </footer>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|         <div id="search-result-wrapper" class="d-flex justify-content-center d-none">
 | ||
|   <div class="col-11 content">
 | ||
|     <div id="search-hints">
 | ||
|       
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
|   
 | ||
|     
 | ||
|   
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|   <section>
 | ||
|     <h2 class="panel-heading">Trending Tags</h2>
 | ||
|     <div class="d-flex flex-wrap mt-3 mb-1 me-3">
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/cd/">cd</a>
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/ci/">ci</a>
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/continuous-deployment/">continuous deployment</a>
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/continuous-integration/">continuous integration</a>
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/docker/">docker</a>
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/git/">git</a>
 | ||
|       
 | ||
|         
 | ||
|         <a class="post-tag btn btn-outline-primary" href="http://localhost:1313/tags/homelab/">homelab</a>
 | ||
|       
 | ||
|     </div>
 | ||
|   </section>
 | ||
| 
 | ||
|     </div>
 | ||
|     <div id="search-results" class="d-flex flex-wrap justify-content-center text-muted mt-3"></div>
 | ||
|   </div>
 | ||
| </div>
 | ||
| 
 | ||
| <script>
 | ||
|   const DEFAULT_CONFIG = {
 | ||
|     search: {
 | ||
|       minChars: 1,              
 | ||
|       maxResults: 5,            
 | ||
|       fields: {                 
 | ||
|         title: true,
 | ||
|         description: true,
 | ||
|         section: true,
 | ||
|         contents: true
 | ||
|       },
 | ||
|       
 | ||
|       strictMode: true          
 | ||
|     }
 | ||
|   };
 | ||
| 
 | ||
|   class FastSearch {
 | ||
|     constructor({
 | ||
|       searchInput, resultsContainer, json,
 | ||
|       searchResultTemplate = null,
 | ||
|       noResultsText = null,
 | ||
|     }) {
 | ||
|       this.searchInput = searchInput;
 | ||
|       this.resultsContainer = resultsContainer;
 | ||
|       this.json = json;
 | ||
|       this.searchResultTemplate = searchResultTemplate;
 | ||
|       this.noResultsText = noResultsText;
 | ||
|       
 | ||
|       this.init();
 | ||
|     }
 | ||
| 
 | ||
|     init() {
 | ||
|       this.loadSearchIndex();
 | ||
|       this.searchInput.addEventListener('input', (event) => {
 | ||
|         if (!this.searchIndex) {
 | ||
|           this.resultsContainer.innerHTML = '<li class="search-message">Loading search index...</li>';
 | ||
|           return;
 | ||
|         }
 | ||
|         this.performSearch(this.searchInput.value);
 | ||
|       });
 | ||
|     }
 | ||
| 
 | ||
|     
 | ||
|     async loadSearchIndex() {
 | ||
|       try {
 | ||
|         const response = await fetch(this.json);
 | ||
|         if (!response.ok) throw new Error('Failed to load search index');
 | ||
|         const data = await response.json();
 | ||
|         
 | ||
|         this.searchIndex = data.map(item => ({
 | ||
|           ...item,
 | ||
|           
 | ||
|           searchableTitle: item.title?.toLowerCase() || '',
 | ||
|           searchableDesc: item.desc?.toLowerCase() || '',
 | ||
|           searchableSection: item.section?.toLowerCase() || '',
 | ||
|           searchableContents: item.contents?.toLowerCase() || ''
 | ||
|         }));
 | ||
|         } catch (error) {
 | ||
|           console.error('Error loading search index:', error);
 | ||
|         this.resultsContainer.innerHTML = '<li class="search-message">Error loading search index...</li>';
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     escapeHtml(unsafe) {
 | ||
|       if (!unsafe) return '';
 | ||
|       return unsafe
 | ||
|         .replace(/&/g, "&")
 | ||
|         .replace(/</g, "<")
 | ||
|         .replace(/>/g, ">")
 | ||
|         .replace(/"/g, """)
 | ||
|         .replace(/'/g, "'");
 | ||
|     }
 | ||
|     
 | ||
|     
 | ||
|     containsTerm(text, term) {
 | ||
|       if (!text || !term) return false;
 | ||
|       return text.includes(term);
 | ||
|     }
 | ||
| 
 | ||
|     performSearch(query) {
 | ||
|       
 | ||
|       query = query.toLowerCase().trim();
 | ||
|       
 | ||
|       
 | ||
|       if (!query || !this.searchIndex || query.length < DEFAULT_CONFIG.search.minChars) {
 | ||
|         this.resultsContainer.innerHTML = '';
 | ||
|         return;
 | ||
|       }
 | ||
| 
 | ||
|       
 | ||
|       const searchTerms = [
 | ||
|         query, 
 | ||
|         ...query.split(/\s+/).filter(term => term.length > 0) 
 | ||
|       ];
 | ||
|       
 | ||
|       
 | ||
|       const uniqueTerms = [...new Set(searchTerms)];
 | ||
|       
 | ||
|       
 | ||
|       const requireFullQueryMatch = DEFAULT_CONFIG.search.strictMode;
 | ||
|       
 | ||
|       
 | ||
|       const results = this.searchIndex
 | ||
|         .map(item => {
 | ||
|           
 | ||
|           const fullQueryMatched = this.checkFieldsForMatch(item, uniqueTerms[0]);
 | ||
|           
 | ||
|           
 | ||
|           if (requireFullQueryMatch && !fullQueryMatched) {
 | ||
|             return { item, score: 0, matched: false };
 | ||
|           }
 | ||
|           
 | ||
|           
 | ||
|           let score = 0;
 | ||
|           let matchedTermsCount = 0;
 | ||
|           let matchedInTitle = false;
 | ||
|           
 | ||
|           
 | ||
|           uniqueTerms.forEach((term, index) => {
 | ||
|             
 | ||
|             const isFullQuery = index === 0;
 | ||
|             const matched = this.checkFieldsForMatch(item, term);
 | ||
|             
 | ||
|             if (matched) {
 | ||
|               matchedTermsCount++;
 | ||
|               
 | ||
|               
 | ||
|               if (matched.inTitle) {
 | ||
|                 score += isFullQuery ? 10 : 5;
 | ||
|                 matchedInTitle = true;
 | ||
|               }
 | ||
|               if (matched.inDesc) {
 | ||
|                 score += isFullQuery ? 8 : 4;
 | ||
|               }
 | ||
|               if (matched.inSection) {
 | ||
|                 score += isFullQuery ? 6 : 3;
 | ||
|               }
 | ||
|               if (matched.inContents) {
 | ||
|                 score += isFullQuery ? 4 : 2;
 | ||
|               }
 | ||
|             }
 | ||
|           });
 | ||
|           
 | ||
|           
 | ||
|           const matchRatio = matchedTermsCount / uniqueTerms.length;
 | ||
|           
 | ||
|           
 | ||
|           const finalScore = score * matchRatio * (matchedInTitle ? 1.5 : 1);
 | ||
|           
 | ||
|           return {
 | ||
|             item,
 | ||
|             score: finalScore,
 | ||
|             matched: fullQueryMatched 
 | ||
|           };
 | ||
|         })
 | ||
|         .filter(result => result.matched)
 | ||
|         .sort((a, b) => b.score - a.score)
 | ||
|         .slice(0, DEFAULT_CONFIG.search.maxResults)
 | ||
|         .map(result => result.item);
 | ||
| 
 | ||
|       
 | ||
|       if (results.length === 0) {
 | ||
|         this.resultsContainer.innerHTML = '<p class="mt-5">Oops! No results found.</p>';
 | ||
|         return;
 | ||
|       }
 | ||
| 
 | ||
|       const searchItems = results.map((item) => {
 | ||
|         let categories = '';
 | ||
|         let tags = '';
 | ||
|         if (item.categories) {
 | ||
|           categories = item.categories.join(', ');
 | ||
|           categories = `<div class="me-sm-4"><i class="far fa-folder fa-fw"></i>${categories}</div>`;
 | ||
|         }
 | ||
|         if (item.tags) {
 | ||
|           tags = item.tags.join(', ');
 | ||
|           tags = `<div><i class="fa fa-tag fa-fw"></i>${tags}</div>`
 | ||
|         }
 | ||
|         return `
 | ||
|         <article class="px-1 px-sm-2 px-lg-4 px-xl-0">
 | ||
|           <header>
 | ||
|             <h2><a href="${this.escapeHtml(item.permalink)}">${this.escapeHtml(item.title)}</a></h2>
 | ||
|             <div class="post-meta d-flex flex-column flex-sm-row text-muted mt-1 mb-1">
 | ||
|               ${categories}
 | ||
|               ${tags}
 | ||
|             </div>
 | ||
|           </header>
 | ||
|           <p>${this.escapeHtml(item.contents)}</p>
 | ||
|         </article>
 | ||
|       `;
 | ||
|       }).join('');
 | ||
|       
 | ||
|       this.resultsContainer.innerHTML = searchItems;
 | ||
|     }
 | ||
|     
 | ||
|     
 | ||
|     checkFieldsForMatch(item, term) {
 | ||
|       const matches = {
 | ||
|         inTitle: false,
 | ||
|         inDesc: false,
 | ||
|         inSection: false,
 | ||
|         inContents: false
 | ||
|       };
 | ||
|       
 | ||
|       
 | ||
|       if (DEFAULT_CONFIG.search.fields.title && this.containsTerm(item.searchableTitle, term)) {
 | ||
|         matches.inTitle = true;
 | ||
|       }
 | ||
|       
 | ||
|       if (DEFAULT_CONFIG.search.fields.description && this.containsTerm(item.searchableDesc, term)) {
 | ||
|         matches.inDesc = true;
 | ||
|       }
 | ||
|       
 | ||
|       if (DEFAULT_CONFIG.search.fields.section && this.containsTerm(item.searchableSection, term)) {
 | ||
|         matches.inSection = true;
 | ||
|       }
 | ||
|       
 | ||
|       if (DEFAULT_CONFIG.search.fields.contents && this.containsTerm(item.searchableContents, term)) {
 | ||
|         matches.inContents = true;
 | ||
|       }
 | ||
|       
 | ||
|       
 | ||
|       if (matches.inTitle || matches.inDesc || matches.inSection || matches.inContents) {
 | ||
|         return matches;
 | ||
|       }
 | ||
|       
 | ||
|       
 | ||
|       return false;
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   const search = new FastSearch({
 | ||
|     searchInput: document.getElementById('search-input'),
 | ||
|     resultsContainer: document.getElementById('search-results'),
 | ||
|     json: `\/index.json`
 | ||
|   });
 | ||
| 
 | ||
| </script>
 | ||
|       </div>
 | ||
| 
 | ||
|       <aside aria-label="Scroll to Top">
 | ||
|         <button id="back-to-top" type="button" class="btn btn-lg btn-box-shadow">
 | ||
|           <i class="fas fa-angle-up"></i>
 | ||
|         </button>
 | ||
|       </aside>
 | ||
|     </div>
 | ||
| 
 | ||
|     <div id="mask" class="d-none position-fixed w-100 h-100 z-1"></div>
 | ||
|   </body>
 | ||
| </html> |