<?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>Mkdocs on foosel.net</title><link>https://foosel.net/tags/mkdocs/</link><description>Recent content in Mkdocs on foosel.net</description><generator>Hugo</generator><language>en-us</language><copyright>Gina Häußge (foosel)</copyright><lastBuildDate>Fri, 28 Jul 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://foosel.net/tags/mkdocs/index.xml" rel="self" type="application/rss+xml"/><item><title>How to make MkDocs support site_url relative URLs</title><link>https://foosel.net/til/how-to-make-mkdocs-support-siteurl-relative-urls/</link><pubDate>Thu, 27 Jul 2023 00:00:00 +0000</pubDate><guid>https://foosel.net/til/how-to-make-mkdocs-support-siteurl-relative-urls/</guid><description>&lt;p&gt;I&amp;rsquo;m currently &lt;em&gt;finally&lt;/em&gt; back on converting the &lt;a href="https://octoprint.org"&gt;OctoPrint&lt;/a&gt; docs to using Markdown and &lt;a href="https://mkdocs.org"&gt;MkDocs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since I have some images in the docs that I want to be able to reference without having to use relative URLs (&lt;code&gt;../../../../images/&lt;/code&gt;),
especially since that would tie things in OctoPrint&amp;rsquo;s source tree structure too close to things in its documentation tree structure that
might or might not end up being in a different repository in the future, I needed a way to use absolute URLs here (&lt;code&gt;/images/&lt;/code&gt;). But
since the docs will most likely also end up being hosted on a version specific subpath of &lt;code&gt;docs.octoprint.org&lt;/code&gt;, just using
(host) absolute URLs would not work either and break.&lt;/p&gt;</description><content:encoded><![CDATA[<p>I&rsquo;m currently <em>finally</em> back on converting the <a href="https://octoprint.org">OctoPrint</a> docs to using Markdown and <a href="https://mkdocs.org">MkDocs</a>.</p>
<p>Since I have some images in the docs that I want to be able to reference without having to use relative URLs (<code>../../../../images/</code>),
especially since that would tie things in OctoPrint&rsquo;s source tree structure too close to things in its documentation tree structure that
might or might not end up being in a different repository in the future, I needed a way to use absolute URLs here (<code>/images/</code>). But
since the docs will most likely also end up being hosted on a version specific subpath of <code>docs.octoprint.org</code>, just using
(host) absolute URLs would not work either and break.</p>
<p>There&rsquo;s <a href="https://github.com/mkdocs/mkdocs/issues/1592">several</a> <a href="https://github.com/mkdocs/mkdocs/issues/192">issues</a> on the MkDocs issue
tracker about workflow problems caused by this, but the suggested workarounds like using <a href="https://mkdocs-macros-plugin.readthedocs.io/">macros</a>
to prefix a variable&rsquo;s contents to related URLs didn&rsquo;t work for me due to me also heavily relying on <a href="mkdocstrings.github.io/">mkdocstrings</a>,
and anything contained in docstrings is not processed by macros<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p>So I got the idea to implement a minimal MkDocs plugin that would just turn all URLs contained in <code>href</code> and <code>src</code> attributes
that are prefixed with a custom schema <code>site:</code> schema into <em>site relative</em> URLs, with this effect. Example:</p>
<table>
  <thead>
      <tr>
          <th>URL</th>
          <th>site_url</th>
          <th>resulting URL</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>site:images/foo.png</code></td>
          <td><code>https://docs.octoprint.org/</code></td>
          <td><code>/images/foo.png</code></td>
      </tr>
      <tr>
          <td><code>site:images/foo.png</code></td>
          <td><code>https://docs.octoprint.org/1.9.x/</code></td>
          <td><code>/1.9.x/images/foo.png</code></td>
      </tr>
  </tbody>
</table>
<p>Using a <a href="https://www.mkdocs.org/user-guide/configuration/#hooks">hook</a> I could register a callback for the
<a href="https://www.mkdocs.org/dev-guide/plugins/#on_page_content"><code>on_page_content</code></a> event that would then replace all URLs as needed
in the generated page HTML.</p>
<p>And this is the resulting <code>site_urls.py</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> logging
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> urllib.parse
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> re
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> mkdocs.plugins
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>log <span style="color:#f92672">=</span> logging<span style="color:#f92672">.</span>getLogger(<span style="color:#e6db74">&#34;mkdocs&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SITE_URLS_REGEX <span style="color:#f92672">=</span> re<span style="color:#f92672">.</span>compile(<span style="color:#e6db74">r</span><span style="color:#e6db74">&#39;(href|src)=&#34;site:([^&#34;]+)&#34;&#39;</span>, re<span style="color:#f92672">.</span>IGNORECASE)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">@mkdocs.plugins.event_priority</span>(<span style="color:#ae81ff">50</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">on_page_content</span>(html, page, config, files):
</span></span><span style="display:flex;"><span>    site_url <span style="color:#f92672">=</span> config[<span style="color:#e6db74">&#34;site_url&#34;</span>]
</span></span><span style="display:flex;"><span>    path <span style="color:#f92672">=</span> urllib<span style="color:#f92672">.</span>parse<span style="color:#f92672">.</span>urlparse(site_url)<span style="color:#f92672">.</span>path
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> path:
</span></span><span style="display:flex;"><span>        path <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;/&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> <span style="color:#f92672">not</span> path<span style="color:#f92672">.</span>endswith(<span style="color:#e6db74">&#34;/&#34;</span>):
</span></span><span style="display:flex;"><span>        path <span style="color:#f92672">+=</span> <span style="color:#e6db74">&#34;/&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">_replace</span>(<span style="color:#66d9ef">match</span>):
</span></span><span style="display:flex;"><span>        param <span style="color:#f92672">=</span> <span style="color:#66d9ef">match</span><span style="color:#f92672">.</span>group(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>        url <span style="color:#f92672">=</span> <span style="color:#66d9ef">match</span><span style="color:#f92672">.</span>group(<span style="color:#ae81ff">2</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> url<span style="color:#f92672">.</span>startswith(<span style="color:#e6db74">&#34;/&#34;</span>):
</span></span><span style="display:flex;"><span>            url <span style="color:#f92672">=</span> url[<span style="color:#ae81ff">1</span>:]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        log<span style="color:#f92672">.</span>info(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Replacing site:</span><span style="color:#e6db74">{</span>match<span style="color:#f92672">.</span>group(<span style="color:#ae81ff">2</span>)<span style="color:#e6db74">}</span><span style="color:#e6db74"> with </span><span style="color:#e6db74">{</span>path<span style="color:#e6db74">}{</span>url<span style="color:#e6db74">}</span><span style="color:#e6db74">...&#34;</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#e6db74">f</span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">{</span>param<span style="color:#e6db74">}</span><span style="color:#e6db74">=&#34;</span><span style="color:#e6db74">{</span>path<span style="color:#e6db74">}{</span>url<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> SITE_URLS_REGEX<span style="color:#f92672">.</span>sub(_replace, html)
</span></span></code></pre></div><p>that I&rsquo;ve registered as a hook in my <code>mkdocs.yaml</code> like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">hooks</span>:
</span></span><span style="display:flex;"><span>  - <span style="color:#ae81ff">site_urls.py</span>
</span></span></code></pre></div><p>Seems to work just fine, both for images and links! 😄</p>
<p><strong>Update 2023-07-28</strong>: I&rsquo;ve now published this as a proper plugin on PyPI, see <a href="https://pypi.org/project/mkdocs-site-urls/">mkdocs-site-urls</a>.
With that, all you need to do - given you are already on MkDocs 1.5 or newer - is installing the plugin via <code>pip install mkdocs-site-urls</code> and
then adding this to your <code>mkdocs.yaml</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">plugins</span>:
</span></span><span style="display:flex;"><span>  - <span style="color:#ae81ff">site-urls</span>
</span></span></code></pre></div><div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>As I found out when I wanted to add a <code>version_added</code> macro, which simply didn&rsquo;t render.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded></item></channel></rss>