tabi/blog/custom-font-subset/index.html
2025-09-22 21:40:28 +00:00

118 lines
No EOL
74 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html><html lang=en><head><meta charset=UTF-8><meta content="default-src 'self';font-src 'self' data:;img-src 'self' https://* data:;media-src 'self' https://cdn.jsdelivr.net/;style-src 'self';frame-src player.vimeo.com https://www.youtube-nocookie.com;connect-src 'self' https://tabi-stats.osc.garden vhiweeypifbwacashxjz.supabase.co;script-src 'self' https://tabi-stats.osc.garden cdn.jsdelivr.net 'self'" http-equiv=Content-Security-Policy><meta content="width=device-width,initial-scale=1.0" name=viewport><meta content=https://welpo.github.io/tabi name=base><title>
~/tabi • Optimise loading times with a custom font subset</title><link href=https://welpo.github.io/tabi/img/seedling.png rel=icon type=image/png><link href='data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text y="50%" x="50%" dominant-baseline="central" text-anchor="middle" font-size="88">🌱</text></svg>' rel=icon><link title="~/tabi - Atom Feed" href=https://welpo.github.io/tabi/atom.xml rel=alternate type=application/atom+xml><link href="https://welpo.github.io/tabi/custom_subset.css?h=0b9535a28bc3d5bf2321" rel=stylesheet><link href="https://welpo.github.io/tabi/main.css?h=e9648e8ea2820aa9b15b" rel=stylesheet><meta content="light dark" name=color-scheme><meta content=#087e96 name=theme-color><meta content="Learn how to create a custom subset that only includes the necessary glyphs." name=description><meta content="Learn how to create a custom subset that only includes the necessary glyphs." property=og:description><meta content="Optimise loading times with a custom font subset" property=og:title><meta content=article property=og:type><meta content="https://welpo.github.io/tabi/blog/custom-font-subset/social_cards/blog_custom_font_subset.jpg?h=0e516edca740ba4fa780" property=og:image><meta content=1400 property=og:image:width><meta content=800 property=og:image:height><meta content="https://welpo.github.io/tabi/blog/custom-font-subset/social_cards/blog_custom_font_subset.jpg?h=0e516edca740ba4fa780" name=twitter:image><meta content=summary_large_image name=twitter:card><meta content=ca_ES property=og:locale:alternate><link href=https://welpo.github.io/tabi/ca/blog/custom-font-subset/ hreflang=ca rel=alternate><meta content=en_GB property=og:locale:alternate><link href=https://welpo.github.io/tabi/blog/custom-font-subset/ hreflang=en rel=alternate><meta content=es_ES property=og:locale:alternate><link href=https://welpo.github.io/tabi/es/blog/custom-font-subset/ hreflang=es rel=alternate><meta content=https://welpo.github.io/tabi/blog/custom-font-subset/ property=og:url><meta content=~/tabi property=og:site_name><noscript><link href=https://welpo.github.io/tabi/no_js.css rel=stylesheet></noscript><script src=https://welpo.github.io/tabi/js/initializeTheme.min.js></script><script defer src=https://welpo.github.io/tabi/js/themeSwitcher.min.js></script><script async data-goatcounter=https://tabi-stats.osc.garden/count src=https://tabi-stats.osc.garden/count.js></script><script src="https://welpo.github.io/tabi/js/searchElasticlunr.min.js?h=3626c0ef99daa745b31e" defer></script><body><header><nav class=navbar><div class=nav-title><a class=home-title href=https://welpo.github.io/tabi/>~/tabi</a></div><div class=nav-navs><ul><li><a class="nav-links no-hover-padding" href=https://welpo.github.io/tabi/blog/>blog </a><li><a class="nav-links no-hover-padding" href=https://welpo.github.io/tabi/archive/>archive </a><li><a class="nav-links no-hover-padding" href=https://welpo.github.io/tabi/tags/>tags </a><li><a class="nav-links no-hover-padding" href=https://welpo.github.io/tabi/projects/>projects </a><li class=menu-icons-container><ul class=menu-icons-group><li class="js menu-icon"><div aria-label="Click or press $SHORTCUT to open search" class="search-icon interactive-icon" title="Click or press $SHORTCUT to open search" id=search-button role=button tabindex=0><svg viewbox="0 -960 960 960" xmlns=http://www.w3.org/2000/svg><path d="M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z"/></svg></div><li class=language-switcher><details class=dropdown><summary aria-label="Language selection" title="Language selection" aria-haspopup=true role=button><div class=language-switcher-icon></div></summary> <div class=dropdown-content role=menu>English<a aria-label=Español href=https://welpo.github.io/tabi/es/blog/custom-font-subset/ lang=es role=menuitem>Español</a><a aria-label=Català href=https://welpo.github.io/tabi/ca/blog/custom-font-subset/ lang=ca role=menuitem>Català</a><a aria-label=العربية href=https://welpo.github.io/tabi/ar/blog/custom-font-subset/ lang=ar role=menuitem>العربية</a></div></details><li class="theme-switcher-wrapper js"><div aria-label="Toggle dark mode" title="Toggle dark/light mode" aria-pressed=false class=theme-switcher role=button tabindex=0></div><div aria-label="Reset mode to default" class="theme-resetter arrow" title="Reset mode to default" aria-hidden=true role=button tabindex=0></div></ul></ul></div></nav></header><div class=content><main><article class=h-entry><h1 class="p-name article-title">Optimise loading times with a custom font subset</h1><a class="u-url u-uid" href=https://welpo.github.io/tabi/blog/custom-font-subset/></a><ul class=meta><li><time class=dt-published datetime=2023-04-29>29th Apr 2023</time><li title="482 words"><span aria-hidden=true class=separator></span>3 min read<li class=tag><span aria-hidden=true class=separator></span>Tags: <li class=tag><a class=p-category href=https://welpo.github.io/tabi/tags/showcase/>showcase</a>, <li class=tag><a class=p-category href=https://welpo.github.io/tabi/tags/tutorial/>tutorial</a></ul><ul class="meta last-updated"><li><time class=dt-updated datetime=2025-01-12>Updated on 12th Jan 2025</time><li><span aria-hidden=true class=separator></span><a class=external href=https://github.com/welpo/tabi/commits/main/content/blog/custom-font-subset/index.md>See changes</a></ul><p class=p-summary hidden>Learn how to create a custom subset that only includes the necessary glyphs.<section class="e-content body"><h2 id=the-problem><a aria-label="Anchor link for: the-problem" class="header-anchor no-hover-padding" href=#the-problem><span aria-hidden=true class=link-icon></span></a> The problem</h2><p>Custom fonts cause flashing text in Firefox. For a gif and more details, see <a class=external href=https://github.com/welpo/tabi/issues/75>this issue</a>.<h2 id=the-solution><a aria-label="Anchor link for: the-solution" class="header-anchor no-hover-padding" href=#the-solution><span aria-hidden=true class=link-icon></span></a> The solution</h2><p>To fix this, tabi loads a subset of glyphs for the header. Since this (slightly) increases the initial load time, its a good idea to try and minimise the size of this subset.<p>By default, there are subset files for English and Spanish characters (with a few symbols). These files are loaded when the Zola page/site is set to that language.<div class="admonition tip"><div class="admonition-icon admonition-icon-tip"></div><div class=admonition-content><strong class=admonition-title>TIP</strong><p>If youre using a custom font, either create your custom subset (see below) or disable the built-in subsets completely with <code>enable_subset = false</code> in your <code>config.toml</code>.</div></div><p>Heres how you can create a custom font subset that only includes the characters used in your header, for maximum efficiency.<h2 id=requirements><a aria-label="Anchor link for: requirements" class="header-anchor no-hover-padding" href=#requirements><span aria-hidden=true class=link-icon></span></a> Requirements</h2><p>Install these tools:<ul><li><p><a class=external href=https://github.com/fonttools/fonttools>fonttools</a></p><li><p><a class=external href=https://github.com/google/brotli>brotli</a></p></ul><p>Run <code>pip install fonttools brotli</code> to install both.<h2 id=the-script><a aria-label="Anchor link for: the-script" class="header-anchor no-hover-padding" href=#the-script><span aria-hidden=true class=link-icon></span></a> The script</h2><p>The script below takes a <code>config.toml</code> file and a font file as input, extracts the necessary characters, creates a subset of the font, and generates a CSS file containing the base64 encoded subset.<pre class="language-bash z-code" data-lang=bash><code class=language-bash data-lang=bash><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell">!/usr/bin/env bash</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-meta z-function z-shell"><span class="z-entity z-name z-function z-shell">usage</span><span class="z-punctuation z-section z-parens z-begin z-shell">(</span><span class="z-punctuation z-section z-parens z-end z-shell">)</span> <span class="z-punctuation z-section z-braces z-begin z-shell">{</span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-function z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>Usage: <span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">0</span></span> [--config | -c CONFIG_FILE] [--font | -f FONT_FILE] [--output | -o OUTPUT_PATH]<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-function z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-function z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>Options:<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-function z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span> --config, -c Path to the config.toml file.<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-function z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span> --font, -f Path to the font file.<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-function z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span> --output, -o Output path for the generated subset.css file (default: current directory)<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-function z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span> --help, -h Show this help message and exit<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-function z-shell"><span class="z-punctuation z-section z-braces z-end z-shell">}</span></span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Default output is current directory.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-variable z-other z-readwrite z-assignment z-shell">output_path</span><span class="z-keyword z-operator z-assignment z-shell">=</span><span class="z-string z-unquoted z-shell"><span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>.<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Parse command line options</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-loop z-while z-shell">while</span> <span class="z-support z-function z-test z-begin z-shell">[</span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-language z-shell">#</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span> <span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell">-</span>gt</span> 0 <span class="z-support z-function z-test z-end z-shell">]</span></span><span class="z-keyword z-operator z-logical z-continue z-shell">;</span> <span class="z-keyword z-control z-loop z-do z-shell">do</span>
</span><span class="z-source z-shell z-bash"> <span class="z-meta z-conditional z-case z-shell"><span class="z-keyword z-control z-conditional z-case z-shell">case</span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">1</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span> <span class="z-keyword z-control z-in z-shell">in</span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-shell"> </span><span class="z-meta z-conditional z-case z-clause z-patterns z-shell">--config<span class="z-keyword z-operator z-logical z-shell">|</span>-c<span class="z-meta z-conditional z-case z-shell"><span class="z-keyword z-control z-conditional z-patterns z-end z-shell">)</span></span></span><span class="z-meta z-conditional z-case z-clause z-commands z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> <span class="z-variable z-other z-readwrite z-assignment z-shell">config_file</span><span class="z-keyword z-operator z-assignment z-shell">=</span><span class="z-string z-unquoted z-shell"><span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">2</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-shift z-shell">shift</span></span><span class="z-meta z-function-call z-arguments z-shell"> 2</span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> </span><span class="z-meta z-conditional z-case z-clause z-commands z-shell"><span class="z-punctuation z-terminator z-case z-clause z-shell">;;</span></span><span class="z-meta z-conditional z-case z-clause z-patterns z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-patterns z-shell"> </span><span class="z-meta z-conditional z-case z-clause z-patterns z-shell">--font<span class="z-keyword z-operator z-logical z-shell">|</span>-f<span class="z-meta z-conditional z-case z-clause z-patterns z-shell"><span class="z-keyword z-control z-conditional z-patterns z-end z-shell">)</span></span></span><span class="z-meta z-conditional z-case z-clause z-commands z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> <span class="z-variable z-other z-readwrite z-assignment z-shell">font_file</span><span class="z-keyword z-operator z-assignment z-shell">=</span><span class="z-string z-unquoted z-shell"><span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">2</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-shift z-shell">shift</span></span><span class="z-meta z-function-call z-arguments z-shell"> 2</span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> </span><span class="z-meta z-conditional z-case z-clause z-commands z-shell"><span class="z-punctuation z-terminator z-case z-clause z-shell">;;</span></span><span class="z-meta z-conditional z-case z-clause z-patterns z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-patterns z-shell"> </span><span class="z-meta z-conditional z-case z-clause z-patterns z-shell">--output<span class="z-keyword z-operator z-logical z-shell">|</span>-o<span class="z-meta z-conditional z-case z-clause z-patterns z-shell"><span class="z-keyword z-control z-conditional z-patterns z-end z-shell">)</span></span></span><span class="z-meta z-conditional z-case z-clause z-commands z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> <span class="z-variable z-other z-readwrite z-assignment z-shell">output_path</span><span class="z-keyword z-operator z-assignment z-shell">=</span><span class="z-string z-unquoted z-shell"><span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">2</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-shift z-shell">shift</span></span><span class="z-meta z-function-call z-arguments z-shell"> 2</span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> </span><span class="z-meta z-conditional z-case z-clause z-commands z-shell"><span class="z-punctuation z-terminator z-case z-clause z-shell">;;</span></span><span class="z-meta z-conditional z-case z-clause z-patterns z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-patterns z-shell"> </span><span class="z-meta z-conditional z-case z-clause z-patterns z-shell">--help<span class="z-keyword z-operator z-logical z-shell">|</span>-h<span class="z-meta z-conditional z-case z-clause z-patterns z-shell"><span class="z-keyword z-control z-conditional z-patterns z-end z-shell">)</span></span></span><span class="z-meta z-conditional z-case z-clause z-commands z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">usage</span></span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-exit z-shell">exit</span></span><span class="z-meta z-function-call z-arguments z-shell"> 0</span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> </span><span class="z-meta z-conditional z-case z-clause z-commands z-shell"><span class="z-punctuation z-terminator z-case z-clause z-shell">;;</span></span><span class="z-meta z-conditional z-case z-clause z-patterns z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-patterns z-shell"> </span><span class="z-meta z-conditional z-case z-clause z-patterns z-shell"><span class="z-keyword z-operator z-regexp z-quantifier z-shell">*</span><span class="z-meta z-conditional z-case z-clause z-patterns z-shell"><span class="z-keyword z-control z-conditional z-patterns z-end z-shell">)</span></span></span><span class="z-meta z-conditional z-case z-clause z-commands z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>Unknown option: <span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">1</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">usage</span></span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-exit z-shell">exit</span></span><span class="z-meta z-function-call z-arguments z-shell"> 1</span>
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-commands z-shell"> </span><span class="z-meta z-conditional z-case z-clause z-commands z-shell"><span class="z-punctuation z-terminator z-case z-clause z-shell">;;</span></span><span class="z-meta z-conditional z-case z-clause z-patterns z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-conditional z-case z-clause z-patterns z-shell"> <span class="z-keyword z-control z-conditional z-end z-shell">esac</span></span>
</span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-loop z-end z-shell">done</span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Check if -c and -f options are provided</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-conditional z-if z-shell">if</span> <span class="z-support z-function z-test z-begin z-shell">[</span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell">-</span>z</span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">config_file</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span> <span class="z-support z-function z-test z-end z-shell">]</span></span><span class="z-keyword z-operator z-logical z-continue z-shell">;</span> <span class="z-keyword z-control z-conditional z-then z-shell">then</span>
</span><span class="z-source z-shell z-bash"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>Error: --config|-c option is required.<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span><span class="z-source z-shell z-bash"> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">usage</span></span>
</span><span class="z-source z-shell z-bash"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-exit z-shell">exit</span></span><span class="z-meta z-function-call z-arguments z-shell"> 1</span>
</span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-conditional z-end z-shell">fi</span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-conditional z-if z-shell">if</span> <span class="z-support z-function z-test z-begin z-shell">[</span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell">-</span>z</span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">font_file</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span> <span class="z-support z-function z-test z-end z-shell">]</span></span><span class="z-keyword z-operator z-logical z-continue z-shell">;</span> <span class="z-keyword z-control z-conditional z-then z-shell">then</span>
</span><span class="z-source z-shell z-bash"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>Error: --font|-f option is required.<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span><span class="z-source z-shell z-bash"> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">usage</span></span>
</span><span class="z-source z-shell z-bash"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-exit z-shell">exit</span></span><span class="z-meta z-function-call z-arguments z-shell"> 1</span>
</span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-conditional z-end z-shell">fi</span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Check if config and font files exist.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-conditional z-if z-shell">if</span> <span class="z-support z-function z-test z-begin z-shell">[</span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-keyword z-operator z-logical z-shell">!</span> <span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell">-</span>f</span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">config_file</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span> <span class="z-support z-function z-test z-end z-shell">]</span></span><span class="z-keyword z-operator z-logical z-continue z-shell">;</span> <span class="z-keyword z-control z-conditional z-then z-shell">then</span>
</span><span class="z-source z-shell z-bash"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>Error: Config file '<span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">config_file</span></span>' not found.<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span><span class="z-source z-shell z-bash"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-exit z-shell">exit</span></span><span class="z-meta z-function-call z-arguments z-shell"> 1</span>
</span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-conditional z-end z-shell">fi</span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-conditional z-if z-shell">if</span> <span class="z-support z-function z-test z-begin z-shell">[</span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-keyword z-operator z-logical z-shell">!</span> <span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell">-</span>f</span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">font_file</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span> <span class="z-support z-function z-test z-end z-shell">]</span></span><span class="z-keyword z-operator z-logical z-continue z-shell">;</span> <span class="z-keyword z-control z-conditional z-then z-shell">then</span>
</span><span class="z-source z-shell z-bash"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>Error: Font file '<span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">font_file</span></span>' not found.<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span><span class="z-source z-shell z-bash"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-exit z-shell">exit</span></span><span class="z-meta z-function-call z-arguments z-shell"> 1</span>
</span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-conditional z-end z-shell">fi</span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Extract the title and menu names from the config file.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-variable z-other z-readwrite z-assignment z-shell">title</span><span class="z-keyword z-operator z-assignment z-shell">=</span><span class="z-string z-unquoted z-shell"><span class="z-meta z-group z-expansion z-command z-parens z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-punctuation z-section z-parens z-begin z-shell">(</span><span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">awk</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>F</span><span class="z-string z-quoted z-single z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">'</span> = <span class="z-punctuation z-definition z-string z-end z-shell">'</span></span> <span class="z-string z-quoted z-single z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">'</span>/^title/{print $2}<span class="z-punctuation z-definition z-string z-end z-shell">'</span></span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">config_file</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span> <span class="z-keyword z-operator z-logical z-pipe z-shell">|</span> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">tr</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>d</span> <span class="z-string z-quoted z-single z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">'</span>"<span class="z-punctuation z-definition z-string z-end z-shell">'</span></span></span><span class="z-punctuation z-section z-parens z-end z-shell">)</span></span></span>
</span><span class="z-source z-shell z-bash"><span class="z-variable z-other z-readwrite z-assignment z-shell">menu_names</span><span class="z-keyword z-operator z-assignment z-shell">=</span><span class="z-string z-unquoted z-shell"><span class="z-meta z-group z-expansion z-command z-parens z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-punctuation z-section z-parens z-begin z-shell">(</span><span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">awk</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>F</span><span class="z-string z-quoted z-single z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">'</span> = <span class="z-punctuation z-definition z-string z-end z-shell">'</span></span> <span class="z-string z-quoted z-single z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">'</span>/^menu/{f=1;next} /socials/{f=0} f && /name/{print $2}<span class="z-punctuation z-definition z-string z-end z-shell">'</span></span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">config_file</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span> <span class="z-keyword z-operator z-logical z-pipe z-shell">|</span> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">cut</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>d</span><span class="z-string z-quoted z-single z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">'</span>,<span class="z-punctuation z-definition z-string z-end z-shell">'</span></span><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>f1</span></span> <span class="z-keyword z-operator z-logical z-pipe z-shell">|</span> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">tr</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>d</span> <span class="z-string z-quoted z-single z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">'</span>"<span class="z-punctuation z-definition z-string z-end z-shell">'</span></span> </span><span class="z-punctuation z-section z-parens z-end z-shell">)</span></span></span>
</span><span class="z-source z-shell z-bash"><span class="z-variable z-other z-readwrite z-assignment z-shell">language_names</span><span class="z-keyword z-operator z-assignment z-shell">=</span><span class="z-string z-unquoted z-shell"><span class="z-meta z-group z-expansion z-command z-parens z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-punctuation z-section z-parens z-begin z-shell">(</span><span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">awk</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>F</span><span class="z-string z-quoted z-single z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">'</span> = <span class="z-punctuation z-definition z-string z-end z-shell">'</span></span> <span class="z-string z-quoted z-single z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">'</span>/^language_name\./{print $2}<span class="z-punctuation z-definition z-string z-end z-shell">'</span></span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">config_file</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span> <span class="z-keyword z-operator z-logical z-pipe z-shell">|</span> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">tr</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>d</span> <span class="z-string z-quoted z-single z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">'</span>"<span class="z-punctuation z-definition z-string z-end z-shell">'</span></span> </span><span class="z-punctuation z-section z-parens z-end z-shell">)</span></span></span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> If the site is multilingual, get the menu translations.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-conditional z-if z-shell">if</span> <span class="z-support z-function z-test z-begin z-shell">[</span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell">-</span>n</span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">language_names</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span> <span class="z-support z-function z-test z-end z-shell">]</span></span><span class="z-keyword z-operator z-logical z-continue z-shell">;</span> <span class="z-keyword z-control z-conditional z-then z-shell">then</span>
</span><span class="z-source z-shell z-bash"> <span class="z-keyword z-control z-loop z-for z-shell">for</span><span class="z-meta z-group z-for z-shell"> menu_name <span class="z-keyword z-control z-in z-shell">in</span> <span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">menu_names</span></span></span><span class="z-keyword z-operator z-logical z-continue z-shell">;</span> <span class="z-keyword z-control z-loop z-do z-shell">do</span>
</span><span class="z-source z-shell z-bash"> <span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Find the line with the menu name inside a [languages.*.translations] section and get the translated menus.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"> <span class="z-variable z-other z-readwrite z-assignment z-shell">menu_translation</span><span class="z-keyword z-operator z-assignment z-shell">=</span><span class="z-string z-unquoted z-shell"><span class="z-meta z-group z-expansion z-command z-parens z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-punctuation z-section z-parens z-begin z-shell">(</span><span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">awk</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>F</span><span class="z-string z-quoted z-single z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">'</span> = <span class="z-punctuation z-definition z-string z-end z-shell">'</span></span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>/<span class="z-constant z-character z-escape z-shell">\\</span>[languages.*<span class="z-constant z-character z-escape z-shell">\\</span>.translations<span class="z-constant z-character z-escape z-shell">\\</span>]/{f=1;next} /^<span class="z-constant z-character z-escape z-shell">\\</span>[/ {f=0} f && /<span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">menu_name</span></span> =/{print <span class="z-constant z-character z-escape z-shell">\$</span>2}<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">config_file</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span> <span class="z-keyword z-operator z-logical z-pipe z-shell">|</span> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">tr</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>d</span> <span class="z-string z-quoted z-single z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">'</span>"<span class="z-punctuation z-definition z-string z-end z-shell">'</span></span> </span><span class="z-punctuation z-section z-parens z-end z-shell">)</span></span></span>
</span><span class="z-source z-shell z-bash"> <span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Add the found menu value to the translations string</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"> <span class="z-variable z-other z-readwrite z-assignment z-shell">menu_names</span><span class="z-keyword z-operator z-assignment z-shell">+=</span><span class="z-string z-unquoted z-shell"><span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">menu_translation</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span><span class="z-source z-shell z-bash"> <span class="z-keyword z-control z-loop z-end z-shell">done</span>
</span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-conditional z-end z-shell">fi</span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Combine the extracted strings.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-variable z-other z-readwrite z-assignment z-shell">combined</span><span class="z-keyword z-operator z-assignment z-shell">=</span><span class="z-string z-unquoted z-shell"><span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">title</span></span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">menu_names</span></span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">language_names</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Get unique characters.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-variable z-other z-readwrite z-assignment z-shell">unique_chars</span><span class="z-keyword z-operator z-assignment z-shell">=</span><span class="z-string z-unquoted z-shell"><span class="z-meta z-group z-expansion z-command z-parens z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-punctuation z-section z-parens z-begin z-shell">(</span><span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">combined</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span> <span class="z-keyword z-operator z-logical z-pipe z-shell">|</span> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">grep</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>o</span> .</span> <span class="z-keyword z-operator z-logical z-pipe z-shell">|</span> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">sort</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>u</span></span> <span class="z-keyword z-operator z-logical z-pipe z-shell">|</span> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">tr</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>d</span> <span class="z-string z-quoted z-single z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">'</span>\n<span class="z-punctuation z-definition z-string z-end z-shell">'</span></span></span><span class="z-punctuation z-section z-parens z-end z-shell">)</span></span></span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Create a temporary file for subset.woff2.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-variable z-other z-readwrite z-assignment z-shell">temp_subset</span><span class="z-keyword z-operator z-assignment z-shell">=</span><span class="z-string z-unquoted z-shell"><span class="z-meta z-group z-expansion z-command z-parens z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-punctuation z-section z-parens z-begin z-shell">(</span><span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">mktemp</span></span><span class="z-punctuation z-section z-parens z-end z-shell">)</span></span></span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Create the subset.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">pyftsubset</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">font_file</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span> <span class="z-punctuation z-separator z-continuation z-line z-shell">\
</span></span></span><span class="z-source z-shell z-bash"><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> --</span>text</span><span class="z-keyword z-operator z-assignment z-option z-shell">=</span><span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">unique_chars</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span> <span class="z-punctuation z-separator z-continuation z-line z-shell">\
</span></span></span><span class="z-source z-shell z-bash"><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> --</span>layout-features</span><span class="z-keyword z-operator z-assignment z-option z-shell">=</span><span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>*<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> --</span>flavor</span><span class="z-keyword z-operator z-assignment z-option z-shell">=</span><span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>woff2<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> --</span>output-file</span><span class="z-keyword z-operator z-assignment z-option z-shell">=</span><span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">temp_subset</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> --</span>with-zopfli</span></span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Remove trailing slash from output path, if present.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-variable z-other z-readwrite z-assignment z-shell">output_path</span><span class="z-keyword z-operator z-assignment z-shell">=</span><span class="z-string z-unquoted z-shell"><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-punctuation z-section z-expansion z-parameter z-begin z-shell">{</span></span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-variable z-other z-readwrite z-shell">output_path<span class="z-keyword z-operator z-expansion z-shell">%</span></span></span><span class="z-meta z-group z-expansion z-parameter z-shell">/</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-section z-expansion z-parameter z-end z-shell">}</span></span></span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Base64 encode the temporary subset.woff2 file and create the CSS file.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-variable z-other z-readwrite z-assignment z-shell">base64_encoded_font</span><span class="z-keyword z-operator z-assignment z-shell">=</span><span class="z-string z-unquoted z-shell"><span class="z-meta z-group z-expansion z-command z-parens z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-punctuation z-section z-parens z-begin z-shell">(</span><span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">base64</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>i</span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">temp_subset</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span><span class="z-punctuation z-section z-parens z-end z-shell">)</span></span></span>
</span><span class="z-source z-shell z-bash"><span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>@font-face{font-family:<span class="z-constant z-character z-escape z-shell">\"</span>Inter Subset<span class="z-constant z-character z-escape z-shell">\"</span>;src:url(data:application/font-woff2;base64,<span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">base64_encoded_font</span></span>);}<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span> <span class="z-keyword z-operator z-assignment z-redirection z-shell">></span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">output_path</span></span>/custom_subset.css<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Remove the temporary subset.woff2 file.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">rm</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span><span class="z-meta z-group z-expansion z-parameter z-shell"><span class="z-punctuation z-definition z-variable z-shell">$</span><span class="z-variable z-other z-readwrite z-shell">temp_subset</span></span><span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span></code></pre><h2 id=usage><a aria-label="Anchor link for: usage" class="header-anchor no-hover-padding" href=#usage><span aria-hidden=true class=link-icon></span></a> Usage</h2><p>Save the script somewhere like <code>~/bin/subset_font</code>. Make it executable with <code>chmod +x ~/bin/subset_font</code>.<p>Now you can run it with the required <code>--config</code> and <code>--font</code> options:<pre class="language-bash z-code" data-lang=bash><code class=language-bash data-lang=bash><span class="z-source z-shell z-bash"><span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell"><span class="z-meta z-group z-expansion z-tilde"><span class="z-variable z-language z-tilde z-shell">~</span></span>/bin/subset_font</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> --</span>config</span> path/to/config.toml<span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> --</span>font</span> path/to/font.woff2</span>
</span></code></pre><p>By default, this generates a <code>custom_subset.css</code> file in the current directory. Use <code>-o</code> or <code>--output</code> to specify a different path:<pre class="language-bash z-code" data-lang=bash><code class=language-bash data-lang=bash><span class="z-source z-shell z-bash"><span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell"><span class="z-meta z-group z-expansion z-tilde"><span class="z-variable z-language z-tilde z-shell">~</span></span>/bin/subset_font</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>c</span> path/to/config.toml<span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>f</span> path/to/font.woff2<span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>o</span> path/to/output</span>
</span></code></pre><p>You should place this <code>custom_subset.css</code> file inside the <code>static/</code> directory.<h2 id=automating-with-pre-commit-hook><a aria-label="Anchor link for: automating-with-pre-commit-hook" class="header-anchor no-hover-padding" href=#automating-with-pre-commit-hook><span aria-hidden=true class=link-icon></span></a> Automating with Pre-commit Hook</h2><p>You might change the title or menu options of your site, making the custom subset no longer useful.<p>To automate the process of creating this file, you can integrate the script into a Git pre-commit hook that checks for changes in the <code>config.toml</code> file, runs the script, and stores the resulting CSS file in the <code>static/</code> directory of your site.<ol><li><p>Create a <code>.git/hooks/pre-commit</code> file in your Git project, if it doesnt already exist.</p><li><p>Make it executable with <code>chmod +x .git/hooks/pre-commit</code>.</p><li><p>Add the following code to the file:</p></ol><pre class="language-bash z-code" data-lang=bash><code class=language-bash data-lang=bash><span class="z-source z-shell z-bash"><span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Check if config.toml has been modified.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-conditional z-if z-shell">if</span> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">git</span></span><span class="z-meta z-function-call z-arguments z-shell"> diff<span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> --</span>cached</span><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> --</span>name-only</span></span> <span class="z-keyword z-operator z-logical z-pipe z-shell">|</span> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">grep</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>q</span> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>config.toml<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span><span class="z-keyword z-operator z-logical z-continue z-shell">;</span> <span class="z-keyword z-control z-conditional z-then z-shell">then</span>
</span><span class="z-source z-shell z-bash"> <span class="z-meta z-function-call z-shell"><span class="z-support z-function z-echo z-shell">echo</span></span><span class="z-meta z-function-call z-arguments z-shell"> <span class="z-string z-quoted z-double z-shell"><span class="z-punctuation z-definition z-string z-begin z-shell">"</span>config.toml modified. Running subset_font…<span class="z-punctuation z-definition z-string z-end z-shell">"</span></span></span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"> <span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Call the subset_font script.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell"><span class="z-meta z-group z-expansion z-tilde"><span class="z-variable z-language z-tilde z-shell">~</span></span>/bin/subset_font</span></span><span class="z-meta z-function-call z-arguments z-shell"><span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>c</span> config.toml<span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>f</span> static/fonts/Inter4.woff2<span class="z-variable z-parameter z-option z-shell"><span class="z-punctuation z-definition z-parameter z-shell"> -</span>o</span> static/</span>
</span><span class="z-source z-shell z-bash">
</span><span class="z-source z-shell z-bash"> <span class="z-comment z-line z-number-sign z-shell"><span class="z-punctuation z-definition z-comment z-begin z-shell">#</span></span><span class="z-comment z-line z-number-sign z-shell"> Add the generated subset.css file to the commit.</span><span class="z-comment z-line z-number-sign z-shell">
</span></span><span class="z-source z-shell z-bash"> <span class="z-meta z-function-call z-shell"><span class="z-variable z-function z-shell">git</span></span><span class="z-meta z-function-call z-arguments z-shell"> add static/custom_subset.css</span>
</span><span class="z-source z-shell z-bash"><span class="z-keyword z-control z-conditional z-end z-shell">fi</span>
</span></code></pre><p>Make sure to modify the script to match the path where you stored the <code>subset_font</code> script. The config and font paths should work fine with tabis default setup.<p>Now, every time you commit changes to your Git project, the pre-commit hook will check for modifications in the <code>config.toml</code> file and automatically run the <code>subset_font</code> script to update the <code>custom_subset.css</code> file.<p>By the way, if youre interested in a way to automatically update the date of your Zola posts or compress your PNG files, check out <a class=external href=https://osc.garden/blog/zola-date-git-hook/>this post</a>.<p>If you want to use all scripts at once (compressing PNG files, updating the date, and creating the font subset), combine their code into a single <code>.git/hooks/pre-commit</code> file.</section><form action="https://vhiweeypifbwacashxjz.supabase.co/rest/v1/rpc/increment_hits?apikey=sb_publishable_EoB7MFJhCmb6PiAk-GPJ4w_PGhQ44Ru" class=iine-form method=post><input name=page_slug type=hidden value=/blog/custom-font-subset/><button aria-label="Like this post" title="Like this post" class=iine-button data-icon=thumbs_up data-slug=/blog/custom-font-subset/>👍</button></form><nav class="full-width article-navigation"><div><a aria-describedby=left_title aria-label=Next href=https://welpo.github.io/tabi/blog/comments/><span class=arrow></span> Next</a><p aria-hidden=true id=left_title>Add comments to your posts with these 4 comment systems</div><div><a aria-describedby=right_title aria-label=Prev href=https://welpo.github.io/tabi/blog/security/>Prev <span class=arrow></span></a><p aria-hidden=true id=right_title>Secure by default</div></nav></article></main><span class=hidden id=copy-success> Copied! </span><span class=hidden id=copy-init> Copy code to clipboard </span><script defer src=https://welpo.github.io/tabi/js/copyCodeToClipboard.min.js></script><script defer src=https://cdn.jsdelivr.net/gh/welpo/iine@main/iine.mini.js></script></div><footer><section><nav class="socials nav-navs"><ul><li><a class="nav-links no-hover-padding social" href=https://welpo.github.io/tabi/atom.xml> <img alt=feed loading=lazy src=https://welpo.github.io/tabi/social_icons/rss.svg title=feed> </a><li class=js><a class="nav-links no-hover-padding social" data-encoded-email=dGFiaUBvc2MuZ2FyZGVu href=#><img alt=email loading=lazy src=https://welpo.github.io/tabi/social_icons/email.svg title=email> </a><li><a class="nav-links no-hover-padding social" rel=" me" href=https://github.com/welpo/> <img alt=github loading=lazy src=https://welpo.github.io/tabi/social_icons/github.svg title=github> </a><li><a class="nav-links no-hover-padding social" rel=" me" href=https://soundcloud.com/oskerwyld> <img alt=soundcloud loading=lazy src=https://welpo.github.io/tabi/social_icons/soundcloud.svg title=soundcloud> </a><li><a class="nav-links no-hover-padding social" rel=" me" href=https://instagram.com/oskerwyld> <img alt=instagram loading=lazy src=https://welpo.github.io/tabi/social_icons/instagram.svg title=instagram> </a><li><a class="nav-links no-hover-padding social" rel=" me" href=https://youtube.com/@oskerwyld> <img alt=youtube loading=lazy src=https://welpo.github.io/tabi/social_icons/youtube.svg title=youtube> </a><li><a class="nav-links no-hover-padding social" rel=" me" href=https://open.spotify.com/artist/5Hv2bYBhMp1lUHFri06xkE> <img alt=spotify loading=lazy src=https://welpo.github.io/tabi/social_icons/spotify.svg title=spotify> </a></ul></nav><nav class=nav-navs><small> <ul><li><a class="nav-links no-hover-padding" href=https://welpo.github.io/tabi/about/> about </a><li><a class="nav-links no-hover-padding" href=https://welpo.github.io/tabi/privacy/> privacy policy </a><li><a class="nav-links no-hover-padding" href=https://tabi-stats.osc.garden/> site statistics </a><li><a class="nav-links no-hover-padding" href=https://welpo.github.io/tabi/sitemap.xml> sitemap </a></ul> </small></nav><div class=credits><small> Powered by <a href=https://www.getzola.org>Zola</a> & <a href=https://github.com/welpo/tabi>tabi</a><a href=https://github.com/welpo/tabi> Site source </a></small></div></section><script async src=https://welpo.github.io/tabi/js/decodeMail.min.js></script><div class="search-modal js" aria-labelledby=modalTitle id=searchModal role=dialog><h1 class=visually-hidden id=modalTitle>Search</h1><div id=modal-content><div id=searchBar><div aria-hidden=true class=search-icon><svg viewbox="0 -960 960 960" xmlns=http://www.w3.org/2000/svg><path d="M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z"/></svg></div><input aria-controls=results-container aria-expanded=false autocomplete=off id=searchInput placeholder=Search… role=combobox spellcheck=false><div class="close-icon interactive-icon" title="Clear search" id=clear-search role=button tabindex=0><svg viewbox="0 -960 960 960" xmlns=http://www.w3.org/2000/svg><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/></svg></div></div><div id=results-container><div id=results-info><span id=zero_results> No results</span><span id=one_results> $NUMBER result</span><span id=many_results> $NUMBER results</span><span id=two_results> $NUMBER results</span><span id=few_results> $NUMBER results</span></div><div id=results role=listbox></div></div></div></div></footer>