<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Inkstone Demo</title><link>https://inkstone.125520.xyz/</link><description>A minimal bilingual Hugo template for longreads.</description><generator>Hugo</generator><language>en</language><managingEditor>Inkstone Author</managingEditor><copyright>© 2026 Inkstone Author</copyright><lastBuildDate>Fri, 15 May 2026 12:14:50 +0000</lastBuildDate><atom:link href="https://inkstone.125520.xyz/index.xml" rel="self" type="application/rss+xml"/><item><title>Multilingual Content Authoring</title><link>https://inkstone.125520.xyz/multilingual-content-authoring/</link><pubDate>Mon, 20 Apr 2026 00:00:00 +0000</pubDate><guid isPermaLink="true">https://inkstone.125520.xyz/multilingual-content-authoring/</guid><description>How Inkstone handles bilingual content models.</description><content:encoded><![CDATA[<p>Inkstone uses Hugo&rsquo;s content language fallback model. The default site language lives at root URLs (<code>/posts/foo/</code>); secondary languages get a subdirectory (<code>/zh-cn/posts/foo/</code>).</p>
<h2 id="filename-convention">Filename convention</h2>
<p>There are two ways to mark content language:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">content/posts/foo.md          # default language
</span></span><span class="line"><span class="cl">content/posts/foo.zh-cn.md    # Chinese version
</span></span><span class="line"><span class="cl">content/posts/foo.en.md       # explicit English (when default is zh-cn)
</span></span></code></pre></div><p>Or use directory layout:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">content/en/posts/foo.md
</span></span><span class="line"><span class="cl">content/zh-cn/posts/foo.md
</span></span></code></pre></div><p>The theme works with either; pick the one that matches your editing flow.</p>
<h2 id="language-switcher">Language switcher</h2>
<p>The header has a language toggle. It only appears for pages that have a translation. If a Chinese post has no English version, the toggle is hidden on the Chinese page — no broken links, no stub pages.</p>
<h2 id="i18n-strings">i18n strings</h2>
<p>UI strings live in <code>i18n/&lt;lang&gt;.toml</code>. The theme ships with <code>en.toml</code> and <code>zh-cn.toml</code>. To add a new language:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">cp themes/inkstone/i18n/en.toml i18n/ja.toml
</span></span><span class="line"><span class="cl"><span class="c1"># Then translate the values inside</span>
</span></span></code></pre></div><p>Add the language to your site config:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="p">[</span><span class="nx">languages</span><span class="p">.</span><span class="nx">ja</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">  <span class="nx">label</span> <span class="p">=</span> <span class="s2">&#34;日本語&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">locale</span> <span class="p">=</span> <span class="s2">&#34;ja&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nx">weight</span> <span class="p">=</span> <span class="mi">3</span>
</span></span><span class="line"><span class="cl">  <span class="p">[</span><span class="nx">languages</span><span class="p">.</span><span class="nx">ja</span><span class="p">.</span><span class="nx">params</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="nx">description</span> <span class="p">=</span> <span class="s2">&#34;...&#34;</span>
</span></span></code></pre></div><h2 id="reading-time">Reading time</h2>
<p>Reading time is calculated per language using Hugo&rsquo;s <code>WordCount</code> and <code>ReadingTime</code>. With <code>hasCJKLanguage = true</code> set, CJK pages report 501 chars/minute; non-CJK pages report 213 words/minute. The theme reads the page&rsquo;s actual language and uses the right formula automatically.</p>

  <link
    rel="stylesheet"
    type="text/css"
    href="/css/_shortcodes/admonition.css"
  />
  <div
    class="shortcode-admonition shortcode-admonition-warning "
  >
      <div class="shortcode-admonition-title">Don&rsquo;t override globally</div>
      <div class="shortcode-admonition-content">Avoid setting <code>hasCJKLanguage</code> per-page or per-language — it&rsquo;s a site-wide flag. Setting it once at the top of <code>hugo.toml</code> is enough; Hugo handles the rest based on actual content.</div>
  </div>

<p>That&rsquo;s the multilingual model in a nutshell. For the underlying patterns, see Hugo&rsquo;s <a href="https://gohugo.io/content-management/multilingual/" target="_blank" rel="noopener">language management docs<span class="external-mark" aria-hidden="true">↗</span></a>
.</p>
]]></content:encoded></item><item><title>Mixing CJK and Latin Text</title><link>https://inkstone.125520.xyz/mixing-cjk-and-latin-text/</link><pubDate>Wed, 15 Apr 2026 00:00:00 +0000</pubDate><guid isPermaLink="true">https://inkstone.125520.xyz/mixing-cjk-and-latin-text/</guid><description>How Inkstone handles typography when Chinese, Japanese, or Korean text mixes with Latin scripts.</description><content:encoded><![CDATA[<p>This post is the English companion to a real CJK demo. Inkstone is opinionated about mixed-script typography — here&rsquo;s what the theme does for you when an article mixes 中文 with English.</p>
<h2 id="what-inkstone-does-for-cjk">What Inkstone does for CJK</h2>
<ol>
<li><strong>Word counting respects characters, not whitespace tokens.</strong> With <code>hasCJKLanguage = true</code> set site-wide, Hugo&rsquo;s <code>.WordCount</code> counts CJK characters individually instead of trying (and failing) to whitespace-tokenize them.</li>
<li><strong>Reading time uses 501 chars/min on CJK pages</strong>, the constant Hugo derives from CJK reading speed studies. Latin pages stay on the 213 word/min default.</li>
<li><strong>Font stack prefers <code>LXGW WenKai</code></strong>, falling back through <code>Noto Serif SC</code> to system serif — chosen to keep CJK and Latin glyphs at compatible weights.</li>
<li><strong>Line-height bumps to 1.7</strong> on CJK pages (vs. 1.6 for pure Latin) to compensate for taller character bodies.</li>
</ol>
<h2 id="why-this-matters-in-practice">Why this matters in practice</h2>
<p>Mixed-script paragraphs are where naive themes break. A sentence like &ldquo;我读了 Borges 的 <em>Ficciones</em>&rdquo; has three writing systems and an italic stretch — and most themes either let the browser produce a fake oblique on CJK glyphs (ugly) or force a single font for everything (worse).</p>
<p>Inkstone scopes <code>font-style: normal</code> to the CJK-detected ranges in prose, so the Latin italics still render properly while the CJK characters stay upright in their natural form.</p>
<h2 id="punctuation-and-spacing">Punctuation and spacing</h2>
<p>The <code>.prose</code> region opts into:</p>
<ul>
<li><code>font-feature-settings: &quot;palt&quot;</code> for proportional alternates on CJK punctuation — <code>，</code> <code>。</code> <code>？</code> <code>！</code> collapse the half-em &ldquo;air&rdquo; they ship with by default.</li>
<li><code>text-spacing-trim</code> to handle leading/trailing punctuation at line breaks.</li>
<li>A 0.15em soft gap between CJK characters and adjacent Latin/numeric runs (Pangu-style), scoped to prose only — UI chrome is left alone.</li>
</ul>
<h2 id="try-it-on-a-real-chinese-post">Try it on a real Chinese post</h2>
<p>The translation of this post — <code>03-cjk-mixed.zh-cn.md</code> — is where you can actually see the typography work. Switch the language toggle to view it.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">content/posts/03-cjk-mixed.md         # this English post
</span></span><span class="line"><span class="cl">content/posts/03-cjk-mixed.zh-cn.md   # the Chinese demo post
</span></span></code></pre></div><h2 id="summary">Summary</h2>
<p>If you write a lot of bilingual prose, Inkstone aims to remove the typography distractions so you can focus on what the words are doing. Most of these decisions are scoped to <code>.prose</code> and won&rsquo;t bleed into UI chrome, so they&rsquo;re safe to compose with other themes&rsquo; design tokens if you fork.</p>
]]></content:encoded></item><item><title>Typography &amp; Prose</title><link>https://inkstone.125520.xyz/typography-prose/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><guid isPermaLink="true">https://inkstone.125520.xyz/typography-prose/</guid><description>Reading-optimized typography for longreads.</description><content:encoded><![CDATA[<p>Inkstone is built for <strong>longreads</strong>. This post showcases the prose typography rules that the theme applies to every article body.</p>
<h2 id="headings">Headings</h2>
<p>The theme uses <code>LXGW WenKai</code> for body text in CJK contexts and falls back to <code>Noto Serif SC</code> and system serif fonts. Headings inherit the same family by default but can be re-styled per project via <code>assets/css/variable.css</code> design tokens.</p>
<h3 id="third-level-heading">Third-level heading</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
<h4 id="fourth-level-heading">Fourth-level heading</h4>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<h2 id="paragraph-spacing">Paragraph spacing</h2>
<p>The default rhythm is 1.6× line-height with a comfortable max-width that keeps line length around 65–75 characters. This is tuned for desktop reading; on mobile the layout collapses to a single column with adjusted spacing.</p>
<p>For mixed CJK/Latin text, the theme bumps line-height slightly to accommodate the taller character box of Chinese glyphs without making English paragraphs feel airy.</p>
<h2 id="lists">Lists</h2>
<p>Unordered:</p>
<ul>
<li>First item with a meaningful sentence about something</li>
<li>Second item that demonstrates how the bullet styling looks</li>
<li>Third item just for completeness
<ul>
<li>Nested item one</li>
<li>Nested item two</li>
</ul>
</li>
</ul>
<p>Ordered:</p>
<ol>
<li>Numbered items use a slightly different rhythm</li>
<li>The numbers themselves are styled to match the prose color</li>
<li>Nested ordered lists work too:
<ol>
<li>Indented one</li>
<li>Indented two</li>
</ol>
</li>
</ol>
<h2 id="inline-elements">Inline elements</h2>
<p>Here&rsquo;s a sentence with <code>inline code</code>, <strong>bold text</strong>, <em>italic text</em>, and a <a href="https://github.com/BerBai/inkstone" target="_blank" rel="noopener">link to the source<span class="external-mark" aria-hidden="true">↗</span></a>
. The link gets an external-link mark automatically when it points off-domain.</p>
<h2 id="blockquotes">Blockquotes</h2>
<blockquote>
<p>Reading is to the mind what exercise is to the body.</p>
<p>— Joseph Addison</p>
</blockquote>
<h2 id="code-blocks">Code blocks</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;&#34;&#34;Classic recursive fib — please don&#39;t use this in production.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="n">n</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">fibonacci</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">fibonacci</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">([</span><span class="n">fibonacci</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">)])</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">debounce</span> <span class="o">=</span> <span class="p">(</span><span class="nx">fn</span><span class="p">,</span> <span class="nx">ms</span> <span class="o">=</span> <span class="mi">250</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kd">let</span> <span class="nx">t</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="k">return</span> <span class="p">(...</span><span class="nx">args</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">t</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nx">t</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(()</span> <span class="p">=&gt;</span> <span class="nx">fn</span><span class="p">(...</span><span class="nx">args</span><span class="p">),</span> <span class="nx">ms</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span></code></pre></div><h2 id="tables">Tables</h2>
<table>
  <thead>
      <tr>
          <th>Feature</th>
          <th>Inkstone</th>
          <th>PaperMod</th>
          <th>Hugo Default</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Bilingual i18n</td>
          <td>✅</td>
          <td>✅</td>
          <td>❌</td>
      </tr>
      <tr>
          <td>CJK reading time</td>
          <td>✅</td>
          <td>❌</td>
          <td>❌</td>
      </tr>
      <tr>
          <td>Built-in ⌘K search</td>
          <td>✅</td>
          <td>❌</td>
          <td>❌</td>
      </tr>
      <tr>
          <td>Tailwind v4</td>
          <td>✅</td>
          <td>❌</td>
          <td>❌</td>
      </tr>
      <tr>
          <td>25+ shortcodes</td>
          <td>✅</td>
          <td>❌</td>
          <td>❌</td>
      </tr>
  </tbody>
</table>
<h2 id="pullquote">Pullquote</h2>

<blockquote class="pullquote">
  A classic is a book that has never finished saying what it has to say.
  <cite>— Italo Calvino</cite>
</blockquote>

<p>That&rsquo;s the gist. For a complete shortcode catalog, see the <a href="/shortcodes-demo/">Shortcodes demo</a>
.</p>
]]></content:encoded></item><item><title>Welcome to Inkstone</title><link>https://inkstone.125520.xyz/welcome-to-inkstone/</link><pubDate>Wed, 01 Apr 2026 00:00:00 +0000</pubDate><guid isPermaLink="true">https://inkstone.125520.xyz/welcome-to-inkstone/</guid><description>A quick tour of what the theme can do.</description><content:encoded><![CDATA[<p>This is the first post in the Inkstone demo site. It exists to show off the theme&rsquo;s prose typography, callouts, and a handful of inline shortcodes.</p>
<h2 id="why-inkstone">Why Inkstone?</h2>
<p>Inkstone is built around three convictions:</p>
<ol>
<li><strong>Reading is the primary mode.</strong> Every layout decision serves the reader, not the author&rsquo;s ego.</li>
<li><strong>Bilingual is the default.</strong> Mixed Chinese/English content gets proper line-height, character-counted reading time, and a font fallback chain that doesn&rsquo;t render Latin glyphs in a CJK font.</li>
<li><strong>Progressive enhancement is non-negotiable.</strong> Search, lightbox, theme toggle all degrade gracefully when JS is disabled.</li>
</ol>
<div class="callout callout-note" role="note">
  <div class="callout-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg></div>
  <div class="callout-body"><p class="callout-title">Setup tip</p>
    The theme works out of the box with <code>hugo server</code>. Tailwind v4 is processed through Hugo&rsquo;s built-in <code>css.TailwindCSS</code> function — no separate npm watch step needed during development.
  </div>
</div>

<h2 id="built-in-shortcodes">Built-in shortcodes</h2>
<p>Inkstone ships with 25+ content shortcodes. The most common ones:</p>
<ul>
<li><strong>Callouts and admonitions</strong> — Five severity levels (note, tip, warning, danger, success) with i18n-aware labels</li>
<li><strong>Galleries</strong> — Justified grid + lightbox, configured via JSON data</li>
<li><strong>Code blocks</strong> — Highlighted with Chroma, with optional copy button and line numbers</li>
<li><strong>Diagrams</strong> — Mermaid and Markmap rendered client-side via CDN</li>
<li><strong>Math</strong> — MathJax v4, only loaded on pages that actually use math</li>
</ul>
<p>For the full reference with live examples, see the <a href="/shortcodes-demo/">Shortcodes demo page</a>
.</p>

  <link
    rel="stylesheet"
    type="text/css"
    href="/css/_shortcodes/admonition.css"
  />
  <div
    class="shortcode-admonition shortcode-admonition-tip "
  >
      <div class="shortcode-admonition-title">Pagefind search</div>
      <div class="shortcode-admonition-content">Press <kbd>⌘K</kbd> (or <kbd>Ctrl-K</kbd> on non-Mac) to open the search modal. The theme provides the UI; you wire up Pagefind in your build pipeline (<code>pagefind --site public</code> after <code>hugo</code>).</div>
  </div>

<h2 id="whats-next">What&rsquo;s next</h2>
<p>Browse the <a href="/posts/">Posts</a>
 section for more samples, or jump directly to the <a href="/shortcodes-demo/">Shortcodes demo</a>
 for the full reference.</p>
]]></content:encoded></item></channel></rss>