<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>there’s no place like code</title>
    <description></description>
    <link>http://noplacelikecode.redrice.io</link>
    <atom:link href="http://noplacelikecode.redrice.io/feed.xml" rel="self" type="application/atom+xml" />
    
    <item>
      <title>
        You might not need TypeScript enums #javascript #typescript #enum
      </title>
      <description>&lt;p&gt;With Node.js learning to ignore TypeScript annotations&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; and TypeScript getting an option that disallows runtime semantics&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, let’s re–evaluate if we need the most commonly used TypeScript runtime features: &lt;strong&gt;enums&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Spoiler: no)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s look at a common example of an enum:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Things&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;FOO&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;BAR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;ZAR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;zar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since values are human readable, we can use TypeScript union of strings
instead:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Thing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;zar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then you can use strings for values:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;someThing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Thing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;logThing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;logThing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;list-values&quot;&gt;List values&lt;/h2&gt;

&lt;p&gt;Sometimes it’s useful to have access to all possible values at
runtime. For this, we can list them in an array and use that as source
of truth for types&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;THINGS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;freeze&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;zar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Thing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;THINGS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ↑ this evaluates to: type Thing = &quot;foo&quot; | &quot;bar&quot; | &quot;zar&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;as const&lt;/code&gt; makes TypeScript to see it as immutable (instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array&amp;lt;string&amp;gt;&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Object.freeze&lt;/code&gt; prevents from changing the array by accident at runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you can e.g. present user with a list of all options to choose from
(example using &lt;a href=&quot;https://lit.dev/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lit-html&lt;/code&gt;&lt;/a&gt;):&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&amp;lt;select&amp;gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;THINGS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&amp;lt;option&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;lt;/option&amp;gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;
&amp;lt;/select&amp;gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;… or sanitise user input:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sanitise&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;dirtyValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;allowedValues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Readonly&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;fallbackValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;undefined&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;allowedValues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dirtyValue&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dirtyValue&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`Unrecognised value: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dirtyValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fallbackValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;warn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fallbackValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dirtyThing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;URLSearchParams&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cleanThing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sanitise&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Thing&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dirtyThing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;THINGS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;THINGS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;mapping&quot;&gt;Mapping&lt;/h2&gt;

&lt;p&gt;To map values to something else, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Record&lt;/code&gt; to make sure all values
are included as keys (an no other keys are present):&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;thingToLabelMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Felicity&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Bartholomew&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;zar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Zahary&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;thingToLabelMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/play/?#code/PTAEl4NxAndAVAnAnqAhgE1QSwHYHNQHs5Q4BTAW3wDds8SAbckrAFwGdQAzOfM0EjZgAsSRGAAkAkgDkA4gGUCRITRj4AMsgBG9ALLIADgFgAUCYDG+LK2axJshQF5QAeU0ArEmeYA6LiRIAXiQAFADaAOQc+PjhADSg4ZrIcHEJAcnhALoo7BZWzACUANwmzAj6JLCCNKBOwWUV+By20vIFoVgArmTacJklpsZ51qDKuABcVTVOkdHhJuaWI2M4qhradHr6kwBKnoSoADww1bjx1nA0AHy1oADeJqCc0ZPhAGL0GGYCCHGPoEk4K8AELJIT4Og8EgAdz+xie6SBCQAWshBMlfrETABfEwkAAe+kINmGNjoWnotxWawpmwMoRW-SAA&quot;&gt;Try it out in TypeScript playground&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;switch&quot;&gt;Switch&lt;/h2&gt;

&lt;p&gt;To make sure all values are handled in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch&lt;/code&gt; statement, you can
either rely on a
&lt;a href=&quot;https://typescript-eslint.io/rules/switch-exhaustiveness-check/&quot;&gt;EsLint switch-exhaustiveness-check rule&lt;/a&gt;, or
include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;default&lt;/code&gt; case with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;satisfies never&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-typescript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;foo?&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;bar.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;zar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;zar!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// This will raise a TS error, if we add a new value&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// without adding a case&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;thing&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;satisfies&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;never&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://www.typescriptlang.org/play/?#code/PTAEl4NxAndAVAnAnqAhgE1QSwHYHNQHs5Q4BTAW3wDds8SAbckrAFwGdQAzOfM0EjZgAsSRGAAkAkgDkA4gGUCRVgHcBAY0GhWzZM0YsAsAChja-Fm2xJshQF5QAeQBGAKxJrmAOi4kSALxIACgBtAHIOfHxQgBpQUKdkOBi4v0TQgF0UdjMLZgBKAG5jZgQABxJYQRpQe0CS8vwOK2l5POCsAFcyJxF0opMjEFApfD0ALjjkdhgq3FDQLF9UElRYnrVkDtYK1SF8DuZQIV1YBSxE7mV2ZY5sAXMCJqEMdmZ8OIio03NLZ9wJmbVezhSLzKaVGjGYwqdSaOqzHB5YwAb2MoFAG22H1BYzR6IxP3wDE8yycHRwgRB+AA-KFCnj0U5SMgANb9dGYirxNK4oz4gkWIkkEkkMkU7lwTx09n4pkkVkyzkpHkMgWsIUisWU1JwACE0tVcoVeJumzozF5-KGgPYqjodGIyBeFWQpz4cG4cFiGCayhd6BQCxIylAlGQdA6JFVQ12gn2hzQmFwgc5qr+eFYuhetxI7EWlBE-QAvsYgA&quot;&gt;Try it out in TypeScript playground&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--experimental-strip-types&lt;/code&gt; flag introduced in Node.js 23.0.0 and &lt;a href=&quot;https://nodejs.org/en/blog/release/v23.6.0#unflagging---experimental-strip-types&quot;&gt;no flag needed since 23.6.0&lt;/a&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://devblogs.microsoft.com/typescript/announcing-typescript-5-8-beta/#the---erasablesyntaxonly-option&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enableSyntaxOnly&lt;/code&gt; option introduced in TypeScript 5.8 beta&lt;/a&gt; &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I’d put array definition in one location (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/consts/…&lt;/code&gt;) and
  types in another (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/types/…&lt;/code&gt;), but you do you. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Mon, 24 Feb 2025 00:00:00 +0000</pubDate>
      <link>http://noplacelikecode.redrice.io/2025/02/24/you-might-not-need-enums.html</link>
      <guid isPermaLink="true">http://noplacelikecode.redrice.io/2025/02/24/you-might-not-need-enums.html</guid>
    </item>
    
    <item>
      <title>
        Project–specific tmux sessions #tmux #shell
      </title>
      <description>&lt;h1 id=&quot;the-problem&quot;&gt;The Problem&lt;/h1&gt;

&lt;p&gt;If you use a terminal multiplexer &lt;a href=&quot;https://github.com/tmux/tmux&quot;&gt;tmux&lt;/a&gt;, you might find yourself
re–creating the same pane layout every time you want to start working on
project. There are some tools that allows you to configure tmux
sessions, like &lt;a href=&quot;https://github.com/tmuxinator/tmuxinator&quot;&gt;tmuxinator&lt;/a&gt;, but they never felt natural to me – why
would I want to use &lt;abbr&gt;YAML&lt;/abbr&gt; config file, when tmux has it’s own config
syntax?&lt;/p&gt;

&lt;h1 id=&quot;the-solution&quot;&gt;The Solution&lt;/h1&gt;

&lt;p&gt;Let’s put &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux.conf&lt;/code&gt; files in project directories.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Set up Git globally to ignore &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux.conf&lt;/code&gt; files in the root of repository.&lt;/p&gt;

    &lt;p&gt;Add this to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/git/ignore&lt;/code&gt; (create the directory and the file
if it doesn’t exist):&lt;/p&gt;

    &lt;pre&gt;&lt;code class=&quot;language-gitignore&quot;&gt;/tmux.conf
&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Load &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux.conf&lt;/code&gt; from current directory, when starting a new tmux
session.&lt;/p&gt;

    &lt;p&gt;Add this to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/tmux/tmux.conf&lt;/code&gt;
(or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.tmux.conf&lt;/code&gt;, if you prefer):&lt;/p&gt;

    &lt;pre&gt;&lt;code class=&quot;language-tmux&quot;&gt;if-shell -b &apos;[ -e ./tmux.conf ]&apos; {
  set-hook -g after-new-session &apos;source-file -q ./tmux.conf&apos;
}
&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;If you have tmux, running, re–read the config file:&lt;/p&gt;

    &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tmux source-file ~/.config/tmux/tmux.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Et voilà!&lt;/p&gt;

&lt;h1 id=&quot;examples&quot;&gt;Examples&lt;/h1&gt;

&lt;p&gt;The one I use most often:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-tmux&quot;&gt;rename-session &apos;project-foo&apos;

# Create short pane at the top of the window
split-window -vbdl 6
# Run npm install and `dev` npm script on the top pane
send -t &quot;{previous}&quot; &quot;npm install &amp;amp;&amp;amp; npm run --if-present dev&quot; Enter
# Fetch latest changes in the main pane
send &quot;git fetch&quot; Enter
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here’s a much more involved example with multiple panes on top of the
screen:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-tmux&quot;&gt;rename-session &apos;project-bar&apos;

# | watch+build | serve | api |
# |-------------|-------|-----|
# | main                      |

split-window -vbl10 ; send &apos;npm install &amp;amp;&amp;amp; nodemon -e &quot;npm run build&quot;&apos; Enter
split-window -h     ; send &apos;npm run serve&apos; Enter
split-window -h     ; send &apos;cd ../api &amp;amp;&amp;amp; npm install &amp;amp;&amp;amp; npm run dev&apos; Enter

select-layout -E

select-pane -t&apos;{next}&apos;
send &apos;git fetch&apos; Enter
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or even more complex one that waits for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm install&lt;/code&gt; to finish before
running things in other panes:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-tmux&quot;&gt;rename-session &apos;project-zar&apos;
set-environment -g SOME_IP_ENV_VAR &apos;10.13.32.3&apos;

# | dev | storybook | api |
# |-----------------------|
# | main                  |

# dev
split-window -vbl10

# storybook
split-window -h

send -t 0 &apos;\
  npm install; \
  tmux send -t0 &quot;npm run dev &quot; Enter; \
  tmux send -t1 &quot;npm run storybook --no-open&quot; Enter; \
&apos; Enter

# api
split-window -h
select-pane -t&apos;{next}&apos;
send &apos;cd ../api&apos; Enter
send &apos;git fetch&apos; Enter
send &apos;npm install &amp;amp;&amp;amp; npm run dev&apos; Enter

select-layout -E

# main working area
select-pane -t&apos;{next}&apos;
send &apos;git fetch&apos; Enter
&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&quot;default-configuration&quot;&gt;Default configuration&lt;/h1&gt;

&lt;p&gt;You can go very complex, but most of the time you will probably want to
use the same config for most of your projects. But why copy the same
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux.conf&lt;/code&gt; to each directory?&lt;/p&gt;

&lt;p&gt;Let’s expand our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;after-new-sesssion&lt;/code&gt; hook in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tmux.conf&lt;/code&gt;. If
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./tmux.conf&lt;/code&gt; is not found, it will detect if project is using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm&lt;/code&gt; or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yarn&lt;/code&gt; and run run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dev&lt;/code&gt; npm script in the top pane. While we are here,
let’s use current directory name as a session name.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-tmux&quot;&gt;set-hook -g after-new-session &apos;\
    run-shell &quot;tmux rename-session \&quot;$( basename \&quot;#{pane_current_path}\&quot; \)\&quot;&quot;; \
    \
    if-shell -b &quot;[ -e ./tmux.conf ]&quot; { \
        source-file ./tmux.conf; \
    } { \
        if-shell -b &quot;[ -e ./yarn.lock ]&quot; { \
            split-window -vbdl 6; \
            send -t &quot;{previous}&quot; &quot;yarn install &amp;amp;&amp;amp; yarn run --if-present dev&quot; Enter; \
            send &quot;git fetch&quot; Enter; \
        } { \
            if-shell -b &quot;[ -e ./package.json ]&quot; { \
                split-window -vbdl 6; \
                send -t &quot;{previous}&quot; &quot;npm install &amp;amp;&amp;amp; npm run --if-present dev&quot; Enter; \
                send &quot;git fetch&quot; Enter; \
            }; \
        }; \
    }; \
&apos;
&lt;/code&gt;&lt;/pre&gt;

</description>
      <pubDate>Wed, 03 Jul 2024 00:00:00 +0000</pubDate>
      <link>http://noplacelikecode.redrice.io/2024/07/03/tmux.conf.html</link>
      <guid isPermaLink="true">http://noplacelikecode.redrice.io/2024/07/03/tmux.conf.html</guid>
    </item>
    
    <item>
      <title>
        Hyphenate headings as a last resort #CSS
      </title>
      <description>&lt;style&gt;
  .demo div
  {
    font-size: 1.5em;
    width: 16ch;
    border: 2px dashed #aaa;
    resize: horizontal;
  }
&lt;/style&gt;

&lt;p&gt;Before I forgot about blogging for nine years in 2012, my
&lt;a href=&quot;/2012/01/24/word-break-inside-avoid-kind-of-deal.html&quot;&gt;last post here was about hyphenation&lt;/a&gt;. Surely things
progressed since then, right?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Right?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;(Not really.)&lt;/p&gt;

&lt;h2 id=&quot;need-for-hyphenation&quot;&gt;Need for hyphenation&lt;/h2&gt;

&lt;p&gt;Most of the time there is no need for hyphenation and text looks fine
aligned to the &lt;del&gt;left&lt;/del&gt; start&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Where hyphenation comes in
really handy is &lt;strong&gt;headings&lt;/strong&gt;. It’s easy to end up with a heading set in
a relatively large size and somebody &lt;em&gt;will&lt;/em&gt; at some point put a
very–long–word™ there. Then browsers with narrow viewport will start
adding horizontal scrolling or – &lt;i&gt;gasp!&lt;/i&gt; – your whole page will
be shrunk to accommodate the offending word.&lt;/p&gt;

&lt;p&gt;Ok. Let’s start putting some long words in narrow containers and see what
happens.&lt;/p&gt;

&lt;aside aria-hidden=&quot;&quot;&gt;
  &lt;i&gt;Note:&lt;/i&gt;
  Demo boxes on this page are set to a width that aims to fit the word
  &lt;q&gt;extraordinarily&lt;/q&gt;, but not &lt;q&gt;uncharacteristically&lt;/q&gt;. If that
  renders differently for you — boxes are resizeable.
&lt;/aside&gt;

&lt;p&gt;By default words are not hyphenated and just stick out of the container.&lt;/p&gt;

&lt;div id=&quot;demo-naked&quot; class=&quot;demo&quot; aria-hidden=&quot;&quot;&gt;
  &lt;div&gt;
    Uncharacteristically and also extraordinarily long English words.
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&quot;hyphens-auto&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyphens: auto&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;One would hope that adding &lt;a href=&quot;https://w3c.github.io/csswg-drafts/css-text/#valdef-hyphens-auto&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyphens: auto&lt;/code&gt;&lt;/a&gt; would
make things just work, but there are a few problems with it:&lt;/p&gt;

&lt;div id=&quot;demo-hyphens-auto&quot; class=&quot;demo&quot; role=&quot;img&quot; aria-label=&quot;Box with text &amp;quot;Uncharacteristically and also extraordinarily long English words.&amp;quot;. Word &amp;quot;Uncharacteristically&amp;quot; is cut off. Word &amp;quot;extraordinarily&amp;quot; is hyphenated.&quot;&gt;
  &lt;style&gt;
    #demo-hyphens-auto div
    {
      hyphens: auto;
    }
  &lt;/style&gt;
  &lt;div&gt;
    Uncharacteristically and also extraordinarily long English words.
  &lt;/div&gt;
&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;q&gt;Uncharacteristically&lt;/q&gt; is not hyphenated. What gives?&lt;/p&gt;

    &lt;p&gt;Turns out currently both Chrome and Firefox disable hyphenation of
capitalised words&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. This is to avoid performing it on proper
nouns. Good intention, but it significantly limits usage of
hyphenation in
headings, which usually starts with a capitalised word or even have
all of them capitalised.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;q&gt;extraordinarily&lt;/q&gt; is short enough to fit in a line, but gets
hyphenated.&lt;/p&gt;

    &lt;p&gt;Browsers are eager to hyphenate. In our case we want to hyphenate
words only as a last resort, when whole word doesn’t fit in a line –
that’s currently not possible with CSS.&lt;/p&gt;

    &lt;p&gt;We &lt;em&gt;could&lt;/em&gt; use &lt;a href=&quot;https://w3c.github.io/csswg-drafts/css-text-4/#propdef-hyphenate-limit-chars&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyphenate-limit-chars&lt;/code&gt;&lt;/a&gt;
to make the situation better to some extend, but it’s not perfect and
it’s only supported by Chrome.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Not visible in this example, but browser needs to support hyphenation
for your language. Check out &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/hyphens#browser_compatibility&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyphens&lt;/code&gt; browser compatibility table
on MDN&lt;/a&gt; – support for non–English is spotty to
seat the least (&lt;span aria-label=&quot;bravo&quot;&gt;👏 for&lt;/span&gt; Firefox).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;soft-hyphens&quot;&gt;Soft hyphens&lt;/h2&gt;

&lt;p&gt;You can instruct browsers of places where words can be broken using
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;shy;&lt;/code&gt; HTML entity (or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;U-00AD&lt;/code&gt; Soft Hyphen character). This takes care
of capitalised words. As a bonus it also brings hyphenation to browsers
that don’t support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyphens: auto&lt;/code&gt; (at all or in your language).&lt;/p&gt;

&lt;p&gt;Alas, hyphenation is still performed too eagerly. While we like that
&lt;q&gt;Uncharacteristically&lt;/q&gt; is broken into two lines, since it’s longer
than our container, &lt;q&gt;extraordinarily&lt;/q&gt; is not and could be carried
over to a next line.&lt;/p&gt;

&lt;div id=&quot;demo-shy&quot; class=&quot;demo&quot; role=&quot;img&quot; aria-label=&quot;Box with text &amp;quot;Uncharacteristically and also extraordinarily long English words.&amp;quot;. Words &amp;quot;Uncharacteristically&amp;quot; and &amp;quot;extraordinarily&amp;quot; are hyphenated.&quot;&gt;
  &lt;div&gt;
    Un&amp;shy;cha&amp;shy;ra&amp;shy;cte&amp;shy;ri&amp;shy;sti&amp;shy;ca&amp;shy;lly and also
    ex&amp;shy;tra&amp;shy;or&amp;shy;di&amp;shy;na&amp;shy;ri&amp;shy;ly long Eng&amp;shy;lish
    words.
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&quot;the-solution&quot;&gt;The solution&lt;/h2&gt;

&lt;p&gt;Let’s try to address the shortcomings of previous attempts with what we
have at our disposal in 2023.&lt;/p&gt;

&lt;p&gt;You will not like it.&lt;/p&gt;

&lt;p&gt;In addition to adding soft hyphens, wrap &lt;em&gt;each word&lt;/em&gt; in an element with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;display: inline-block&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This will prefer carrying whole block to the next line before
hyphenating. Effectively only breaking the word as a last resort – when
it doesn’t fit in the line on it’s own.&lt;/p&gt;

&lt;div id=&quot;demo-final&quot; class=&quot;demo&quot; role=&quot;img&quot; aria-label=&quot;Box with text &amp;quot;Uncharacteristically and also extraordinarily long English words.&amp;quot;. Word &amp;quot;Uncharacteristically&amp;quot; is hyphenated, but &amp;quot;extraordinarily&amp;quot; is not.&quot;&gt;
  &lt;style&gt;
    #demo-final .word
    {
      display: inline-block;
    }
  &lt;/style&gt;
  &lt;div&gt;
    &lt;span class=&quot;word&quot;&gt;Un&amp;shy;cha&amp;shy;ra&amp;shy;cte&amp;shy;ri&amp;shy;sti&amp;shy;ca&amp;shy;lly&lt;/span&gt;
    &lt;span class=&quot;word&quot;&gt;and&lt;/span&gt;
    &lt;span class=&quot;word&quot;&gt;also&lt;/span&gt;
    &lt;span class=&quot;word&quot;&gt;ex&amp;shy;tra&amp;shy;or&amp;shy;di&amp;shy;na&amp;shy;ri&amp;shy;ly&lt;/span&gt;
    &lt;span class=&quot;word&quot;&gt;long&lt;/span&gt;
    &lt;span class=&quot;word&quot;&gt;Eng&amp;shy;lish&lt;/span&gt;
    &lt;span class=&quot;word&quot;&gt;words.&lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Here’s a JavaScript snippet to process your headings (you are a
responsible adult and will do it only on server side, right?):&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;hyphenateSync&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;hyphens/en&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;hyphenateSync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\s&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;+/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`&amp;lt;span class=word&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;lt;/span&amp;gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that this will increase weight of your HTML, so probably don’t run
it everywhere. I’d only do it on headings and other elements that will be
displayed in a bigger font.&lt;/p&gt;

&lt;p&gt;This solution definitely
has a distinct ’90s smell all over it and makes you feel dirty
when implementing it, but it does work.&lt;/p&gt;

&lt;h2 id=&quot;the-future&quot;&gt;The future&lt;/h2&gt;

&lt;p&gt;There is a &lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/5157&quot;&gt;discussion on CSS WG about allowing hyphenating capitalised
words&lt;/a&gt;. With this and
&lt;a href=&quot;https://w3c.github.io/csswg-drafts/css-text-4/#propdef-hyphenate-limit-chars&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyphenate-limit-chars&lt;/code&gt;&lt;/a&gt; we’ll hopefully get
a reasonable CSS–only solution in the future.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Read about &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties&quot;&gt;logical properties&lt;/a&gt;. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/w3c/csswg-drafts/issues/3927&quot;&gt;Initial discussion that lead to disabling hyphenation for capitalised words in CSS spec&lt;/a&gt;. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Fri, 20 Jan 2023 00:00:00 +0000</pubDate>
      <link>http://noplacelikecode.redrice.io/2023/01/20/hyphens-last-resort.html</link>
      <guid isPermaLink="true">http://noplacelikecode.redrice.io/2023/01/20/hyphens-last-resort.html</guid>
    </item>
    
    <item>
      <title>
        WebDev advent calendars 2022
      </title>
      <description>&lt;p&gt;Last year I tried to follow too many advent calendars, so naturally I
more or less stopped reading them after a week or so. This year I’m
limiting myself up three, maybe four:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://calendar.perfplanet.com/2022&quot;&gt;Web Performance Calendar&lt;/a&gt; never
disappoints. Topic range from basics all the way to nerdy, in depth
dive–ins.&lt;/li&gt;
  &lt;li&gt;I did not follow &lt;a href=&quot;https://www.htmhell.dev/adventcalendar&quot;&gt;HTMHell Advent
calendar&lt;/a&gt; before, but it seems
to be something right up my alley.&lt;/li&gt;
  &lt;li&gt;I’m not particularly a React fan, but doing most of my work in it, I
also subscribed to &lt;a href=&quot;https://react.holiday&quot;&gt;React Holiday&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://12daysofweb.dev&quot;&gt;12 Days of Web&lt;/a&gt; starts at 13th of December.
Let’s see if I’ll be still reading those by then. 😅&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Fri, 09 Dec 2022 00:00:00 +0000</pubDate>
      <link>http://noplacelikecode.redrice.io/2022/12/09/webdev-advent-calendars-2022.html</link>
      <guid isPermaLink="true">http://noplacelikecode.redrice.io/2022/12/09/webdev-advent-calendars-2022.html</guid>
    </item>
    
    <item>
      <title>
        Mastodon misconceptions #fediverse
      </title>
      <description>&lt;p&gt;I’ve collected some of the things I found myself explaining to people in
recent days.&lt;/p&gt;

&lt;h3 id=&quot;checking-mastodon-out-is-too-much-of-a-hassle-i-dont-even-know-if-any-of-my-friends-are-on-it&quot;&gt;Checking Mastodon out is too much of a hassle. I don’t even know if any of my friends are on it&lt;/h3&gt;

&lt;p&gt;Use &lt;a href=&quot;https://fedifinder.glitch.me&quot;&gt;fedi finder&lt;/a&gt; to check out how many
people you follow on Twitter moved. It will also show what instances
they are on. After you create an account I’d recommend using
&lt;a href=&quot;https://www.movetodon.org&quot;&gt;movestodon&lt;/a&gt;, because it allows you to follow
people right from the page, instead of having to import a CSV file.&lt;/p&gt;

&lt;p&gt;When you move, leave your mastodon handle in your Twitter description,
user name or pinned tweet, so people can find you using these tools.&lt;/p&gt;

&lt;h3 id=&quot;its-hard-to-choose-what-instance-to-create-account-on-i-dont-want-to-be-stuck-with-something&quot;&gt;It’s hard to choose what instance to create account on. I don’t want to be stuck with something&lt;/h3&gt;

&lt;p&gt;You can move your account to a different insurance later. Your followers
will be redirected to the new address. Unfortunately, your toots will
not be moved.&lt;/p&gt;

&lt;h3 id=&quot;toot-is-a-silly-name&quot;&gt;“Toot” is a silly name&lt;/h3&gt;

&lt;p&gt;Agreed. But so is “tweet”, if you think about it. Also, some
&lt;a href=&quot;#user-content-clients&quot;&gt;clients&lt;/a&gt; don’t use it.&lt;/p&gt;

&lt;h3 id=&quot;how-does-moderation-work-aka-will-there-be-nazis&quot;&gt;How does moderation work (a.k.a. will there be nazis?)&lt;/h3&gt;

&lt;p&gt;Moderation is done on per–instance basis. That’s important to remember
for few reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ideally choose an instance run by people you trust.&lt;/li&gt;
  &lt;li&gt;If you don’t feel good on your instance, don’t abandon Mastodon just
yet — try finding one with admins that share your values.&lt;/li&gt;
  &lt;li&gt;Remember that many instances are run by people out of their pockets
and there’s no advertising there. Look for ways to support them on
insurances’ “About” pages, if you can afford it.&lt;/li&gt;
  &lt;li&gt;Everybody can host their own insurance, so there surely already are
very bad™️ ones out there. There are block lists of both accounts and
whole instances and they can be shared between instance admins.
Hopefully this will make it easier to keep things under control.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;fediverse-is-just-another-name-for-mastodon&quot;&gt;Fediverse is just another name for Mastodon&lt;/h3&gt;

&lt;p&gt;Mastodon is built on top of open standards like &lt;a href=&quot;https://activitypub.rocks&quot;&gt;Activity
Pub&lt;/a&gt; and is not the only one using it.
There’s e.g. Instagram–like &lt;a href=&quot;https://pixelfed.org&quot;&gt;PixelFed&lt;/a&gt;.
Fediverse’s promise is that you can follow people not only from other
Mastodon instances, but also from other “things”. Some already
established sites may join the fun: &lt;a href=&quot;https://techcrunch.com/2022/11/21/tumblr-to-add-support-for-activitypub-the-social-protocol-powering-mastodon-and-other-apps&quot;&gt;Tumblr will implement Activity
Pub&lt;/a&gt;
and &lt;a href=&quot;https://techcrunch.com/2022/11/28/flickr-weighs-support-for-activitypub-the-social-protocol-powering-twitter-alternative-mastodon&quot;&gt;Flickr is thinking about
fediverse&lt;/a&gt;
as well.&lt;/p&gt;

&lt;p&gt;Mastodon is also not the first one of its kind. There’s &lt;a href=&quot;https://kind.social/@f00fc7c8/109407989829565640&quot;&gt;a nice thread
about the history&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;i-dont-like-twittermastodon-because-it-should-be-casual-writing-about-nonsense-but-it-stays-in-the-internet-forever-ill-stick-with-instagram-storiestiktok&quot;&gt;I don’t like Twitter/Mastodon, because it should be casual, writing about nonsense, but it stays in the internet forever. I’ll stick with Instagram Stories/TikTok&lt;/h3&gt;

&lt;p&gt;You are in luck. There’s an option in Mastodon to let your toots be
deleted after a given time.&lt;/p&gt;

&lt;h3 id=&quot;so-there-are-different-clients&quot;&gt;&lt;span id=&quot;user-content-clients&quot;&gt;So, there are different clients?&lt;/span&gt;&lt;/h3&gt;

&lt;p&gt;Sure. Unlike Twitter, which didn’t really like people using non–official
clients there’s healthy ecosystem for Mastodon.&lt;/p&gt;

&lt;p&gt;The web site of your instance is installable as PWA. Because of &lt;a href=&quot;https://thenewstack.io/apples-browser-engine-ban-is-holding-back-web-app-innovation&quot;&gt;Apple
iOS browser
ban&lt;/a&gt;
you won’t get notifications on iOS, but maybe you don’t mind.&lt;/p&gt;

&lt;p&gt;Other clients lack some of the features, e.g. DM or local timeline
sections or bookmarks, viewing your started toots, but offer logging in
with multiple instances/accounts and may do a better job of remembering
position where scrolling your timeline.&lt;/p&gt;

&lt;p&gt;Some of the more popular ones:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;del&gt;&lt;a href=&quot;https://pinafore.social&quot;&gt;Pinafore&lt;/a&gt;&lt;/del&gt;
&lt;ins datetime=&quot;2023-01-30&quot;&gt;&lt;a href=&quot;https://semaphore.social&quot;&gt;Semaphore&lt;/a&gt;&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/ins&gt;
is a different PWA. It has a
simple and highly accessible interface.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://elk.zone/m.webtoo.ls/public/local&quot;&gt;Elk&lt;/a&gt; is also a PWA with
strong Twitter vibes.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://joinmastodon.org/apps&quot;&gt;Official Mastodon client&lt;/a&gt;
is available for both Android and iOS&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.keylesspalace.tusky&quot;&gt;Tusky&lt;/a&gt;
for Android&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://apps.apple.com/us/app/metatext/id1523996615&quot;&gt;Metatext&lt;/a&gt;
for iOS&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://nolanlawson.com/2023/01/09/retiring-pinafore/&quot;&gt;Pinafore’s original author stopped maintaining it&lt;/a&gt;. Project got forked as &lt;q&gt;Semaphore&lt;/q&gt;. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Tue, 06 Dec 2022 00:00:00 +0000</pubDate>
      <link>http://noplacelikecode.redrice.io/2022/12/06/mastodon-misconceptions.html</link>
      <guid isPermaLink="true">http://noplacelikecode.redrice.io/2022/12/06/mastodon-misconceptions.html</guid>
    </item>
    
    <item>
      <title>
        Set up different work e﻿–﻿mail in git by directory #git
      </title>
      <description>&lt;p&gt;For some time now git can include additional config files depending on
directory you are in (since &lt;a href=&quot;https://github.com/git/git/blob/master/Documentation/RelNotes/2.13.0.txt#L127-L130&quot;&gt;version 2.13.0&lt;/a&gt; to be
precise). Most common use case for this is setting your work e–mail for
repositories checked out in one directory
(&lt;acronym lang=&quot;la&quot; title=&quot;exempli gratia&quot;&gt;e.g.&lt;/acronym&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/src/@example-inc&lt;/code&gt;)
while keeping your private e–mail for the rest of the projects.&lt;/p&gt;

&lt;p&gt;There’s a good chance you currently have something similar to this in
your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.gitconfig&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[user]&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Test “The Face” McTestface&quot;&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;test@example.net&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# Hopefully you also have a GPG key for the e–mail.
&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;# Ignore signingKey key here and later if you don’t.
&lt;/span&gt;    &lt;span class=&quot;py&quot;&gt;signingKey&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;0123456789ABCDEF&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you want to use a different e–mail for work stuff, you need to
remember to set it every time you create or clone a repository:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config user.name &lt;span class=&quot;s2&quot;&gt;&quot;Test McTestface&quot;&lt;/span&gt;
git config user.email &lt;span class=&quot;s2&quot;&gt;&quot;test.mctestface@example.com&quot;&lt;/span&gt;
git config user.signingKey &lt;span class=&quot;s2&quot;&gt;&quot;FEDCBA9876543210&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;No more!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can add a &lt;a href=&quot;https://git-scm.com/docs/git-config#_conditional_includes&quot;&gt;conditional include&lt;/a&gt; to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.gitconfig&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[user]&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Test “The Face” McTestface&quot;&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;test@example.net&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;signingKey&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;0123456789ABCDEF&quot;&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[includeIf &quot;gitdir:~/src/@example-inc&quot;]&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;./.gitconfig.work&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.gitconfig.work&lt;/code&gt; and put any config you want to be used
for repositories checked out in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/src/@example-inc&lt;/code&gt; (or its
subdirectories):&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[user]&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Test McTestface&quot;&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;email&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;test.mctestface@example.com&quot;&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;signingKey&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;FEDCBA9876543210&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Presto!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;If you are using vim, you may want to add a &lt;a href=&quot;https://vimhelp.org/options.txt.html#modeline&quot;&gt;vim modeline&lt;/a&gt; to get proper
syntax highlighting in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.gitconfig.work&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# vim: ft=gitconfig
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
      <pubDate>Sun, 29 Aug 2021 00:00:00 +0000</pubDate>
      <link>http://noplacelikecode.redrice.io/2021/08/29/git-email-by-directory.html</link>
      <guid isPermaLink="true">http://noplacelikecode.redrice.io/2021/08/29/git-email-by-directory.html</guid>
    </item>
    
    <item>
      <title>
        `word-break-inside: avoid` kind of deal #css
      </title>
      <description>&lt;p&gt;I’ve spent some time looking for something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;word-break-inside: avoid&lt;/code&gt; (sort of an opposite to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;wbr /&amp;gt;&lt;/code&gt; — a way to avoid breaking words in a inline element, but do that, if it’s longer than a line, just like page-break-inside: avoid does for pages in print). Turns out there’s none.&lt;/p&gt;

&lt;p&gt;Just seemd that’s it’s too trivial thing to use JavaScritpt for that. But actually you can do just that using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;display: inline-block&lt;/code&gt;.&lt;/p&gt;

&lt;iframe src=&quot;https://dabblet.com/gist/11193537&quot; style=&quot;width:100%; height:10em&quot;&gt;

```html
&lt;p&gt;
    Licensed under
    &lt;span class=&quot;avoid-br&quot;&gt;Creative Commons Attribute-ShareAlike 2.0&lt;/span&gt;
&lt;/p&gt;

&lt;style&gt;
  .avoid-br
  {
      display: inline-block;
  }
&lt;/style&gt;
```

&lt;a href=&quot;https://dabblet.com/gist/11193537&quot;&gt;View the code and result.&lt;/a&gt;

&lt;/iframe&gt;
</description>
      <pubDate>Tue, 24 Jan 2012 20:25:00 +0000</pubDate>
      <link>http://noplacelikecode.redrice.io/2012/01/24/word-break-inside-avoid-kind-of-deal.html</link>
      <guid isPermaLink="true">http://noplacelikecode.redrice.io/2012/01/24/word-break-inside-avoid-kind-of-deal.html</guid>
    </item>
    
    <item>
      <title>
        &lt;abbr&gt;PHP&lt;/abbr&gt; just made me doubt printf. /: #php #wtf
      </title>
      <description>
</description>
      <pubDate>Wed, 28 Sep 2011 12:18:01 +0000</pubDate>
      <link>http://noplacelikecode.redrice.io/2011/09/28/php-just-made-me-doubt-printf.html</link>
      <guid isPermaLink="true">http://noplacelikecode.redrice.io/2011/09/28/php-just-made-me-doubt-printf.html</guid>
    </item>
    
    <item>
      <title>
        call methods of objects crated on-the-fly in &lt;abbr&gt;PHP&lt;/abbr&gt; #php
      </title>
      <description>&lt;p&gt;PHP sux, that’s not news.&lt;/p&gt;

&lt;p&gt;I always wanted to do this:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;but it did not allow me. But there’s a neat trick, which makes it possible. Kind of. Just define small helper function:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;and now:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// almost like (new Object())-&amp;gt;method();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;voila!&lt;/p&gt;

&lt;p&gt;You can also pretend to refer to array keys of arrays created on-the-fly.&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;array_flip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;key&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// almost like array_flip($array)[&apos;key&apos;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;update&quot;&gt;Update&lt;/h3&gt;

&lt;p&gt;Newer versions of &lt;abbr&gt;PHP&lt;/abbr&gt; allows that syntax.&lt;/p&gt;
</description>
      <pubDate>Mon, 28 Mar 2011 15:58:50 +0000</pubDate>
      <link>http://noplacelikecode.redrice.io/2011/03/28/call-methods-of-objects-crated-on-the-fly-in-php.html</link>
      <guid isPermaLink="true">http://noplacelikecode.redrice.io/2011/03/28/call-methods-of-objects-crated-on-the-fly-in-php.html</guid>
    </item>
    
    <item>
      <title>
        XML­Http­Request-Capable
      </title>
      <description>&lt;p&gt;Why won’t browsers send any XMLHttpRequest-Capable HTTP headers?&lt;/p&gt;
</description>
      <pubDate>Fri, 18 Feb 2011 18:33:00 +0000</pubDate>
      <link>http://noplacelikecode.redrice.io/2011/02/18/xmlhttprequest-capable-http-header.html</link>
      <guid isPermaLink="true">http://noplacelikecode.redrice.io/2011/02/18/xmlhttprequest-capable-http-header.html</guid>
    </item>
    
  </channel>
</rss>
