<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://ulysseszh.github.io/feed/tags/web.xml" rel="self" type="application/atom+xml" /><link href="https://ulysseszh.github.io/" rel="alternate" type="text/html" hreflang="en-US" /><updated>2026-04-19T16:48:01-07:00</updated><id>https://ulysseszh.github.io/feed/tags/web.xml</id><title type="html"><![CDATA[Ulysses’ trip]]></title><subtitle>Here we are at the awesome (awful) blog written by UlyssesZhan!</subtitle><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><entry><title type="html"><![CDATA[Embed the latest Mastodon post in my website]]></title><link href="https://ulysseszh.github.io/update/2023/11/19/embed-mastodon.html" rel="alternate" type="text/html" title="Embed the latest Mastodon post in my website" /><published>2023-11-19T13:51:36-08:00</published><updated>2023-11-19T13:51:36-08:00</updated><id>https://ulysseszh.github.io/update/2023/11/19/embed-mastodon</id><content type="html" xml:base="https://ulysseszh.github.io/update/2023/11/19/embed-mastodon.html"><![CDATA[<p>As we all know you can <a href="https://help.twitter.com/en/using-x/embed-x-feed" target="_blank" rel="external">embed a Twitter timeline</a> in your website like this:</p>
<details>
<summary>
A Twitter timeline
</summary>
<a class="twitter-timeline" id="twitter-timeline-UlyssesZhan" data-height="400" href="https://twitter.com/UlyssesZhan">Tweets by UlyssesZhan</a>
<script><![CDATA[
document.getElementById('twitter-timeline-UlyssesZhan').setAttribute('data-theme', matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
]]]]><![CDATA[></script>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"/>
</details>
<p>You can also embed a Twitter post like this:</p>
<details>
<summary>
A Twitter post
</summary>
<blockquote class="twitter-tweet" id="twitter-1561297804596695041">
<a href="https://twitter.com/UlyssesZhan/status/1561297804596695041">Twitter post from UlyssesZhan</a>
</blockquote>
<script><![CDATA[
document.getElementById('twitter-1561297804596695041').setAttribute('data-theme', matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
]]]]><![CDATA[></script>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"/>
</details>
<p>However, <a href="https://github.com/mastodon/mastodon/issues/1065#issuecomment-297531140" target="_blank" rel="external">there is no official way of embedding a Mastodon timeline</a>. At most, you can embed a specific Mastodon post like this:</p>
<details>
<summary>
A Mastodon post
</summary>
<div class="embed-container">
<iframe id="mastodon.social-ulysseszhan-111417118208218240" src="https://mastodon.social/@ulysseszhan/111417118208218240/embed" class="mastodon-embed" allowfullscreen="" scrolling="">
</iframe>
</div>
<script src="https://mastodon.social/embed.js" async=""/>
<script><![CDATA[
(async () => {
	const iframe = document.getElementById('mastodon.social-ulysseszhan-111417118208218240');
	new MutationObserver((mutations, observer) => {
		if (!mutations.some(m => m.attributeName === 'height')) {
			return;
		}
		iframe.parentNode.style.paddingBottom = iframe.height + 'px';
		observer.disconnect();
	}).observe(iframe, { attributes: true });
})();
]]]]><![CDATA[></script>
</details>
<p>This just embeds a specific Mastodon post instead of dynamically grabbing the latest posts. Also, this embed requires JavaScript on the client side, which I have been trying to avoid. Another downside of this embed is that <a href="https://stackoverflow.com/a/74523939" target="_blank" rel="external">it does not have a light-theme version</a>.</p>
<p>Thanks to Mastodon’s API, the community implemented <a href="https://mastodon-embeds.glitch.me" target="_blank" rel="external">various ways of embedding Mastodon timelines or posts</a>. I then decided to develop my own way of embedding Mastodon posts. Here was the roadmap:</p>
<ul>
<li>The home page of my website shows my latest Mastodon post.</li>
<li>It should be rendered server-side, without the necessity of client-side JavaScript.</li>
<li>Blend the post in the webpage with a style consistent with rest of the webpage.</li>
</ul>
<p>How do I ensure the embedded post is always the latest one if it was rendered server-side? This means I have to somehow trigger the building and deployment of by website automatically whenever a new Mastodon post is created. Thanks to the <a href="https://github.com/huginn/huginn" target="_blank" rel="external">Huginn</a> instance deployed on my self-hosted server, I can monitor my Mastodon account and trigger a GitHub Actions workflow whenever there is a new post.</p>
<p>Here is then the idea of implementing the roadmap:</p>
<ol type="1">
<li>On the Jekyll side:
<ol type="1">
<li>Write a Jekyll hook at <code>:site</code> <code>:after_init</code> that reads the <a href="https://mastodon.social/@ulysseszhan.rss" target="_blank" rel="external">RSS feed of my Mastodon account</a> to get all information I need.</li>
<li>Write a Liquid template that can be populated with the collected information.</li>
<li>Include the Liquid template in the home page of my website and write some SCSS to style it.</li>
</ol></li>
<li>On the GitHub side:
<ol type="1">
<li>Use <a href="https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages" target="_blank" rel="external">GitHub Actions to build and deploy on GitHub Pages</a> and make the GitHub Actions triggered by <a href="https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch" target="_blank" rel="external"><code>workflow_dispatch</code></a>.</li>
<li>Create a <a href="https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic" target="_blank" rel="external">GitHub personal access token</a>. It will then be used to trigger <a href="https://docs.github.com/en/rest/actions/workflows?apiVersion=2022-11-28#create-a-workflow-dispatch-event" target="_blank" rel="external">GitHub Actions through REST API</a>.</li>
</ol></li>
<li>On the Huginn side:
<ol type="1">
<li>Create an agent to monitor the RSS feed of my Mastodon account.</li>
<li>Create an agent to send HTTP requests to invoke GitHub’s REST API. It receives events from the first agent and triggers the GitHub Actions workflow.</li>
</ol></li>
</ol>
<p>Great! Now, my website can show my latest Mastodon post on the home page.</p>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="update" /><category term="web" /><category term="jekyll" /><category term="selfhosting" /><summary type="html"><![CDATA[I show the latest Mastodon post in my website hosted on GitHub Pages, and it does not require JavaScript on the client side. How do I do that?]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2023-11-19-embed-mastodon.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2023-11-19-embed-mastodon.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[I restructured my blog]]></title><link href="https://ulysseszh.github.io/update/2023/11/06/restructure.html" rel="alternate" type="text/html" title="I restructured my blog" /><published>2023-11-06T00:06:52-08:00</published><updated>2023-11-06T00:06:52-08:00</updated><id>https://ulysseszh.github.io/update/2023/11/06/restructure</id><content type="html" xml:base="https://ulysseszh.github.io/update/2023/11/06/restructure.html"><![CDATA[<h2 data-label="0.1" id="rendering-equations-server-side">Rendering equations server-side</h2>
<p>I have been using <a href="https://mathjax.org" target="_blank" rel="external">MathJax</a> as a client-side equation renderer to render equations on my blog for a long time.</p>
<p>The main problem about the client-side rendering is that it makes people that turn off JavaScript on their browsers (e.g. for privacy reasons) unable to see the equations in my articles. Another problem is that it is annoying to wait for the browser to render all the equations, especially if the site owner could have rendered them for you.</p>
<p>I actually have had some experience in server-side equation rendering in Jekyll. In <a href="/programming/2022/11/08/math-emails.html">a past post</a>, I talked about how I used Jekyll and <a href="https://katex.org" target="_blank" rel="external">KaTeX</a> to render equations in emails server-side. For the <a href="https://sunniesnow.github.io" target="_blank" rel="external">website of Sunniesnow</a> (see <a href="/update/2023/09/08/sunniesnow.html">here</a> for a related post), I use <a href="https://github.com/linjer/jekyll-katex/" target="_blank" rel="external">jekyll-katex</a> to render the equations server-side.</p>
<p>Then, I thought, what is stopping me to render equations server-side on my blog? I then started the migration.</p>
<h3 data-label="0.1.1" id="the-painful-building">The painful building</h3>
<p>The easiest way to switch to server-side equation rendering is just to use <a href="https://github.com/kramdown/math-katex" target="_blank" rel="external">kramdown-math-katex</a>. Install the gem, add an option <code>math_engine: katex</code> into the Kramdown configurations of <code>_config.yml</code>, add the needed CSS to the theme, and… What is my computer doing? It is just stuck at building the site!</p>
<p>By adding the <code>--verbose</code> option to the <code>jekyll serve</code> command, I can see what it was doing. I can see that it is never stuck on any step, but rendering each article that has equations (especially those with a ton of ones) takes seconds. Because I have dozens of articles with equations, it takes minutes to build the site. It seems that although KaTeX has always been advertising itself as the fastest math typesetting library for the web, it is not fast enough for me to use it to render equations server-side.</p>
<p>A way to mitigate this issue is to use the <code>--incremental</code> option of <code>jekyll serve</code>. This makes the building much faster except the first time. I can also expect Jekyll to support <a href="https://github.com/jekyll/jekyll/issues/9434" target="_blank" rel="external">lazy building</a> in the future, which will entirely skip the building phase and build the files as needed on the fly.</p>
<p>I found another way to partially mitigate this issue. On my blog, I have been extensively utilizing the <code>markdownify</code> filter to render Markdown inside the templates, including the title of the posts, the excerpt of the posts, and something else. Those are rendered in multiple places, including the homepage, the archive page, the Atom feed, and the search page. Since now rendering Markdown is being very slow, I decided to cache the rendered Markdowns. A very simple strategy is as follows:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">def</span> <span class="nf">markdownify</span> <span class="n">input</span>
</span>
            <span class="line line-2">	<span class="no">UlyssesZhan</span><span class="p">.</span><span class="nf">markdown_snippet_cache</span><span class="p">[</span><span class="n">input</span><span class="p">]</span> <span class="o">||=</span> <span class="no">Filters</span><span class="p">.</span><span class="nf">instance_method</span><span class="p">(</span><span class="ss">:markdownify</span><span class="p">).</span><span class="nf">bind_call</span> <span class="nb">self</span><span class="p">,</span> <span class="n">input</span>
</span>
            <span class="line line-3"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>Also, for most of the time I actually do not need to see the Markdown styling in the titles and excerpts, so I can also disable the <code>markdownify</code> filter depending on the site configuration, like this:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="k">def</span> <span class="nf">markdownify</span> <span class="n">input</span>
</span>
            <span class="line line-2">	<span class="k">return</span> <span class="n">input</span> <span class="k">if</span> <span class="vi">@context</span><span class="p">.</span><span class="nf">registers</span><span class="p">[</span><span class="ss">:site</span><span class="p">].</span><span class="nf">config</span><span class="p">[</span><span class="s1">'avoid_markdown'</span><span class="p">]</span>
</span>
            <span class="line line-3">	<span class="no">UlyssesZhan</span><span class="p">.</span><span class="nf">markdown_snippet_cache</span><span class="p">[</span><span class="n">input</span><span class="p">]</span> <span class="o">||=</span> <span class="no">Filters</span><span class="p">.</span><span class="nf">instance_method</span><span class="p">(</span><span class="ss">:markdownify</span><span class="p">).</span><span class="nf">bind_call</span> <span class="nb">self</span><span class="p">,</span> <span class="n">input</span>
</span>
            <span class="line line-4"><span class="k">end</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>If I do not want to modify the site configuration file, I can also utilize an environment variable. I can use a <a href="https://jekyllrb.com/docs/plugins/hooks/#built-in-hook-owners-and-events" target="_blank" rel="external">after-init hook</a> to set the configuration item based on the environment variable.</p>
<p>Rendering archives has also been very slow even with this Markdown disabling trick (for some reason I do not know). I decide to use another environment variable to disable the rendering of archives. Change the line <code>gem 'jekyll-archives'</code> in Gemfile to this:</p>
<table class="rouge-table">
  <tbody>
    <tr>
      <td class="highlight language-ruby">
        <pre>
          <code>
            <span class="line line-1"><span class="n">gem</span> <span class="s1">'jekyll-archives'</span><span class="p">,</span> <span class="ss">install_if: </span><span class="o">!</span><span class="no">ENV</span><span class="p">[</span><span class="s1">'JEKYLL_NO_ARCHIVE'</span><span class="p">]</span>
</span>
          </code>
        </pre>
      </td>
    </tr>
  </tbody>
</table>
<p>By using <code>--incremental</code> and these two tricks together, I can finally build the site in seconds if I only modify one post during <code>jekyll serve</code>.</p>
<h3 data-label="0.1.2" id="cross-referencing">Cross-referencing</h3>
<p>It seems that I cannot cross-reference equations using server-side means. First, <a href="https://github.com/KaTeX/KaTeX/issues/2003" target="_blank" rel="external">KaTeX does not support cross-referencing</a>, and the current workarounds are not acceptable for my use cases.</p>
<p>I then looked at <a href="https://github.com/kramdown/math-mathjaxnode" target="_blank" rel="external">kramdown-math-mathjaxnode</a>, which uses the MathJax Node library to render equations server-side. The MathJax Node library itself does support rendering equation numbers, but kramdown-math-mathjaxnode does not support cross-referencing either. What is worse is that it has not been maintained for years, which means I probably had to rewrite the plugin myself, but I did not have spare time.</p>
<p>Even worse, Kramdown is just not suitable for implementing cross-referencing. I briefly looked at Kramdown’s source codes, and I realized that if I was about to write a math engine for Kramdown to support cross-reference, I would have to refactor Kramdown a bit. Actually, cross-referencing is quite a non-trivial feature for markup languages because of references that cannot be resolved during the first compilation. In <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext>LaTeX</mtext></mrow><annotation encoding="application/x-tex">\LaTeX</annotation></semantics></math></span></span>, those references are resolved in the second compilation. I would need to refactor Kramdown to support a similar workflow to make it possible to implement cross-referencing.</p>
<p>Then, I looked at other Markdown engines. For Ruby, the only successful Markdown engine besides Kramdown that I know was <a href="https://github.com/vmg/redcarpet" target="_blank" rel="external">Redcarpet</a> (it used to be the default Markdown engine of Jekyll), and it was not designed with cross-referencing in mind either. Its developer even <a href="https://github.com/vmg/redcarpet/issues/313#issuecomment-35110367" target="_blank" rel="external">rejected to support math-related features</a> a long time ago.</p>
<p>This is why I looked at non-Ruby Markdown engines. The first option that I came up with and also the option that I finally chose is <a href="https://pandoc.org" target="_blank" rel="external">Pandoc</a>.</p>
<p>Pandoc is power in that its form of customization is <em>filters</em>, which transforms the whole parsed AST of the document. Because the whole AST is visible at once for a filter, it is then possible to implement cross-referencing by using a filter. Fortunately, someone has already written such a filter, and it is called <a href="https://github.com/lierdakil/pandoc-crossref" target="_blank" rel="external">pandoc-crossref</a>. What is good about this approach is that it is independent of the math engine that I use: I can use MathJax or KaTeX, client-side or server-side, and it does not matter. The only drawback about it is that it does not support cross-reference a particular line in <code>align</code> or <code>eqnarray</code> environment, which is a feature that I have used in some of my posts. I have to reword those posts to avoid using that feature.</p>
<p>Now that we have a filter, we then need a way to let Pandoc render the math expressions server-side. Fortunately (again), someone has already written a filter for this purpose, and it is called <a href="https://github.com/xu-cheng/pandoc-katex" target="_blank" rel="external">pandoc-katex</a>. Append this filter after the pandoc-crossref filter, and we are done.</p>
<p>The drawback about Pandoc is that it has no Ruby implementations, which means the only way to utilize Pandoc in Jekyll is to write a wrapper of it in Ruby and develop a Jekyll plugin for using that wrapper of Pandoc as the Markdown engine. Fortunately, someone has already done this: the wrapper is called <a href="https://github.com/xwmx/pandoc-ruby" target="_blank" rel="external">pandoc-ruby</a>, and the Jekyll plugin is called <a href="https://github.com/mfenner/jekyll-pandoc" target="_blank" rel="external">jekyll-pandoc</a>.</p>
<p>Although the math rendering problem is solved, a somewhat unrelated problem arises: Pandoc does not use <a href="https://github.com/rouge-ruby/rouge" target="_blank" rel="external">Rouge</a> to highlight code blocks, but I like Rouge. Unfortunately, no one has written a Pandoc filter to use Rouge to highlight code blocks for me; but fortunately, I can write one myself quickly because it is easy enough, especially if I utilize <a href="https://github.com/htdebeer/paru" target="_blank" rel="external">Paru</a>, which contains an API library to help me with writing Pandoc filters in Ruby.</p>
<p>Paru is actually an alternative to pandoc-ruby. Now that I also use Paru, I started to wonder if I should use pandoc-ruby at all. Considering that jekyll-pandoc has not been maintained for years, I decided to write my own Jekyll plugin to use Paru as the Markdown engine, and the simple plugin is called <a href="https://github.com/UlyssesZh/jekyll-paru" target="_blank" rel="external">jekyll-paru</a>.</p>
<h3 data-label="0.1.3" id="tedious-work-of-reformatting-the-old-posts">Tedious work of reformatting the old posts</h3>
<p>Using kramdown-math-katex is the only option that I do not need to adjust most of my posts. Another option, <a href="https://github.com/linjer/jekyll-katex/" target="_blank" rel="external">jekyll-katex</a>, is not compatible with the markup that I use to write equations. I could not either just wrap the whole <code>{{ content }}</code> inside the <code>{% katexmm %}</code> block (due to some errors that I do not know), and the error messages then were impossible to utilize to help me locate the incompatibilities.</p>
<p>For the option that I finally use, Pandoc, I also have to adjust most of my posts. The major incompatibility is that I need to change all <code>\label</code> and <code>\ref</code> to the format recognizable by pandoc-crossref. Another incompatibility is that I need to use <code>{target=_blank}</code> instead of <code>{:target="_blank"}</code> to indicate a link to be opened in a new tab (as well as other HTML attributes that I use this syntax to embed in Markdown). Also, Pandoc does not allow blank lines inside math display blocks, which I have used in some of my posts (by the way, <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext>LaTeX</mtext></mrow><annotation encoding="application/x-tex">\LaTeX</annotation></semantics></math></span></span> does not allow those blank lines either, which is pretty annoying).</p>
<p>I then wrote a simple script that use regular expressions to help me with this refactoring task. However, because of the diversity of the syntaxes that I used, I still need to check the posts manually after I ran the script. This makes the refactoring task still very tedious.</p>
<h3 data-label="0.1.4" id="the-much-more-complicated-github-actions-workflow">The much more complicated GitHub Actions workflow</h3>
<p>Now, to build my site, the machine needs pandoc, pandoc-crossref, and pandoc-katex, none of which are Ruby Gems. I need to set up Haskell environment and Rust environment to install them. In GitHub Actions, I can use <a href="https://github.com/haskell-actions/setup" target="_blank" rel="external">haskell-actions/setup</a> to set up Haskell environment and <a href="https://github.com/baptiste0928/cargo-install" target="_blank" rel="external">cargo-install</a> to install Cargo packages.</p>
<p>I do not know how I managed to make the GitHub Actions workflow file work expectedly at one shot, but I did.</p>
<h3 data-label="0.1.5" id="table-of-contents-and-searching">Table of contents and searching</h3>
<p>I have been using <a href="https://github.com/toshimaru/jekyll-toc" target="_blank" rel="external">jekyll-toc</a> to generate the table of contents for each post. The problem with using it now is that it strips the HTML in headings and only keeps the text, so headings with math expressions will not be rendered with nice math typesetting. It was not a problem previously because the client-side math rendering script will render the math expressions in the table of contents. Now that I switched to server-side math rendering, I had to patch jekyll-toc to make it work.</p>
<p>The search functionality was implemented by myself. It is a simple client-side searching powered by <a href="https://lunrjs.com" target="_blank" rel="external">Lunr</a>. I also had to refactor the search functionality a bit to make the search results be rendered with math expressions (which were previously also handled by the client-side math rendering script).</p>
<h2 data-label="0.2" id="updating-the-theme">Updating the theme</h2>
<p>The reason that I updated the theme is actually quite dramatic. This originated from me trying to use kramdown-math-katex. To ensure that the KaTeX CSS has the correct version with the KaTeX renderer used by katex-ruby, I decided to <code>@import</code> the <a href="https://github.com/glebm/katex-ruby/blob/main/vendor/katex/sprockets/stylesheets/_katex.scss" target="_blank" rel="external">SCSS file</a> found in the repo of katex-ruby into my theme. I found that the SCSS file utilizes a function <code>asset-path</code> to load the fonts, but my CSS pre-processor does not support it, so I tried to extend my CSS pre-processor.</p>
<p>Jekyll uses <a href="https://github.com/jekyll/jekyll-sass-converter" target="_blank" rel="external">jekyll-sass-converter</a> to render CSS files, which once (v2) used <a href="https://github.com/sass/sassc-ruby" target="_blank" rel="external">sassc</a>, but now (v3) uses <a href="https://github.com/ntkme/sass-embedded-host-ruby" target="_blank" rel="external">sass-embedded</a>. The former does not support extension of custom SCSS functions, but the latter does. Therefore, I need to upgrade my jekyll-sass-converter to v3. I actually could have upgraded it earlier because I have been using Jekyll v4 for a long time, but I deliberately kept using jekyll-sass-converter v2 because <a href="https://github.com/helaili/jekyll-action" target="_blank" rel="external">jekyll-action</a>, which I used, had <a href="https://github.com/helaili/jekyll-action/issues/150" target="_blank" rel="external">an issue about using sass-embedded</a>. However, I have long ago migrated from jekyll-action to GitHub’s official <a href="https://github.com/actions/upload-pages-artifact" target="_blank" rel="external">upload-pages-artifact</a>, so I can now upgrade jekyll-sass-converter to v3.</p>
<p>Then why does this have anything to do with the theme I used (which is <a href="https://github.com/jekyll/minima" target="_blank" rel="external">Minima</a>)? After I upgraded jekyll-sass-converter to v3, I found that there are some <a href="https://github.com/jekyll/minima/issues/709" target="_blank" rel="external">deprecation warnings in the SCSS files</a> (they are actually already fixed, but I do not know why the issue is still open). This was also when I noticed that Minima has not released a new version <strong>for 4 years</strong>, and the last stable release is v2.5.1.</p>
<p>Then, how did I upgrade to Minima v3? I actually just tried to use the master branch of the Git repo of Minima, and I found that it was great.</p>
<h3 data-label="0.2.1" id="placeholder-files-for-customization">Placeholder files for customization</h3>
<p>I am glad to see Minima v3 introduced the include <code>custom-head.html</code> which allows for custom additional HTML metadata and the SCSS file <code>minima/custom-variables.scss</code> and <code>minima/custom-styles.scss</code> which allows for custom SCSS rules to override the default ones.</p>
<p>Although it took me some time to migrate my already present SCSS files and HTML metadata to the new structure, I am glad that Minima adopted this new structure that is more useful and more modern.</p>
<h3 data-label="0.2.2" id="skins">Skins</h3>
<p>Another feature that I really like about Minima v3 is the support of skins. Minima now comes with several pre-defined skins which I can choose from. The default skin called <code>classic</code> is the one that originated from Minima v2, based on which I wrote my own skin.</p>
<p>I still remember a long time ago I tried to make my site support dark theme. It was such a pain because there are so many colors hardcoded in the theme so that I have to rewrite a large part of the SCSS files provided by Minima to support dark theme. Now, Minima v3 has a pre-defined skin called <code>auto</code>, which adaptively looks the same as <code>classic</code> or <code>dark</code> based on the browser’s <code>prefers-color-scheme</code>. I can now implement my skin based on <code>auto</code> (select my skin in the site’s configuration file and <code>@import</code> the <code>auto</code> skin in my skin’s SCSS file), and the codes are now much cleaner.</p>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="update" /><category term="jekyll" /><category term="tex" /><category term="update" /><category term="web" /><summary type="html"><![CDATA[If you have not noticed, the equations on my blog are now rendered server-side. This change makes it possible for those who turn off JavaScript on their browsers to see the equations. I also updated the theme from Minima v2 to Minima v3.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2023-11-06-restructure.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2023-11-06-restructure.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[I created Sunniesnow, a rhythm game similar to Lyrica]]></title><link href="https://ulysseszh.github.io/update/2023/09/08/sunniesnow.html" rel="alternate" type="text/html" title="I created Sunniesnow, a rhythm game similar to Lyrica" /><published>2023-09-08T21:38:26-07:00</published><updated>2023-09-08T21:38:26-07:00</updated><id>https://ulysseszh.github.io/update/2023/09/08/sunniesnow</id><content type="html" xml:base="https://ulysseszh.github.io/update/2023/09/08/sunniesnow.html"><![CDATA[<p>Lyrica is one of my favorite mobile rhythm games. However, because of the lack of popularity, the player community is not very active. In order to build a better player community for Lyrica, I did the following things:</p>
<ul>
<li>I created a <a href="https://lyrica.fandom.com/zh-tw/wiki/" target="_blank" rel="external">Fandom Wiki for Lyrica</a>.</li>
<li>I created a <a href="https://reddit.com/r/lyricagame/" target="_blank" rel="external">subreddit for Lyrica</a>.</li>
<li>I created an <a href="https://discord.gg/6ZHRU9teju" target="_blank" rel="external">unofficial Discord server for Lyrica</a>.</li>
</ul>
<p>Besides these, most importantly, in order to build a custom charting community for Lyrica, I created a new rhythm game called <a href="https://sunniesnow.github.io" target="_blank" rel="external">Sunniesnow</a>. It is a rhythm game similar to Lyrica. Any people can write their own charts for Sunniesnow, serving as fanmade charts for Lyrica. Learn more about Sunniesnow by <a href="https://discord.gg/6ZHRU9teju" target="_blank" rel="external">joining our Discord server</a> (this is also the unofficial Discord server for Lyrica I created).</p>
<div class="embed-container">
<iframe id="discord-embed-1131429935303626782" src="https://discord.com/widget?id=1131429935303626782" allowtransparency="true" sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts">
</iframe>
</div>
<script><![CDATA[
(() => {
	const element = document.getElementById('discord-embed-1131429935303626782');
	element.src += '&theme=' + (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
	element.parentNode.style.paddingBottom = '400px';
	element.style.maxWidth = '600px';
})();
]]]]><![CDATA[></script>
<p>I have already written a few charts. Here are videos:</p>
<div class="embed-container">
<iframe src="https://www.youtube.com/embed/xqrqxprl71o" frameborder="0" allowfullscreen="">
</iframe>
</div>
<div class="embed-container">
<iframe src="https://www.youtube.com/embed/oiMivgDPJBg" frameborder="0" allowfullscreen="">
</iframe>
</div>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="update" /><category term="update" /><category term="rhythm game" /><category term="web" /><summary type="html"><![CDATA[In order to build a better player community for the rhythm game Lyrica, I created a new rhythm game called <a href="https://sunniesnow.github.io" target="_blank" rel="external">Sunniesnow</a>. Learn more about Sunniesnow by <a href="https://discord.gg/6ZHRU9teju" target="_blank" rel="external">joining our Discord server</a>.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2023-09-08-sunniesnow.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2023-09-08-sunniesnow.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[I created a community rhythm game called Dododo]]></title><link href="https://ulysseszh.github.io/update/2022/05/23/dododo-discord.html" rel="alternate" type="text/html" title="I created a community rhythm game called Dododo" /><published>2022-05-23T01:49:27-07:00</published><updated>2022-05-23T01:49:27-07:00</updated><id>https://ulysseszh.github.io/update/2022/05/23/dododo-discord</id><content type="html" xml:base="https://ulysseszh.github.io/update/2022/05/23/dododo-discord.html"><![CDATA[<p>I have created a <a href="https://dododogame.github.io" target="_blank" rel="external">community rhythm game called Dododo</a>. It is a rhythm game with musical rhythm notations.</p>
<p>It is an open-source project, whose source codes can be seen in the <a href="https://github.com/dododogame/dododo" target="_blank" rel="external">GitHub repo</a>.</p>
<p>It is not mature currently. To help Dododo become mature, I wish you could join our community by <a href="https://discord.gg/yYdMw5hm2K" target="_blank" rel="external">joining our Discord server</a>:</p>
<div class="embed-container">
<iframe id="discord-embed-977458815794552842" src="https://discord.com/widget?id=977458815794552842" allowtransparency="true" sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts">
</iframe>
</div>
<script><![CDATA[
(() => {
	const element = document.getElementById('discord-embed-977458815794552842');
	element.src += '&theme=' + (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
	element.parentNode.style.paddingBottom = '400px';
	element.style.maxWidth = '600px';
})();
]]]]><![CDATA[></script>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="update" /><category term="update" /><category term="rhythm game" /><category term="web" /><summary type="html"><![CDATA[I have created a <a href="https://dododogame.github.io" target="_blank" rel="external">community rhythm game called Dododo</a>. It is a rhythm game with musical rhythm notations.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2022-05-23-dododo-discord.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2022-05-23-dododo-discord.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html"><![CDATA[Simulating a mechanical system using rpg_core.js]]></title><link href="https://ulysseszh.github.io/physics/2020/05/14/simulation-rpgmv.html" rel="alternate" type="text/html" title="Simulating a mechanical system using rpg_core.js" /><published>2020-05-13T09:57:39-07:00</published><updated>2020-05-13T09:57:39-07:00</updated><id>https://ulysseszh.github.io/physics/2020/05/14/simulation-rpgmv</id><content type="html" xml:base="https://ulysseszh.github.io/physics/2020/05/14/simulation-rpgmv.html"><![CDATA[<p>This post is the continuation of <a href="/physics/2020/04/28/simulation-rgss.html">the last post</a>.</p>
<p>If you visit <a href="/rpg/mechsimul/">the page</a> I have just created, you may find the simulation of a mechanical system.</p>
<figure>
<img src="/assets/images/figures/2020-05-14-simulation-rpgmv/rpgmv_simul.png" alt="Result of simulation"/>

</figure>
<p>It is currently <span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi mathvariant="script">H</mi><mo>=</mo><msubsup><mi>p</mi><mn>1</mn><mn>2</mn></msubsup><mo>+</mo><msubsup><mi>p</mi><mn>2</mn><mn>2</mn></msubsup><mo>−</mo><mi>cos</mi><mo>⁡</mo><msub><mi>q</mi><mn>1</mn></msub><mo>−</mo><mi>cos</mi><mo>⁡</mo><msub><mi>q</mi><mn>2</mn></msub><mo>−</mo><mi>cos</mi><mo>⁡</mo><mtext> ⁣</mtext><mrow><mo fence="true">(</mo><msub><mi>q</mi><mn>1</mn></msub><mo>−</mo><msub><mi>q</mi><mn>2</mn></msub><mo fence="true">)</mo></mrow></mrow><annotation encoding="application/x-tex">
    \mathcal H=p_1^2+p_2^2-\cos q_1-\cos q_2-
    \cos\!\left(q_1-q_2\right)
</annotation></semantics></math></span></span></span> depicting two pendulum coupled with a spring (with <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>l</mi><mn>1</mn></msub><mo>=</mo><msub><mi>l</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">l_1=l_2</annotation></semantics></math></span></span> and <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>m</mi><mn>1</mn></msub><mo>=</mo><msub><mi>m</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">m_1=m_2</annotation></semantics></math></span></span>, and the original length of the spring is zero, and the two hanging points overlap),</p>
<figure>
<img src="/assets/images/figures/2020-05-14-simulation-rpgmv/spring_coupled_pendulum.png" class="dark-adaptive" alt="Spring-coupled pendulums"/>

</figure>
<p class="no-indent">
which is a classical example of non-linearly coupled system.
</p>
<p>The pattern of the oscillation can be analyzed using discrete Fourier transformation, whose result can be found by clicking the buttons in the up-left corner (after the simulator has detected a period).</p>
<figure>
<img src="/assets/images/figures/2020-05-14-simulation-rpgmv/rpgmv_simul_fft.png" alt="Result of DFT"/>

</figure>
<p class="no-indent">
Hitting the space bar can make the simulation pause.
</p>
<p>If you want to use it to simulate other mechanical systems, you can study <a href="/rpg/mechsimul/js/mechsimul.js">the codes</a> I wrote and write your own codes in the console.</p>
<p>By the way, the <a href="https://github.com/UlyssesZh/OpenRGSS/" target="_blank" rel="external">OpenRGSS</a> version of the simulator is open-source <a href="https://github.com/UlyssesZh/mechsimul/" target="_blank" rel="external">here</a>. Please star the repo if you like it.</p>]]></content><author><name>UlyssesZhan</name><email>ulysseszhan@gmail.com</email></author><category term="physics" /><category term="javascript" /><category term="rgss" /><category term="hamiltonian" /><category term="calculus" /><category term="ode" /><category term="web" /><category term="fourier transform" /><summary type="html"><![CDATA[Continuing my last work of simulating a mechanical system using RGSS3, I made a new version using rpg_core.js, the game scripting system shipped with RPG Maker MV. This version is live <a href="/rpg/mechsimul">on web</a>!]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://ulysseszh.github.io/assets/images/covers/2020-05-14-simulation-rpgmv.png" /><media:content medium="image" url="https://ulysseszh.github.io/assets/images/covers/2020-05-14-simulation-rpgmv.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>