<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Today I Learned Blog</title>
        <link>https://til.trashposts.com/blog</link>
        <description>Today I Learned Blog</description>
        <lastBuildDate>Tue, 02 Jun 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh-Hant</language>
        <item>
            <title><![CDATA[用 FFmpeg 把 MP4 轉成 WebP 動圖]]></title>
            <link>https://til.trashposts.com/blog/ffmpeg-mp4-to-webp</link>
            <guid>https://til.trashposts.com/blog/ffmpeg-mp4-to-webp</guid>
            <pubDate>Tue, 02 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[今天在寫部落格時，順手學會了怎麼把 MP4 片段轉成 WebP 動圖。]]></description>
            <content:encoded><![CDATA[<p>今天在寫部落格時，順手學會了怎麼把 MP4 片段轉成 WebP 動圖。</p>
<p>這個用途很適合拿來做文章裡的小動畫，比直接塞影片更輕巧。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="筆記">筆記<a href="https://til.trashposts.com/blog/ffmpeg-mp4-to-webp#%E7%AD%86%E8%A8%98" class="hash-link" aria-label="筆記的直接連結" title="筆記的直接連結" translate="no">​</a></h3>
<ul>
<li class=""><a class="" href="https://til.trashposts.com/notes/media/ffmpeg-mp4-to-webp">MP4 轉 WebP 動圖</a></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="參考資料">參考資料<a href="https://til.trashposts.com/blog/ffmpeg-mp4-to-webp#%E5%8F%83%E8%80%83%E8%B3%87%E6%96%99" class="hash-link" aria-label="參考資料的直接連結" title="參考資料的直接連結" translate="no">​</a></h3>
<ul>
<li class=""><a href="https://wiwi.blog/blog/animated-webp/" target="_blank" rel="noopener noreferrer" class="">動畫圖的正解是 WebP</a></li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[批次下載 YouTube 縮圖並調整尺寸]]></title>
            <link>https://til.trashposts.com/blog/youtube-thumbnails-batch</link>
            <guid>https://til.trashposts.com/blog/youtube-thumbnails-batch</guid>
            <pubDate>Tue, 26 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="前言">前言<a href="https://til.trashposts.com/blog/youtube-thumbnails-batch#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="前言的直接連結" title="前言的直接連結" translate="no">​</a></h3>
<p>今天在更新網站上「Tiny Desk Concerts」的欄位，突然想到沒有把下載步驟記下來，在這邊補一下。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="第一步用-yt-dlp-抓整個播放清單的縮圖">第一步：用 yt-dlp 抓整個播放清單的縮圖<a href="https://til.trashposts.com/blog/youtube-thumbnails-batch#%E7%AC%AC%E4%B8%80%E6%AD%A5%E7%94%A8-yt-dlp-%E6%8A%93%E6%95%B4%E5%80%8B%E6%92%AD%E6%94%BE%E6%B8%85%E5%96%AE%E7%9A%84%E7%B8%AE%E5%9C%96" class="hash-link" aria-label="第一步：用 yt-dlp 抓整個播放清單的縮圖的直接連結" title="第一步：用 yt-dlp 抓整個播放清單的縮圖的直接連結" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">yt-dlp ^</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--skip-download ^</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--write-thumbnail ^</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--convert-thumbnails jpg ^</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">-o "%(title)s.%(ext)s" ^</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">"{播放清單／影片網址}"</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="第二步用-imagemagick-統一縮放">第二步：用 ImageMagick 統一縮放<a href="https://til.trashposts.com/blog/youtube-thumbnails-batch#%E7%AC%AC%E4%BA%8C%E6%AD%A5%E7%94%A8-imagemagick-%E7%B5%B1%E4%B8%80%E7%B8%AE%E6%94%BE" class="hash-link" aria-label="第二步：用 ImageMagick 統一縮放的直接連結" title="第二步：用 ImageMagick 統一縮放的直接連結" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">magick mogrify -resize 480x270! *.jpg</span><br></span></code></pre></div></div>
<p><code>mogrify</code> 會直接覆寫原檔，省下另開資料夾的功夫。</p>
<p>尺寸後面的 <code>!</code> 代表忽略原始長寬比，強制拉伸到指定尺寸。</p>
<p>沒加的話，ImageMagick 會把 480x270 當成最大邊界框，在框內保持原始比例縮放。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="筆記">筆記<a href="https://til.trashposts.com/blog/youtube-thumbnails-batch#%E7%AD%86%E8%A8%98" class="hash-link" aria-label="筆記的直接連結" title="筆記的直接連結" translate="no">​</a></h3>
<ul>
<li class=""><a class="" href="https://til.trashposts.com/notes/terminal/yt-dlp">YT-DLP 指令筆記</a></li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[大小寫問題讓網站連結失效]]></title>
            <link>https://til.trashposts.com/blog/case-issue-broke-site-links</link>
            <guid>https://til.trashposts.com/blog/case-issue-broke-site-links</guid>
            <pubDate>Thu, 07 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[發現問題]]></description>
            <content:encoded><![CDATA[<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="發現問題">發現問題<a href="https://til.trashposts.com/blog/case-issue-broke-site-links#%E7%99%BC%E7%8F%BE%E5%95%8F%E9%A1%8C" class="hash-link" aria-label="發現問題的直接連結" title="發現問題的直接連結" translate="no">​</a></h3>
<p>今天偶然發現之前寫的<a href="https://trashposts.com/blog/toeic-resources-2026/" target="_blank" rel="noopener noreferrer" class="">多益資源整理</a>，這篇文章連結點下去會直接跳回首頁。</p>
<p>奇怪，網址明明還停在 <code>/blog/toeic-resources-2026/</code>，內容卻是首頁。</p>
<p>但我在本地跑沒有問題啊！？</p>
<p>想說是不是 Cloudflare Pages 的問題，但往回前翻好幾版都有這個問題。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="找出問題">找出問題<a href="https://til.trashposts.com/blog/case-issue-broke-site-links#%E6%89%BE%E5%87%BA%E5%95%8F%E9%A1%8C" class="hash-link" aria-label="找出問題的直接連結" title="找出問題的直接連結" translate="no">​</a></h3>
<p>我先去看了 sitemap、RSS、文章列表頁，所有指向這篇的連結都是小寫 <code>/toeic-resources-2026/</code>，沒有問題。</p>
<p>也跑去看了 <code>public/blog/</code> 底下的資料夾，確實有 <code>toeic-resources-2026/index.html</code>，檔案在啊。</p>
<p>那為什麼 Cloudflare 找不到？</p>
<p>我請 AI 幫我比對 git 跟磁碟上的檔名，這時候真相浮出水面：</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">GIT:  public/blog/TOEIC-resources-2026/index.html</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">DISK: public/blog/toeic-resources-2026/index.html</span><br></span></code></pre></div></div>
<p><strong>兩邊的大小寫不一樣。</strong></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="為什麼">為什麼<a href="https://til.trashposts.com/blog/case-issue-broke-site-links#%E7%82%BA%E4%BB%80%E9%BA%BC" class="hash-link" aria-label="為什麼的直接連結" title="為什麼的直接連結" translate="no">​</a></h3>
<p>雖然我想不起來了，不過最有可能的情況應該是，我手動把資料夾從大寫的 <code>TOEIC-resources-2026</code> 改成小寫的 <code>toeic-resources-2026</code>，因為其他文章 slug 都是小寫，看起來比較一致。</p>
<p>當時改完，本機看一切正常，就 commit、push 上去了，根本沒注意到 git 其實沒抓到這次改名。</p>
<p>事後才知道，這是三個東西交織的結果：</p>
<ul>
<li class=""><strong>Windows</strong> 檔案系統大小寫不敏感，<code>Foo</code> 跟 <code>foo</code> 是同一個資料夾。</li>
<li class=""><strong>Git on Windows</strong> 預設 <code>core.ignorecase=true</code>，會配合 Windows 的行為，這次的重新命名根本沒被當成一次 diff。</li>
<li class=""><strong>Cloudflare Pages</strong> 跑在 Linux 上，大小寫嚴格區分，<code>/toeic-resources-2026/</code> 跟 <code>/TOEIC-resources-2026/</code> 對它來說是兩個完全不同的網址。</li>
</ul>
<p>於是，本機看起來沒事，repo 裡其實還是大寫，部署上去就只認大寫，小寫的 URL 全部 404。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="解決問題">解決問題<a href="https://til.trashposts.com/blog/case-issue-broke-site-links#%E8%A7%A3%E6%B1%BA%E5%95%8F%E9%A1%8C" class="hash-link" aria-label="解決問題的直接連結" title="解決問題的直接連結" translate="no">​</a></h3>
<p>要讓 git「真的」承認這次改名，得從索引裡先把舊的拿掉，再加回新的：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">git rm -r --cached public/blog/TOEIC-resources-2026</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">git add public/blog/toeic-resources-2026</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">git commit -m "Fix case: TOEIC-resources-2026 → toeic-resources-2026"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">git push</span><br></span></code></pre></div></div>
<p><code>--cached</code> 只動 git 索引，不會碰到磁碟上的實體檔案。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="未來怎麼防範">未來怎麼防範<a href="https://til.trashposts.com/blog/case-issue-broke-site-links#%E6%9C%AA%E4%BE%86%E6%80%8E%E9%BA%BC%E9%98%B2%E7%AF%84" class="hash-link" aria-label="未來怎麼防範的直接連結" title="未來怎麼防範的直接連結" translate="no">​</a></h3>
<p>可以考慮把 git 設成大小寫敏感：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">git config core.ignorecase false</span><br></span></code></pre></div></div>
<p>之後任何資料夾或檔名只要改了大小寫，<code>git status</code> 就會老老實實顯示「舊名稱被刪除 + 新名稱新增」，不會再無聲無息地漏掉。</p>
<p>再順手跑了一下 <code>git status</code> 全域掃描，確認其他歷史檔案沒有同樣的漏網之魚。</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[中島美雪《時代》]]></title>
            <link>https://til.trashposts.com/blog/jidai-miyuki-nakajima</link>
            <guid>https://til.trashposts.com/blog/jidai-miyuki-nakajima</guid>
            <pubDate>Tue, 28 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[《時代》]]></description>
            <content:encoded><![CDATA[<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="時代">《時代》<a href="https://til.trashposts.com/blog/jidai-miyuki-nakajima#%E6%99%82%E4%BB%A3" class="hash-link" aria-label="《時代》的直接連結" title="《時代》的直接連結" translate="no">​</a></h3>
<p>中島美雪的代表作《<a href="https://zh.wikipedia.org/wiki/%E6%97%B6%E4%BB%A3_(%E6%AD%8C%E6%9B%B2)" target="_blank" rel="noopener noreferrer" class="">時代</a>》，是在 1975 年那一年，她連續闖過兩個比賽的一首歌。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1975-年-10-月popcon">1975 年 10 月：Popcon<a href="https://til.trashposts.com/blog/jidai-miyuki-nakajima#1975-%E5%B9%B4-10-%E6%9C%88popcon" class="hash-link" aria-label="1975 年 10 月：Popcon的直接連結" title="1975 年 10 月：Popcon的直接連結" translate="no">​</a></h3>
<p>10 月 12 日，<strong>第 10 屆 Popcon</strong>（ポピュラーソングコンテスト）在靜岡縣つま恋舉辦。</p>
<p>那一屆收到了 <strong>12,000 首</strong> 應募曲，中島美雪的〈時代〉拿下了最高獎 <strong>グランプリ</strong>。也因為這個獎，她得到了代表日本參加 11 月世界歌謠祭的資格。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1975-年-11-月世界歌謠祭">1975 年 11 月：世界歌謠祭<a href="https://til.trashposts.com/blog/jidai-miyuki-nakajima#1975-%E5%B9%B4-11-%E6%9C%88%E4%B8%96%E7%95%8C%E6%AD%8C%E8%AC%A0%E7%A5%AD" class="hash-link" aria-label="1975 年 11 月：世界歌謠祭的直接連結" title="1975 年 11 月：世界歌謠祭的直接連結" translate="no">​</a></h3>
<p>11 月 16 日，「<a href="https://www.yamaha-mf.or.jp/history/e-history/wpsf/wpsf6.html" target="_blank" rel="noopener noreferrer" class="">第 6 屆世界歌謠祭</a>」在日本武道館舉辦。〈時代〉再次拿下了最大獎 Grand Prix（グランプリ）。</p>
<p>那一屆的主持人，是日本傳奇歌手<strong>坂本九</strong>，以及當時已經紅遍亞洲的<strong>翁倩玉</strong>。</p>
<p>下面這段珍貴的影片中，<strong>約 1 分 56 秒處</strong>，收錄了當年在世界歌謠祭的影像，你可以清楚地聽到坂本九與翁倩玉主持的聲音。</p>
<div style="position:relative;width:100%;max-width:560px;aspect-ratio:560 / 315"><iframe style="position:absolute;top:0;left:0;width:100%;height:100%" src="https://www.youtube.com/embed/cyciV0nPVO0?si=bqkaUiay6parCZi4&amp;start=116" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin"></iframe></div>
<br>
<blockquote>
<p>坂本九：「Entry number 30, 日本, 中島みゆき, "時代".」</p>
<p>翁倩玉：「Entry number 30, Japan, "Time Goes Around".」</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="伴奏的故事">伴奏的故事<a href="https://til.trashposts.com/blog/jidai-miyuki-nakajima#%E4%BC%B4%E5%A5%8F%E7%9A%84%E6%95%85%E4%BA%8B" class="hash-link" aria-label="伴奏的故事的直接連結" title="伴奏的故事的直接連結" translate="no">​</a></h3>
<p>〈時代〉在舞台上原本是有管弦樂團伴奏的版本。但拿下 Grand Prix 之後的 <strong>得獎者加演（安可）</strong>，中島美雪走上台前，對著指揮耳語了幾句。接著，整個樂團安靜下來，她抱著吉他，<strong>只用一把吉他自彈自唱</strong>了一遍〈時代〉。</p>
<p>這個決定來自於她的伯樂、YAMAHA 音樂振興會的理事長 <strong>川上源一</strong> 對她說過的一段話：</p>
<blockquote>
<p>「あなたはすごい詞を書く。将来、詞で勝負するようなアーティストに育って欲しい。できれば大音量をバックにするよりも、ギター一本で歌った方が、あなたの詞が人々に伝わる」</p>
<p>「妳寫的詞非常出色。希望將來你能成長為一位以歌詞實力取勝的藝術家。如果可以的話，與其背負著巨大的音量（伴奏），不如只用一把吉他自彈自唱，你的歌詞反而更能傳達進人們的心裡。」（AI 翻譯）</p>
</blockquote>
<p>從那之後，中島美雪在每一張專輯的工作人員名單裡，都會寫上一行 <strong>「DAD 川上源一」</strong>，以此致敬這位恩人。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="關於父親">關於父親<a href="https://til.trashposts.com/blog/jidai-miyuki-nakajima#%E9%97%9C%E6%96%BC%E7%88%B6%E8%A6%AA" class="hash-link" aria-label="關於父親的直接連結" title="關於父親的直接連結" translate="no">​</a></h3>
<p>中島美雪在出道單曲〈<a href="https://zh.wikipedia.org/wiki/%E8%96%8A%E8%8A%B1%E5%A7%91%E5%A8%98%E7%9A%84%E6%90%96%E7%B1%83%E6%9B%B2" target="_blank" rel="noopener noreferrer" class="">薊花姑娘的搖籃曲</a>〉發行前一週（1975 年 9 月 16 日），父親就因腦溢血倒下、昏迷不醒。</p>
<p>10 月的 Popcon、11 月的世界歌謠祭，她其實都是從父親昏迷的病房趕到會場上台的。父親後來於 1976 年 1 月離世，始終沒能聽到女兒奪冠的消息。</p>
<p>世界歌謠祭頒給她的 5,000 美元獎金，後來拿去當作父親的葬儀費用。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1993-年的彩蛋">1993 年的彩蛋<a href="https://til.trashposts.com/blog/jidai-miyuki-nakajima#1993-%E5%B9%B4%E7%9A%84%E5%BD%A9%E8%9B%8B" class="hash-link" aria-label="1993 年的彩蛋的直接連結" title="1993 年的彩蛋的直接連結" translate="no">​</a></h3>
<p>中島美雪在 1993 年重新錄製了《時代》，歌曲的開頭，她取樣了在世界歌謠祭裡面，主持人<strong>坂本九</strong>與<strong>翁倩玉</strong>的介紹詞，以及歌曲開頭的一小段演唱。</p>
<audio controls=""><source src="/audio/post/jidai-1993.mp3" type="audio/mpeg"><p>您的瀏覽器不支援播放音檔。</p></audio>
<blockquote>
<p><strong>翁倩玉：「Entry number 30, Japan, compose and sung by Miyuki Nakajima, the title of the song: Time Goes Around.」</strong></p>
</blockquote>
<p>（這聲音也太美了吧！！）</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="備註">備註<a href="https://til.trashposts.com/blog/jidai-miyuki-nakajima#%E5%82%99%E8%A8%BB" class="hash-link" aria-label="備註的直接連結" title="備註的直接連結" translate="no">​</a></h3>
<p>我在「<a href="https://trashposts.com/blog/sunlight-bike-ride/" target="_blank" rel="noopener noreferrer" class="">這篇貼文</a>」中提到我前陣子跑去看了《陽光女子合唱團》，才發現其實我以前經常聽到這位國民阿嬤翁倩玉的聲音。</p>
<p>至於坂本九的話，我最喜歡的歌曲是《見上げてごらん夜の星を》。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="參考資料">參考資料<a href="https://til.trashposts.com/blog/jidai-miyuki-nakajima#%E5%8F%83%E8%80%83%E8%B3%87%E6%96%99" class="hash-link" aria-label="參考資料的直接連結" title="參考資料的直接連結" translate="no">​</a></h3>
<ul>
<li class="">ヤマハ音楽振興会：<a href="https://www.yamaha-mf.or.jp/history/e-history/wpsf/wpsf6.html" target="_blank" rel="noopener noreferrer" class="">第 6 回世界歌謠祭 (1975)</a>（主持人、得獎者、會場等基本資料）</li>
<li class="">Tap the POP：<a href="https://www.tapthepop.net/song/53873" target="_blank" rel="noopener noreferrer" class="">中島みゆき「時代」③〜亡くなった父の言葉</a>（父親病倒、昏迷、葬儀費的細節）</li>
<li class="">集英社オンライン：<a href="https://shueisha.online/articles/-/182556" target="_blank" rel="noopener noreferrer" class="">23 歳の中島みゆきがオーケストラ演奏を断り、ギター 1 本で『時代』を歌った理由</a></li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[收集部落格 RSS 網址列表]]></title>
            <link>https://til.trashposts.com/blog/collect-blog-rss-url-list</link>
            <guid>https://til.trashposts.com/blog/collect-blog-rss-url-list</guid>
            <pubDate>Fri, 24 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[最近「部落格問題挑戰」這個問答挑戰突然很多人響應。]]></description>
            <content:encoded><![CDATA[<p>最近「<a href="https://trashposts.com/blog/blog-questions-challenge/" target="_blank" rel="noopener noreferrer" class="">部落格問題挑戰</a>」這個問答挑戰突然很多人響應。</p>
<p>想說可以收集一下大家的答案，就像 <a href="https://blog.avas.space/" target="_blank" rel="noopener noreferrer" class="">Ava</a> 的「<a href="https://blog.avas.space/bear-blog-challenge/" target="_blank" rel="noopener noreferrer" class="">bear blog question challenge</a>」一樣！</p>
<p>這樣的話，我就需要收集一下大家的 RSS Feed 了，在這邊記錄一下做法。</p>
<p><del>雖然都是 AI 在做。</del></p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="目標">目標<a href="https://til.trashposts.com/blog/collect-blog-rss-url-list#%E7%9B%AE%E6%A8%99" class="hash-link" aria-label="目標的直接連結" title="目標的直接連結" translate="no">​</a></h3>
<p>將 <a href="https://blogblog.club/party" target="_blank" rel="noopener noreferrer" class="">BlogBlog 同樂會</a> 頁面上的所有部落格整理成一份可匯入閱讀器的 <strong>OPML 清單</strong>。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-取得部落格網址列表">1. 取得部落格網址列表<a href="https://til.trashposts.com/blog/collect-blog-rss-url-list#1-%E5%8F%96%E5%BE%97%E9%83%A8%E8%90%BD%E6%A0%BC%E7%B6%B2%E5%9D%80%E5%88%97%E8%A1%A8" class="hash-link" aria-label="1. 取得部落格網址列表的直接連結" title="1. 取得部落格網址列表的直接連結" translate="no">​</a></h3>
<ol>
<li class="">在 BlogBlog 同樂會 頁面爬取所有連結。</li>
<li class="">去除重複網址，整理並輸出成 txt 檔案。</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-將網址列表轉成-rss-feed">2. 將網址列表轉成 RSS Feed<a href="https://til.trashposts.com/blog/collect-blog-rss-url-list#2-%E5%B0%87%E7%B6%B2%E5%9D%80%E5%88%97%E8%A1%A8%E8%BD%89%E6%88%90-rss-feed" class="hash-link" aria-label="2. 將網址列表轉成 RSS Feed的直接連結" title="2. 將網址列表轉成 RSS Feed的直接連結" translate="no">​</a></h3>
<ol>
<li class="">先比對既有的 OPML（原本就訂閱過的就不用找了）</li>
<li class="">用平台規則猜 RSS 位置，用 cURL 去試試看，平台型部落格通常都會直接成功。</li>
<li class="">抓首頁 HTML，找 <code>link rel="alternate"</code>，有的話通常就直接是 RSS 網址了。</li>
<li class="">測試常見路徑（<code>/feed</code>、<code>/rss</code>、<code>/index.xml</code>、<code>/atom.xml</code> 等等）</li>
<li class="">輸出成 <code>rss_feeds.csv</code>：每個站的 RSS、來源、狀態</li>
</ol>
<hr>
<p>這時候大概能收集到九成的 RSS Feed 了，剩下的就手動稍微找一下，很快就處理完了！</p>
<p>最後輸出成 <code>url.opml.xml</code>，然後在我的 FreshRSS 閱讀器開一個帳號，把這份清單匯入進去。</p>
<p>之後只要上去搜尋關鍵字「部落格問題挑戰」就可以了！</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[e89295]]></title>
            <link>https://til.trashposts.com/blog/e89295</link>
            <guid>https://til.trashposts.com/blog/e89295</guid>
            <pubDate>Thu, 02 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[TIL，《我的部落格》的網站名稱「e89295」，是用三個十六進位的 UTF-8 位元組來表示的：0xE8、0x92、0x95。]]></description>
            <content:encoded><![CDATA[<p>TIL，《<a href="https://e89295.com/blog/" target="_blank" rel="noopener noreferrer" class="">我的部落格</a>》的網站名稱「e89295」，是用三個十六進位的 UTF-8 位元組來表示的：<code>0xE8</code>、<code>0x92</code>、<code>0x95</code>。</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">TextDecoder</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">decode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Uint8Array</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0xE8</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0x92</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0x95</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[如何用 Telegram 傳送通知給自己]]></title>
            <link>https://til.trashposts.com/blog/telegram-notify</link>
            <guid>https://til.trashposts.com/blog/telegram-notify</guid>
            <pubDate>Wed, 01 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="前言">前言<a href="https://til.trashposts.com/blog/telegram-notify#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="前言的直接連結" title="前言的直接連結" translate="no">​</a></h3>
<p>前幾天看到 Eddie 在<a href="https://eddielv.com/musings/1-week-leave-ig/" target="_blank" rel="noopener noreferrer" class="">這篇文章</a>中提到，戒了 IG 後「會想一直開自己網站刷留言，看看有沒有新留言！」。</p>
<p>其實我的這套「<a href="https://trashposts.com/blog/build-my-own-guestbook/" target="_blank" rel="noopener noreferrer" class="">留言系統</a>」有接「<a href="https://trashposts.com/blog/line-notify/" target="_blank" rel="noopener noreferrer" class="">通知功能</a>」耶！只要有人留言，就會觸發 Telegram 的機器人通知我，這樣我就能快快審核，不用定時一直上去檢查。</p>
<p>不過，更簡單的方法應該是：Google Apps Script 內建直接用 Gmail 發信，這樣還能順便備份留言，一舉兩得，簡單又好用！（但我還沒試過，講得我自己都想用了）</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="正文">正文<a href="https://til.trashposts.com/blog/telegram-notify#%E6%AD%A3%E6%96%87" class="hash-link" aria-label="正文的直接連結" title="正文的直接連結" translate="no">​</a></h3>
<p>有時候會希望程式跑完某件事之後，自動發個通知給自己，像是排程結束、伺服器異常、或是有人填了表單之類的。</p>
<p>這件事其實用 Telegram 來做超簡單，只要申請一個 BOT、拿到 Chat ID，然後用 POST 打一下 Telegram 的 API 就搞定了！</p>
<blockquote>
<p>BTW，其實我早期一直都是用 Line Notify 來做通知，但是 Line 又複雜又難用，而且 2025 年 Notify 功能就收掉了，於是就改成用 Telegram 來做通知了。</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="筆記">筆記<a href="https://til.trashposts.com/blog/telegram-notify#%E7%AD%86%E8%A8%98" class="hash-link" aria-label="筆記的直接連結" title="筆記的直接連結" translate="no">​</a></h3>
<ul>
<li class=""><a class="" href="https://til.trashposts.com/notes/tutorial/telegram-notify">如何使用 Telegram 傳送通知給自己</a></li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[I'm Marcus 的閱讀軌跡（推薦系統）]]></title>
            <link>https://til.trashposts.com/blog/marcus-reading-trail</link>
            <guid>https://til.trashposts.com/blog/marcus-reading-trail</guid>
            <pubDate>Thu, 26 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[今天看到 I'm Marcus 的文章：「来玩玩新开发的小游戏吧」。]]></description>
            <content:encoded><![CDATA[<p>今天看到 I'm Marcus 的文章：「<a href="https://immarcus.com/blog/reading-trail" target="_blank" rel="noopener noreferrer" class="">来玩玩新开发的小游戏吧</a>」。</p>
<p>Marcus 在自己的部落格實作了一套基於「閱讀軌跡」的文章推薦系統，這個設計還滿有意思的。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="我觀察到的一些東西">我觀察到的一些東西：<a href="https://til.trashposts.com/blog/marcus-reading-trail#%E6%88%91%E8%A7%80%E5%AF%9F%E5%88%B0%E7%9A%84%E4%B8%80%E4%BA%9B%E6%9D%B1%E8%A5%BF" class="hash-link" aria-label="我觀察到的一些東西：的直接連結" title="我觀察到的一些東西：的直接連結" translate="no">​</a></h3>
<ol>
<li class="">文章向量壓縮到 64 維，整份資料不到 200KB，載入和計算速度都很快。</li>
<li class="">使用者記錄存在瀏覽器的 Local Storage，完全不需要後端，隱私性高又即時。</li>
<li class="">文章不僅能標記「喜歡」，還能標記「不喜歡」，系統會同時考慮兩種訊號。</li>
<li class="">根據「已反饋文章」計算出使用者向量，並對「未反饋文章」計算相似度，決定推薦哪篇文章，也不會重複推薦。</li>
<li class="">每次根據當下的狀態計算推薦，並且記錄下來，形成一條固定的閱讀軌跡。</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="我推測他的運作原理大概是">我推測他的運作原理大概是：<a href="https://til.trashposts.com/blog/marcus-reading-trail#%E6%88%91%E6%8E%A8%E6%B8%AC%E4%BB%96%E7%9A%84%E9%81%8B%E4%BD%9C%E5%8E%9F%E7%90%86%E5%A4%A7%E6%A6%82%E6%98%AF" class="hash-link" aria-label="我推測他的運作原理大概是：的直接連結" title="我推測他的運作原理大概是：的直接連結" translate="no">​</a></h3>
<ol>
<li class="">使用者向量 = <code>AVG(喜歡文章向量) - AVG(不喜歡文章向量)</code></li>
<li class="">計算所有的 <code>Cosine Similarity(使用者向量, 未反饋文章)</code></li>
<li class="">取 Top 1 作為推薦</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="幾個吹毛求疵的小缺點">幾個吹毛求疵的小缺點：<a href="https://til.trashposts.com/blog/marcus-reading-trail#%E5%B9%BE%E5%80%8B%E5%90%B9%E6%AF%9B%E6%B1%82%E7%96%B5%E7%9A%84%E5%B0%8F%E7%BC%BA%E9%BB%9E" class="hash-link" aria-label="幾個吹毛求疵的小缺點：的直接連結" title="幾個吹毛求疵的小缺點：的直接連結" translate="no">​</a></h3>
<ul>
<li class="">只有推薦一篇文章的話，我自己會覺得有點「被牽著走」的感覺，選擇有點太少了。（不過這樣才是「軌跡」，所以也不是缺點，只是一種取捨）</li>
<li class="">按「換點口味」會被視為負反饋，但這不一定代表我對該主題不感興趣，可能只是對該文章不感興趣而已。</li>
<li class="">要讓使用者評分實在是有點難度，但這確實是比較尊重使用者的做法。（通常會用隱性一點的特徵）</li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[用 FFMPEG 製作 Nightcore 風格音樂]]></title>
            <link>https://til.trashposts.com/blog/nightcore-ffmpeg</link>
            <guid>https://til.trashposts.com/blog/nightcore-ffmpeg</guid>
            <pubDate>Mon, 23 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[今天跟 GPT 學到了用 FFMPEG 製作 Nightcore 風格音樂的方法。]]></description>
            <content:encoded><![CDATA[<p>今天跟 GPT 學到了用 FFMPEG 製作 <a href="https://zh.wikipedia.org/zh-tw/Nightcore" target="_blank" rel="noopener noreferrer" class="">Nightcore</a> 風格音樂的方法。</p>
<p><strong>Nightcore 的核心特徵是「音調變高、速度變快」，聽起來像花栗鼠在唱歌的那種感覺。</strong></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="指令">指令<a href="https://til.trashposts.com/blog/nightcore-ffmpeg#%E6%8C%87%E4%BB%A4" class="hash-link" aria-label="指令的直接連結" title="指令的直接連結" translate="no">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">ffmpeg -i input.mp3 -af "asetrate=44100*1.35,aresample=44100" output.mp3</span><br></span></code></pre></div></div>
<ul>
<li class="">
<p><strong><code>asetrate=44100*1.35</code></strong>：改變音訊的播放速率，將採樣率強制改為原來的 1.35 倍，音調與速度都會同步提高。</p>
</li>
<li class="">
<p><strong><code>aresample=44100</code></strong>：將採樣率重採樣回標準的 44100Hz，確保檔案在所有設備上都能正常播放。</p>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="微調速度">微調速度<a href="https://til.trashposts.com/blog/nightcore-ffmpeg#%E5%BE%AE%E8%AA%BF%E9%80%9F%E5%BA%A6" class="hash-link" aria-label="微調速度的直接連結" title="微調速度的直接連結" translate="no">​</a></h3>
<ul>
<li class=""><strong><code>atempo=1.05</code></strong>：純速度濾波器，不影響音調，用來微調最終節奏。</li>
</ul>
<p>例如可以這樣搭配：</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">ffmpeg -i input.mp3 -af "asetrate=44100*1.3,aresample=44100,atempo=1.05" output.mp3</span><br></span></code></pre></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[用 Embedding 做「相關文章」推薦]]></title>
            <link>https://til.trashposts.com/blog/related-articles</link>
            <guid>https://til.trashposts.com/blog/related-articles</guid>
            <pubDate>Tue, 17 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[最近幫部落格做了一個「相關文章」功能，用 AI 的語義向量（Embedding）來計算文章之間的相似度。]]></description>
            <content:encoded><![CDATA[<p>最近幫部落格做了一個「相關文章」功能，用 AI 的語義向量（Embedding）來計算文章之間的相似度。</p>
<blockquote>
<p>原文：《<a href="https://trashposts.com/blog/build-my-own-related-articles" target="_blank" rel="noopener noreferrer" class="">DIY 系列：來做個「相關文章」功能</a>》</p>
</blockquote>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="原理">原理<a href="https://til.trashposts.com/blog/related-articles#%E5%8E%9F%E7%90%86" class="hash-link" aria-label="原理的直接連結" title="原理的直接連結" translate="no">​</a></h3>
<p>三個步驟：</p>
<ol>
<li class="">
<p><strong>把文章餵給 Embedding 模型</strong>，得到一組向量（一串浮點數）。這組向量代表文章的「語意」，語意越接近的文章，向量在空間中的距離也越近。</p>
</li>
<li class="">
<p><strong>計算<a href="https://zh.wikipedia.org/zh-tw/%E4%BD%99%E5%BC%A6%E7%9B%B8%E4%BC%BC%E6%80%A7" target="_blank" rel="noopener noreferrer" class="">餘弦相似度</a></strong>，也就是兩個向量之間的夾角，越接近 1 代表越相似。</p>
</li>
<li class="">
<p><strong>排序取前 K 名</strong>，就是「相關文章」了。</p>
</li>
</ol>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="兩種-embedding-方案">兩種 Embedding 方案<a href="https://til.trashposts.com/blog/related-articles#%E5%85%A9%E7%A8%AE-embedding-%E6%96%B9%E6%A1%88" class="hash-link" aria-label="兩種 Embedding 方案的直接連結" title="兩種 Embedding 方案的直接連結" translate="no">​</a></h3>
<p><strong>方案一：Gemini API（免費）</strong></p>
<p>到 <a href="https://aistudio.google.com/api-keys" target="_blank" rel="noopener noreferrer" class="">Google AI Studio</a> 申請 API Key，呼叫 <code>gemini-embedding-001</code> 模型。</p>
<p>免費方案有速率限制，我的做法是每篇截取前 2000 字，每隔兩秒呼叫一次。</p>
<p><strong>方案二：BGE-M3 本地端（也免費）</strong></p>
<p>用 <a href="https://ollama.com/" target="_blank" rel="noopener noreferrer" class="">Ollama</a> 在本機跑 <a href="https://huggingface.co/BAAI/bge-m3" target="_blank" rel="noopener noreferrer" class="">BGE-M3</a>，CPU 就能跑，完全離線。</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">ollama pull bge-m3</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pip install ollama</span><br></span></code></pre></div></div>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> ollama</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">res </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ollama</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">embeddings</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">model</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"bge-m3"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> prompt</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"文章內容..."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">vector </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> res</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"embedding"</span><span class="token punctuation" style="color:#393A34">]</span><br></span></code></pre></div></div>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="快取機制">快取機制<a href="https://til.trashposts.com/blog/related-articles#%E5%BF%AB%E5%8F%96%E6%A9%9F%E5%88%B6" class="hash-link" aria-label="快取機制的直接連結" title="快取機制的直接連結" translate="no">​</a></h3>
<p>每次重新計算 Embedding 很耗時，所以用 <code>Hash(標題 + 內文)</code> 來判斷文章是否有改變，沒變就直接讀快取。</p>
<p>相似度計算目前是全部重跑（讓新舊文章可以互相連結），一百多篇大概三秒，還可以接受。</p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="完整流程">完整流程<a href="https://til.trashposts.com/blog/related-articles#%E5%AE%8C%E6%95%B4%E6%B5%81%E7%A8%8B" class="hash-link" aria-label="完整流程的直接連結" title="完整流程的直接連結" translate="no">​</a></h3>
<ol>
<li class="">載入快取，用 Hash 比對找出需要更新的文章。</li>
<li class="">清除已刪除文章的舊快取。</li>
<li class="">對需要更新的文章重新 Embedding，存入快取。</li>
<li class="">計算所有文章兩兩之間的相似度，排序取前 K 名。</li>
<li class="">輸出 <code>related.json</code> 或直接生成靜態 HTML。</li>
</ol>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[如何偵測檔案變動]]></title>
            <link>https://til.trashposts.com/blog/detect-file-changes</link>
            <guid>https://til.trashposts.com/blog/detect-file-changes</guid>
            <pubDate>Thu, 12 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="前言">前言<a href="https://til.trashposts.com/blog/detect-file-changes#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="前言的直接連結" title="前言的直接連結" translate="no">​</a></h3>
<p>我自己在目前部落格上有三種實際應用場景：</p>
<ol>
<li class="">
<p><strong>Preview 網頁自動 reload</strong>：這個場景是高頻檢查，例如每秒看一次檔案有沒有變。就算偶爾誤判，最多只是多 reload 一次，所以我用檔案修改時間來判斷。這邊我用 Polling 的方式來做，雖然 I/O 比較重一點，但實現起來簡單，也不用去安裝其他套件。</p>
</li>
<li class="">
<p><strong>Build 建立靜態網站</strong>：這邊的重點是正確性，要精準知道內容是否真的改變，避免不必要重建或漏建，所以我會直接比對全文內容，也就是比對「渲染後的文章」與「輸出資料夾的文章」。</p>
</li>
<li class="">
<p><strong>檔案變動後要打 API</strong>：打 API 通常有副作用，不能亂觸發。這時候不一定要知道改了哪裡，只要知道內容真的不同即可，所以我會把 Hash 存起來，如果有比對到 Hash 變更再去打 API。這種做法很優雅，不需要多留一份原始檔案，只要保留原檔案的 Hash 值就好了。</p>
</li>
</ol>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="三種方法的差異">三種方法的差異<a href="https://til.trashposts.com/blog/detect-file-changes#%E4%B8%89%E7%A8%AE%E6%96%B9%E6%B3%95%E7%9A%84%E5%B7%AE%E7%95%B0" class="hash-link" aria-label="三種方法的差異的直接連結" title="三種方法的差異的直接連結" translate="no">​</a></h3>
<table><thead><tr><th>方法</th><th>核心概念</th><th>速度</th><th>準確度</th><th>代價</th></tr></thead><tbody><tr><td>時間戳</td><td>比對檔案最後修改時間</td><td>很快</td><td>中</td><td>可能會誤判</td></tr><tr><td>全文比對</td><td>逐字比較內容</td><td>慢</td><td>高</td><td>需要讀兩份完整檔案</td></tr><tr><td>Hash 比對</td><td>比較最終內容 Hash</td><td>快</td><td>高</td><td>需額外保存 Hash 值</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-比較檔案時間">1. 比較檔案時間<a href="https://til.trashposts.com/blog/detect-file-changes#1-%E6%AF%94%E8%BC%83%E6%AA%94%E6%A1%88%E6%99%82%E9%96%93" class="hash-link" aria-label="1. 比較檔案時間的直接連結" title="1. 比較檔案時間的直接連結" translate="no">​</a></h3>
<p>只要看檔案最後修改時間有沒有變，就能快速判斷「可能有變更」。</p>
<ul>
<li class="">優點：極快、實作簡單，適合高頻率輪詢。</li>
<li class="">缺點：有誤判機會，像是改了 metadata、或某些同步工具重寫時間。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-全文比對">2. 全文比對<a href="https://til.trashposts.com/blog/detect-file-changes#2-%E5%85%A8%E6%96%87%E6%AF%94%E5%B0%8D" class="hash-link" aria-label="2. 全文比對的直接連結" title="2. 全文比對的直接連結" translate="no">​</a></h3>
<p>直接把新舊檔案內容拿來比，這是最準確的方法。</p>
<ul>
<li class="">優點：只要內容一樣，就一定判定「沒變」。</li>
<li class="">缺點：每次都要讀檔和比對，檔案越大越花時間。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-hash-比對">3. Hash 比對<a href="https://til.trashposts.com/blog/detect-file-changes#3-hash-%E6%AF%94%E5%B0%8D" class="hash-link" aria-label="3. Hash 比對的直接連結" title="3. Hash 比對的直接連結" translate="no">​</a></h3>
<p>做法是先計算檔案 Hash，把它存起來，下次再算一次做比對。</p>
<ul>
<li class="">優點：不需要知道改了哪裡，只要知道內容是否不同，速度與儲存成本都不錯。</li>
<li class="">缺點：仍然要讀取內容計算 Hash；另外需要管理一份本地 Hash 資料。</li>
</ul>
<p>實務上，若是有副作用的操作（例如打 API、觸發部署、通知、計費），Hash 很適合。</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[如何幫網站新增一個 Theme]]></title>
            <link>https://til.trashposts.com/blog/website-theme</link>
            <guid>https://til.trashposts.com/blog/website-theme</guid>
            <pubDate>Wed, 11 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[前言]]></description>
            <content:encoded><![CDATA[<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="前言">前言<a href="https://til.trashposts.com/blog/website-theme#%E5%89%8D%E8%A8%80" class="hash-link" aria-label="前言的直接連結" title="前言的直接連結" translate="no">​</a></h3>
<p>今天想嘗試幫網站做一個 theme。</p>
<p>以前我也曾經做過幾次修改，比如說「<a href="https://trashposts.com/pages/christmas-theme-and-guestbook/" target="_blank" rel="noopener noreferrer" class="">聖誕節主題</a>」、「<a href="https://trashposts.com/pages/matcha-theme/" target="_blank" rel="noopener noreferrer" class="">抹茶主題</a>」等等。</p>
<p>原本我都是直接去修改 <code>styles.css</code>，後來發現這樣要做「期間限定」的 Theme 不是很方便。</p>
<p>所以我就把一些常見的顏色改成參數，可以直接用參數改變顏色，直接幫網站換 Theme。但有時候是連結構都會改變，這時候只改變數就不太夠用了（搞得太複雜也不好維護）。</p>
<p>所以呢，以下整理介紹三種常見的 Theme 做法：</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-css-變數切換">1. CSS 變數切換<a href="https://til.trashposts.com/blog/website-theme#1-css-%E8%AE%8A%E6%95%B8%E5%88%87%E6%8F%9B" class="hash-link" aria-label="1. CSS 變數切換的直接連結" title="1. CSS 變數切換的直接連結" translate="no">​</a></h3>
<p>先把顏色、字體、間距等抽成 CSS 變數（Custom Properties），切換 Theme 時只要替換一組變數值。</p>
<div class="language-css codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-css codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/* 預設主題 */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector pseudo-class" style="color:#00009f">:root</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--color-bg</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token hexcode color">#fff</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--color-text</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token hexcode color">#333</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/* 另一個 Theme */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector pseudo-class" style="color:#00009f">:root</span><span class="token selector attribute punctuation" style="color:#393A34">[</span><span class="token selector attribute attr-name" style="color:#00a4db">data-theme</span><span class="token selector attribute operator" style="color:#393A34">=</span><span class="token selector attribute attr-value" style="color:#e3116c">"retro"</span><span class="token selector attribute punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--color-bg</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token hexcode color">#f2f2f2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token variable" style="color:#36acaa">--color-text</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token hexcode color">#111</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class=""><strong>優點：</strong> 最輕量，只需維護一份 CSS。</li>
<li class=""><strong>缺點：</strong> 只能改到已經參數化的屬性。像 <code>box-shadow</code>、<code>border-radius</code>、<code>order</code> 這類結構型樣式，通常不夠用。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-完整替換整份-css">2. 完整替換整份 CSS<a href="https://til.trashposts.com/blog/website-theme#2-%E5%AE%8C%E6%95%B4%E6%9B%BF%E6%8F%9B%E6%95%B4%E4%BB%BD-css" class="hash-link" aria-label="2. 完整替換整份 CSS的直接連結" title="2. 完整替換整份 CSS的直接連結" translate="no">​</a></h3>
<p>直接維護兩份完整 CSS（例如 <code>default.css</code>、<code>theme.css</code>），切換時整份替換。</p>
<ul>
<li class=""><strong>優點：</strong> 兩份 CSS 完全獨立，不需要考慮覆蓋衝突。</li>
<li class=""><strong>缺點：</strong> 維護成本最高，共用元件的修改要同步兩份。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-css-覆蓋override">3. CSS 覆蓋（Override）<a href="https://til.trashposts.com/blog/website-theme#3-css-%E8%A6%86%E8%93%8Boverride" class="hash-link" aria-label="3. CSS 覆蓋（Override）的直接連結" title="3. CSS 覆蓋（Override）的直接連結" translate="no">​</a></h3>
<p>保留原本的 <code>styles.css</code>，再額外新增一份 <code>theme.css</code>，只覆蓋需要改動的規則。</p>
<div class="language-css codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-css codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token selector class" style="color:#00009f">.post-card</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">background</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token hexcode color">#f2f2f2</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">border-radius</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<ul>
<li class=""><strong>優點：</strong> 可以覆蓋任意屬性，不受限於變數；原本 CSS 幾乎不用動，載入即套用、移除即還原。</li>
<li class=""><strong>缺點：</strong> 需要注意 CSS 優先權（specificity）與載入順序，必要時要調整選擇器權重。</li>
</ul>
<p>實作上，只要在 HTML 的 <code>&lt;head&gt;</code> 多載入一行：</p>
<div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">link</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">rel</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">stylesheet</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">href</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">/assets/css/styles.css</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">link</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">rel</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">stylesheet</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">href</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">/assets/css/theme.css</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">&lt;!-- 加這行 --&gt;</span><br></span></code></pre></div></div>
<p><code>theme.css</code> 直接用相同選擇器覆蓋 <code>styles.css</code>。由於它在後面載入，在相同優先權下會覆蓋前者（CSS cascade）。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="如果要做即時切換">如果要做即時切換<a href="https://til.trashposts.com/blog/website-theme#%E5%A6%82%E6%9E%9C%E8%A6%81%E5%81%9A%E5%8D%B3%E6%99%82%E5%88%87%E6%8F%9B" class="hash-link" aria-label="如果要做即時切換的直接連結" title="如果要做即時切換的直接連結" translate="no">​</a></h3>
<p>可以用 JS 搭配 <code>body</code> class 做 runtime 切換：</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token dom variable" style="color:#36acaa">document</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">body</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">classList</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">toggle</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'theme-alt'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<p>這時候，Theme 規則就要加上 <code>body.theme-alt</code> 前綴：</p>
<div class="language-css codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-css codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token selector" style="color:#00009f">body</span><span class="token selector class" style="color:#00009f">.theme-alt</span><span class="token selector" style="color:#00009f"> </span><span class="token selector class" style="color:#00009f">.post-card</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> ... </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector" style="color:#00009f">body</span><span class="token selector class" style="color:#00009f">.theme-alt</span><span class="token selector" style="color:#00009f"> </span><span class="token selector class" style="color:#00009f">.post-title</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> ... </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>如果你要的是「快速上線、可恢復、又能改結構樣式」，通常 CSS 覆蓋會是最平衡的做法。</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[CSS 圖層魔術]]></title>
            <link>https://til.trashposts.com/blog/magic</link>
            <guid>https://til.trashposts.com/blog/magic</guid>
            <pubDate>Tue, 10 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[今天做了一個很白爛的圖層魔術。]]></description>
            <content:encoded><![CDATA[<p>今天做了一個很白爛的<a href="https://trashposts.com/blog/magic/" target="_blank" rel="noopener noreferrer" class="">圖層魔術</a>。</p>
<p>按下按鈕後，帽子先往下蓋住，再掀開，裡面會冒出兔子、青蛙，或者乾脆什麼都沒有。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="說明">說明<a href="https://til.trashposts.com/blog/magic#%E8%AA%AA%E6%98%8E" class="hash-link" aria-label="說明的直接連結" title="說明的直接連結" translate="no">​</a></h3>
<ul>
<li class=""><code>position: relative</code>：讓舞台變成絕對定位元素的參考點。</li>
<li class=""><code>position: absolute</code>：把每張圖放到指定座標。</li>
<li class=""><code>z-index</code>：控制遮擋順序。帽子要蓋住角色，所以層級要最高。</li>
<li class=""><code>transition</code>：當 <code>top</code> 被改變時，自動產生移動動畫，做出「蓋住 -&gt; 掀開」的節奏。</li>
<li class=""><code>display: none</code> 雖然簡單，但不能直接做淡入淡出；如果需要更順的切換，可以改用 <code>opacity</code> 搭配 <code>visibility</code>。</li>
<li class="">舞台尺寸最好固定，不然不同圖片尺寸可能會讓圖層位置跑掉。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="程式碼">程式碼<a href="https://til.trashposts.com/blog/magic#%E7%A8%8B%E5%BC%8F%E7%A2%BC" class="hash-link" aria-label="程式碼的直接連結" title="程式碼的直接連結" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>注意</div><div class="admonitionContent_BuS1"><p>圖片請自備～（或者去文章內右鍵下載）</p></div></div>
<div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">div</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">class</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">magic-stage</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">style</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:#393A34"><span class="token style language-css">    </span><span class="token style language-css selector class" style="color:#00009f">.magic-stage</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">{</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">position</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> relative</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">width</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">300</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">height</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">400</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">margin</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">0</span><span class="token style language-css unit">px</span><span class="token style language-css"> auto</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">text-align</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> center</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">}</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:#393A34"><span class="token style language-css">    </span><span class="token style language-css selector class" style="color:#00009f">.magic-stage</span><span class="token style language-css selector" style="color:#00009f"> img</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">{</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">position</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> absolute</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">transition</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> top </span><span class="token style language-css number" style="color:#36acaa">0.6</span><span class="token style language-css unit">s</span><span class="token style language-css"> ease-in-out</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">}</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:#393A34"><span class="token style language-css">    </span><span class="token style language-css selector class" style="color:#00009f">.magic-stage</span><span class="token style language-css selector" style="color:#00009f"> </span><span class="token style language-css selector class" style="color:#00009f">.magic-table</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">{</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">width</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">280</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">left</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">10</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">top</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">250</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">z-index</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">1</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">}</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:#393A34"><span class="token style language-css">    </span><span class="token style language-css selector class" style="color:#00009f">.magic-stage</span><span class="token style language-css selector" style="color:#00009f"> </span><span class="token style language-css selector class" style="color:#00009f">.magic-hat</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">{</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">width</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">160</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">left</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">70</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">top</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">0</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">z-index</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">3</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">}</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:#393A34"><span class="token style language-css">    </span><span class="token style language-css selector class" style="color:#00009f">.magic-stage</span><span class="token style language-css selector" style="color:#00009f"> </span><span class="token style language-css selector class" style="color:#00009f">.magic-rabbit</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">{</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">width</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">80</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">left</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">110</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">top</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">170</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">z-index</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">2</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">display</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> none</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">}</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:#393A34"><span class="token style language-css">    </span><span class="token style language-css selector class" style="color:#00009f">.magic-stage</span><span class="token style language-css selector" style="color:#00009f"> </span><span class="token style language-css selector class" style="color:#00009f">.magic-frog</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">{</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">width</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">80</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">left</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">110</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">top</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">195</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">z-index</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">2</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">display</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> none</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">}</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:#393A34"><span class="token style language-css">    </span><span class="token style language-css selector class" style="color:#00009f">.magic-stage</span><span class="token style language-css selector" style="color:#00009f"> </span><span class="token style language-css selector class" style="color:#00009f">.active</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">{</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">display</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> block</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">}</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:#393A34"><span class="token style language-css">    </span><span class="token style language-css selector class" style="color:#00009f">.magic-stage</span><span class="token style language-css selector" style="color:#00009f"> button</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">{</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">margin-top</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">340</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">padding</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">10</span><span class="token style language-css unit">px</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">30</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">cursor</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> pointer</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">border</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">2</span><span class="token style language-css unit">px</span><span class="token style language-css"> solid </span><span class="token style language-css hexcode color">#6200ee</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">border-radius</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">4</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">background</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css hexcode color">#6200ee</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">color</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css color">white</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">font-size</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">16</span><span class="token style language-css unit">px</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">font-weight</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> bold</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">transition</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css number" style="color:#36acaa">0.2</span><span class="token style language-css unit">s</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">}</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:#393A34"><span class="token style language-css">    </span><span class="token style language-css selector class" style="color:#00009f">.magic-stage</span><span class="token style language-css selector" style="color:#00009f"> button</span><span class="token style language-css selector pseudo-class" style="color:#00009f">:disabled</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">{</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">background</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css hexcode color">#ccc</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">border-color</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> </span><span class="token style language-css hexcode color">#ccc</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css property" style="color:#36acaa">cursor</span><span class="token style language-css punctuation" style="color:#393A34">:</span><span class="token style language-css"> not-allowed</span><span class="token style language-css punctuation" style="color:#393A34">;</span><span class="token style language-css"> </span><span class="token style language-css punctuation" style="color:#393A34">}</span><span class="token style language-css"></span><br></span><span class="token-line" style="color:#393A34"><span class="token style language-css">  </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">style</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">table.png</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">class</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">magic-table</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">alt</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">magic-table</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">hat.png</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">class</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">magic-hat</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">alt</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">magic-hat</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">rabbit.png</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">class</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">magic-rabbit</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">alt</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">magic-rabbit</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">frog.png</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">class</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">magic-frog</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">alt</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">magic-frog</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">button</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">class</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">magic-button</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag special-attr attr-name" style="color:#00a4db">onclick</span><span class="token tag special-attr attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag special-attr attr-value punctuation" style="color:#393A34">"</span><span class="token tag special-attr attr-value value javascript language-javascript function" style="color:#d73a49">performMagic</span><span class="token tag special-attr attr-value value javascript language-javascript punctuation" style="color:#393A34">(</span><span class="token tag special-attr attr-value value javascript language-javascript punctuation" style="color:#393A34">)</span><span class="token tag special-attr attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain">Magic</span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">button</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">script</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">    </span><span class="token script language-javascript keyword" style="color:#00009f">let</span><span class="token script language-javascript"> magicStep </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:#36acaa">0</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">    </span><span class="token script language-javascript keyword" style="color:#00009f">function</span><span class="token script language-javascript"> </span><span class="token script language-javascript function" style="color:#d73a49">performMagic</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:#393A34">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">      </span><span class="token script language-javascript keyword" style="color:#00009f">const</span><span class="token script language-javascript"> magicStage </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript dom variable" style="color:#36acaa">document</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript method function property-access" style="color:#d73a49">querySelector</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript string" style="color:#e3116c">'.magic-stage'</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">      </span><span class="token script language-javascript keyword" style="color:#00009f">const</span><span class="token script language-javascript"> magicHat </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> magicStage</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript method function property-access" style="color:#d73a49">querySelector</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript string" style="color:#e3116c">'.magic-hat'</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">      </span><span class="token script language-javascript keyword" style="color:#00009f">const</span><span class="token script language-javascript"> magicRabbit </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> magicStage</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript method function property-access" style="color:#d73a49">querySelector</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript string" style="color:#e3116c">'.magic-rabbit'</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">      </span><span class="token script language-javascript keyword" style="color:#00009f">const</span><span class="token script language-javascript"> magicFrog </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> magicStage</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript method function property-access" style="color:#d73a49">querySelector</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript string" style="color:#e3116c">'.magic-frog'</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">      </span><span class="token script language-javascript keyword" style="color:#00009f">const</span><span class="token script language-javascript"> magicButton </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> magicStage</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript method function property-access" style="color:#d73a49">querySelector</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript string" style="color:#e3116c">'.magic-button'</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">      magicButton</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript property-access">disabled</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript boolean" style="color:#36acaa">true</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">      magicHat</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript property-access">style</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript property-access">top</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">"140px"</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">      </span><span class="token script language-javascript function" style="color:#d73a49">setTimeout</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:#393A34">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">        magicRabbit</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript property-access">classList</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript method function property-access" style="color:#d73a49">remove</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript string" style="color:#e3116c">'active'</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">        magicFrog</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript property-access">classList</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript method function property-access" style="color:#d73a49">remove</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript string" style="color:#e3116c">'active'</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">        </span><span class="token script language-javascript keyword control-flow" style="color:#00009f">if</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript">magicStep </span><span class="token script language-javascript operator" style="color:#393A34">===</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:#36acaa">0</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:#393A34">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">          magicRabbit</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript property-access">classList</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript method function property-access" style="color:#d73a49">add</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript string" style="color:#e3116c">'active'</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">        </span><span class="token script language-javascript punctuation" style="color:#393A34">}</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword control-flow" style="color:#00009f">else</span><span class="token script language-javascript"> </span><span class="token script language-javascript keyword control-flow" style="color:#00009f">if</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript">magicStep </span><span class="token script language-javascript operator" style="color:#393A34">===</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:#36acaa">1</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:#393A34">{</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">          magicFrog</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript property-access">classList</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript method function property-access" style="color:#d73a49">add</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript string" style="color:#e3116c">'active'</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">        </span><span class="token script language-javascript punctuation" style="color:#393A34">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">        magicStep </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript">magicStep </span><span class="token script language-javascript operator" style="color:#393A34">+</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:#36acaa">1</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:#393A34">%</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:#36acaa">3</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">        magicHat</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript property-access">style</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript property-access">top</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript string" style="color:#e3116c">"0px"</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">        </span><span class="token script language-javascript function" style="color:#d73a49">setTimeout</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">(</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript"> </span><span class="token script language-javascript arrow operator" style="color:#393A34">=&gt;</span><span class="token script language-javascript"> magicButton</span><span class="token script language-javascript punctuation" style="color:#393A34">.</span><span class="token script language-javascript property-access">disabled</span><span class="token script language-javascript"> </span><span class="token script language-javascript operator" style="color:#393A34">=</span><span class="token script language-javascript"> </span><span class="token script language-javascript boolean" style="color:#36acaa">false</span><span class="token script language-javascript punctuation" style="color:#393A34">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:#36acaa">600</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">      </span><span class="token script language-javascript punctuation" style="color:#393A34">}</span><span class="token script language-javascript punctuation" style="color:#393A34">,</span><span class="token script language-javascript"> </span><span class="token script language-javascript number" style="color:#36acaa">1250</span><span class="token script language-javascript punctuation" style="color:#393A34">)</span><span class="token script language-javascript punctuation" style="color:#393A34">;</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">    </span><span class="token script language-javascript punctuation" style="color:#393A34">}</span><span class="token script language-javascript"></span><br></span><span class="token-line" style="color:#393A34"><span class="token script language-javascript">  </span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">script</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">div</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Cloudflare Pages：使用 Deploy Hook 觸發部署]]></title>
            <link>https://til.trashposts.com/blog/cloudflare-deploy-hooks</link>
            <guid>https://til.trashposts.com/blog/cloudflare-deploy-hooks</guid>
            <pubDate>Mon, 09 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[上週遇到一個狀況：]]></description>
            <content:encoded><![CDATA[<p>上週遇到一個狀況：</p>
<p>Cloudflare Pages 已經綁定 GitHub，但 git push 之後，沒有自動觸發新的部署（至今仍然不知道為啥）。</p>
<p>後來我又嘗試推了一個空的 commit 上去，結果還是沒觸發（很蠢，我知道）。</p>
<p>查了一下資料，改成使用 Cloudflare Pages 的 Deploy Hook，結果就成功觸發了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="問題">問題<a href="https://til.trashposts.com/blog/cloudflare-deploy-hooks#%E5%95%8F%E9%A1%8C" class="hash-link" aria-label="問題的直接連結" title="問題的直接連結" translate="no">​</a></h3>
<ul>
<li class="">Cloudflare Pages 專案已綁定 GitHub。</li>
<li class="">Push 到指定分支後，沒有看到新的部署紀錄（但以前 git push 都有正常觸發）。</li>
<li class="">網站內容維持舊版本。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="處理">處理<a href="https://til.trashposts.com/blog/cloudflare-deploy-hooks#%E8%99%95%E7%90%86" class="hash-link" aria-label="處理的直接連結" title="處理的直接連結" translate="no">​</a></h3>
<p>改成 Deploy Hook 後，部署有成功觸發，網站也有順利更新。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="筆記">筆記<a href="https://til.trashposts.com/blog/cloudflare-deploy-hooks#%E7%AD%86%E8%A8%98" class="hash-link" aria-label="筆記的直接連結" title="筆記的直接連結" translate="no">​</a></h3>
<ul>
<li class=""><a class="" href="https://til.trashposts.com/notes/web/cloudflare-pages-deploy-hooks">Cloudflare Pages Deploy Hook 筆記</a></li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[重新設計：極簡部落格]]></title>
            <link>https://til.trashposts.com/blog/simple-blog</link>
            <guid>https://til.trashposts.com/blog/simple-blog</guid>
            <pubDate>Thu, 05 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[靈感]]></description>
            <content:encoded><![CDATA[<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="靈感">靈感<a href="https://til.trashposts.com/blog/simple-blog#%E9%9D%88%E6%84%9F" class="hash-link" aria-label="靈感的直接連結" title="靈感的直接連結" translate="no">​</a></h3>
<p>昨天看到了「<a href="https://stefanbohacek.com/blog/how-to-make-a-website-in-5-minutes/" target="_blank" rel="noopener noreferrer" class="">How to make a website in 5 minutes</a>」這篇文章。</p>
<p>突然覺得可以重新設計一版架構，選擇用我喜歡的方式，設計一個非常、非常簡單，功能也完整的部落格架構。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="極簡部落格demo">極簡部落格（Demo）<a href="https://til.trashposts.com/blog/simple-blog#%E6%A5%B5%E7%B0%A1%E9%83%A8%E8%90%BD%E6%A0%BCdemo" class="hash-link" aria-label="極簡部落格（Demo）的直接連結" title="極簡部落格（Demo）的直接連結" translate="no">​</a></h3>
<ul>
<li class=""><strong><a href="https://b.trashposts.com/" target="_blank" rel="noopener noreferrer" class="">示範網站</a></strong><small>（<a href="https://d1034181036.github.io/simple-blog/" target="_blank" rel="noopener noreferrer" class="">備用</a>）</small></li>
<li class=""><strong><a href="https://github.com/D1034181036/simple-blog" target="_blank" rel="noopener noreferrer" class="">原始碼</a></strong></li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="網站架構">網站架構<a href="https://til.trashposts.com/blog/simple-blog#%E7%B6%B2%E7%AB%99%E6%9E%B6%E6%A7%8B" class="hash-link" aria-label="網站架構的直接連結" title="網站架構的直接連結" translate="no">​</a></h3>
<p><strong>最基本的頁面就只有：</strong></p>
<ul>
<li class="">首頁</li>
<li class="">文章列表<!-- -->
<ul>
<li class="">文章頁面</li>
</ul>
</li>
<li class="">RSS Feed</li>
</ul>
<p><strong>架構如下：</strong></p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">blog/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── index.html                              # 首頁</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── feed.xml                                # RSS Feed</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── assets/                                 # 放全站通用的資源</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">│   └── style.css                           # 網站樣式</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└── posts/                                  # 文章目錄</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ├── index.html                          # 文章列表頁面</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    └── 2026-01-01-first-post/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ├── index.html                      # 文章頁面</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        └── img.webp                        # 文章圖片</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="我最早的部落格">我最早的部落格<a href="https://til.trashposts.com/blog/simple-blog#%E6%88%91%E6%9C%80%E6%97%A9%E7%9A%84%E9%83%A8%E8%90%BD%E6%A0%BC" class="hash-link" aria-label="我最早的部落格的直接連結" title="我最早的部落格的直接連結" translate="no">​</a></h3>
<p>我最早的部落格<strong>更是離譜</strong>，就只有一個頁面：</p>
<ul>
<li class="">首頁（文章全部放在這）</li>
</ul>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">blog/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">├── index.html                          # 首頁</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">└── style.css                           # 網站樣式</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="為什麼當初要把文章都塞在-indexhtml">為什麼當初要把文章都塞在 index.html？<a href="https://til.trashposts.com/blog/simple-blog#%E7%82%BA%E4%BB%80%E9%BA%BC%E7%95%B6%E5%88%9D%E8%A6%81%E6%8A%8A%E6%96%87%E7%AB%A0%E9%83%BD%E5%A1%9E%E5%9C%A8-indexhtml" class="hash-link" aria-label="為什麼當初要把文章都塞在 index.html？的直接連結" title="為什麼當初要把文章都塞在 index.html？的直接連結" translate="no">​</a></h3>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="我在這篇文章其實有提到過了">我在<a href="https://trashposts.com/blog/build-my-own-blog-engine/" target="_blank" rel="noopener noreferrer" class="">這篇文章</a>其實有提到過了。<a href="https://til.trashposts.com/blog/simple-blog#%E6%88%91%E5%9C%A8%E9%80%99%E7%AF%87%E6%96%87%E7%AB%A0%E5%85%B6%E5%AF%A6%E6%9C%89%E6%8F%90%E5%88%B0%E9%81%8E%E4%BA%86" class="hash-link" aria-label="我在這篇文章其實有提到過了的直接連結" title="我在這篇文章其實有提到過了的直接連結" translate="no">​</a></h4>
<blockquote>
<p>我的「貼文」很短，通常就一兩行而已，感覺沒必要做成單獨頁面。而且如果首頁和內頁都要顯示全文，就等於要維護兩份一模一樣的內容。</p>
<p>而且如果共用區塊有改動，所有文章檔案都要跟著改，這樣維護起來也不太實際。再加上要取英文 slug、要管理檔案命名、要按日期排序...</p>
<p>種種理由加起來，我的藉口就是：「一開始只想做最簡單的可行方案，不想搞得太複雜」。</p>
<p>那麼...沒有做獨立頁面會有什麼問題？</p>
<p>最明顯的就是文章數量越來越多，首頁的長度真的會太長。我原本想用「年度分頁」來解決，但這樣一來 RSS 的文章連結就要每年換一次，不太合理。</p>
<p>而且沒有獨立頁面的話，要分享或引用單篇文章也很不方便，對讀者和搜尋引擎（SEO）都不太友善。</p>
</blockquote>
<hr>
<p>現在回頭想想，首頁根本不需要顯示全文，只要有文章列表就好，一般人都是用 RSS 訂閱，會來網站上的人也會從列表上挑感興趣的文章來讀。</p>
<p>我當初應該是想模仿社群平台一篇一篇貼文可以直接看的感覺才這樣做的。（原本讀者只有我自己）</p>
<p>至於「<strong>共用區塊</strong>」的部分，其實有很多方法可以解決：</p>
<ul>
<li class="">引用 JS 的方式去實現共用區塊（<del>但我沒有很喜歡這個方式，個人偏好問題</del>）</li>
<li class="">共用區塊只放一些確定幾乎不會改的，例如網站首頁的連結</li>
<li class="">寫一個簡單的 Python 腳本去批次修改，或者文字編輯器其實也做得到</li>
<li class="">就算真的沒改到，其實也不會怎樣，維持原樣也沒關係</li>
<li class="">只放返回按鈕就好了，沒有共用部分</li>
</ul>
<p>那我這次是怎麼解決這個問題的呢......？<strong>當然是「只放返回按鈕」啊</strong>，夠簡單吧！</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="教學示範">教學示範<a href="https://til.trashposts.com/blog/simple-blog#%E6%95%99%E5%AD%B8%E7%A4%BA%E7%AF%84" class="hash-link" aria-label="教學示範的直接連結" title="教學示範的直接連結" translate="no">​</a></h3>
<p>我可能會再重新寫一篇（或多篇）文章，詳細講一下我是怎麼一步步建立出來的（<del>有需要嗎</del>），以及這樣設計的想法是什麼。</p>
<p>我甚至已經在示範部落格裡面寫了幾篇教學文章，直接把專案抓下來，邊用邊參考也沒問題。</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[部落格新增 RSS 圖示、文章列表修改]]></title>
            <link>https://til.trashposts.com/blog/blog-rss-icon-and-update-article-list</link>
            <guid>https://til.trashposts.com/blog/blog-rss-icon-and-update-article-list</guid>
            <pubDate>Mon, 02 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[新增 RSS 圖示]]></description>
            <content:encoded><![CDATA[<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="新增-rss-圖示">新增 RSS 圖示<a href="https://til.trashposts.com/blog/blog-rss-icon-and-update-article-list#%E6%96%B0%E5%A2%9E-rss-%E5%9C%96%E7%A4%BA" class="hash-link" aria-label="新增 RSS 圖示的直接連結" title="新增 RSS 圖示的直接連結" translate="no">​</a></h3>
<p>今天在部落格網站的招牌上新增了 RSS 圖示。</p>
<p>以前曾經想過加在 Menu，但是總覺得有點突兀、不好看，而且長度太長的話，手機上看 Menu 會變成兩行，畫面很怪。</p>
<p>也想過加在 Footer，不過我 Footer 的年份是用 JS 自動產生的（XD），這樣就要改 JS 或是改結構，但最主要還是視覺上怪怪的，可能要全部重新設計過 Footer 才適合放吧。</p>
<p>另外一個點是，我的首頁目前是顯示 「<strong>10 篇全文</strong>」，這樣要拉到很下面才找得到 RSS，太不友善了。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="固定位置-svg">固定位置 SVG<a href="https://til.trashposts.com/blog/blog-rss-icon-and-update-article-list#%E5%9B%BA%E5%AE%9A%E4%BD%8D%E7%BD%AE-svg" class="hash-link" aria-label="固定位置 SVG的直接連結" title="固定位置 SVG的直接連結" translate="no">​</a></h3>
<p>最後選擇的做法是，先找一個 RSS 的 SVG ，固定放在 Header 右下角的位置。</p>
<p>直接內嵌 SVG 有一個好處，可以透過 CSS 自動調整圖示的大小。</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="svg-圖示">SVG 圖示<a href="https://til.trashposts.com/blog/blog-rss-icon-and-update-article-list#svg-%E5%9C%96%E7%A4%BA" class="hash-link" aria-label="SVG 圖示的直接連結" title="SVG 圖示的直接連結" translate="no">​</a></h4>
<div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">svg</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">width</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">18</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">height</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">18</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">viewBox</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">0 0 24 24</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">xmlns</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">http://www.w3.org/2000/svg</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">aria-label</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">RSS 訂閱</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">rect</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">width</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">24</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">height</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">24</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">rx</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">4</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">fill</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">#E8730A</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">circle</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">cx</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">6.5</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">cy</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">17.5</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">r</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">2.5</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">fill</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">white</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">path</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">d</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">M4 11.5C8.14 11.5 11.5 14.86 11.5 19</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">stroke</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">white</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">stroke-width</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">2.2</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">stroke-linecap</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">round</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">fill</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">none</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">path</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">d</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">M4 6C11.18 6 17 11.82 17 19</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">stroke</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">white</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">stroke-width</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">2.2</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">stroke-linecap</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">round</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">fill</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag attr-value" style="color:#e3116c">none</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">svg</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><br></span></code></pre></div></div>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="css">CSS<a href="https://til.trashposts.com/blog/blog-rss-icon-and-update-article-list#css" class="hash-link" aria-label="CSS的直接連結" title="CSS的直接連結" translate="no">​</a></h4>
<div class="language-css codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-css codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token selector class" style="color:#00009f">.header-rss</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">position</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> absolute</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">bottom</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token unit">px</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">right</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token unit">px</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">line-height</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token selector class" style="color:#00009f">.header-rss</span><span class="token selector" style="color:#00009f"> svg</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">width</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">clamp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">18</span><span class="token unit">px</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token unit">vw</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token unit">px</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">height</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">clamp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">18</span><span class="token unit">px</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token unit">vw</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">20</span><span class="token unit">px</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="文章列表">文章列表<a href="https://til.trashposts.com/blog/blog-rss-icon-and-update-article-list#%E6%96%87%E7%AB%A0%E5%88%97%E8%A1%A8" class="hash-link" aria-label="文章列表的直接連結" title="文章列表的直接連結" translate="no">​</a></h3>
<p>文章列表的部分，最開始是改成年份做區隔，但我發現我發的文章還挺多的，有分跟沒分差不多。</p>
<p>最後受到 <a href="https://shuyulin1127.com/" target="_blank" rel="noopener noreferrer" class="">Shuyu Pixelart</a> 部落格的排版啟發，決定改成年+月來分類。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="截圖">截圖<a href="https://til.trashposts.com/blog/blog-rss-icon-and-update-article-list#%E6%88%AA%E5%9C%96" class="hash-link" aria-label="截圖的直接連結" title="截圖的直接連結" translate="no">​</a></h3>
<p><img decoding="async" loading="lazy" alt="2026-03-02-screenshot.png" src="https://til.trashposts.com/assets/images/2026-03-02-screenshot-5d26756f43f15d80a6bb4a9f58f9ee5f.png" width="679" height="1043" class="img_ev3q"></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Dual-25：基因演算法策略]]></title>
            <link>https://til.trashposts.com/blog/dual-25</link>
            <guid>https://til.trashposts.com/blog/dual-25</guid>
            <pubDate>Fri, 27 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Dual 25 是 Wiwi 在 睡前想到的紙牌對戰遊戲。（好玩！）]]></description>
            <content:encoded><![CDATA[<p>Dual 25 是 Wiwi 在 <a href="https://wiwi.blog/blog/simple-card-battle-game/" target="_blank" rel="noopener noreferrer" class="">睡前想到的紙牌對戰遊戲</a>。（好玩！）</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="遊戲介紹">遊戲介紹<a href="https://til.trashposts.com/blog/dual-25#%E9%81%8A%E6%88%B2%E4%BB%8B%E7%B4%B9" class="hash-link" aria-label="遊戲介紹的直接連結" title="遊戲介紹的直接連結" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://wiwi.blog/blog/simple-card-battle-game" target="_blank" rel="noopener noreferrer" class="">文章介紹</a></li>
<li class=""><a href="https://wiwi.video/w/3p8ApVazbFwMpGBP4eU7rx" target="_blank" rel="noopener noreferrer" class="">影片介紹</a></li>
<li class=""><a href="https://wiwi.cafe/duel-25.html" target="_blank" rel="noopener noreferrer" class="">遊戲網址</a></li>
<li class=""><a href="https://github.com/wiwikuan/duel-25" target="_blank" rel="noopener noreferrer" class="">GitHub</a>／<a href="https://code.wiwi.blog/wiwi/duel-25" target="_blank" rel="noopener noreferrer" class="">Code.Wiwi.Blog</a></li>
</ul>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="好想贏電腦">好想贏電腦<a href="https://til.trashposts.com/blog/dual-25#%E5%A5%BD%E6%83%B3%E8%B4%8F%E9%9B%BB%E8%85%A6" class="hash-link" aria-label="好想贏電腦的直接連結" title="好想贏電腦的直接連結" translate="no">​</a></h2>
<p>我（跟 LLM 互動）寫了一個固定策略，嘗試去贏過這個 MCTS 電腦。</p>
<p>接著再測試了一下對戰，以下是模擬結果：</p>
<ul>
<li class="">對戰場次：10000 場<!-- -->
<ul>
<li class="">✅ 獲勝：5902 (59.0%)</li>
<li class="">🤝 平手：1217 (12.2%)</li>
<li class="">❌ 戰敗：2881 (28.8%)</li>
</ul>
</li>
</ul>
<p>（這樣應該還算不錯吧？）</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="試試看">試試看<a href="https://til.trashposts.com/blog/dual-25#%E8%A9%A6%E8%A9%A6%E7%9C%8B" class="hash-link" aria-label="試試看的直接連結" title="試試看的直接連結" translate="no">​</a></h3>
<ul>
<li class=""><a href="https://d1034181036.github.io/duel-25-with-advisor/duel-25-with-advisor.html" target="_blank" rel="noopener noreferrer" class="">策略提示版</a></li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="訓練基因演算法ga">訓練：基因演算法（GA）<a href="https://til.trashposts.com/blog/dual-25#%E8%A8%93%E7%B7%B4%E5%9F%BA%E5%9B%A0%E6%BC%94%E7%AE%97%E6%B3%95ga" class="hash-link" aria-label="訓練：基因演算法（GA）的直接連結" title="訓練：基因演算法（GA）的直接連結" translate="no">​</a></h2>
<ul>
<li class="">
<p>每種牌型定義 3 個權重參數：</p>
<ul>
<li class=""><strong>基礎參數</strong>（<code>base</code>）：該牌型的基礎分數</li>
<li class=""><strong>牌型參數</strong>（<code>v</code>）：點數的權重，決定大牌還是小牌更優先</li>
<li class=""><strong>危險參數</strong>（<code>danger</code>）：生命值越低時的傾向調整 = (25 - 當前生命值) / 25，範圍是 0~1</li>
</ul>
</li>
<li class="">
<p>每張牌會根據以下公式計算分數，分數最高的牌就會被選出：</p>
<ul>
<li class="">attack  = atk_base  + v × atk_v  + danger × atk_danger</li>
<li class="">counter = ctr_base  + v × ctr_v  + danger × ctr_danger</li>
<li class="">heal    = heal_base + v × heal_v + danger × heal_danger</li>
</ul>
</li>
<li class="">
<p>訓練參數設定：</p>
<ul>
<li class=""><strong>族群大小</strong>：150 個個體</li>
<li class=""><strong>演化世代</strong>：1000 代</li>
<li class=""><strong>評估局數</strong>：每個體每世代評估 800 局</li>
<li class=""><strong>評分機制</strong>：勝利 = 1.0 分，平手 = 0.5 分，失敗 = 0 分</li>
<li class=""><strong>訓練對手</strong>：採用「隨機出牌」策略，這樣跑比較快（應該也比較不會 Overfitting？），不然用 MCTS 會訓練太久</li>
</ul>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="額外補強">額外補強<a href="https://til.trashposts.com/blog/dual-25#%E9%A1%8D%E5%A4%96%E8%A3%9C%E5%BC%B7" class="hash-link" aria-label="額外補強的直接連結" title="額外補強的直接連結" translate="no">​</a></h3>
<p>我最後再額外再加上「斬殺（lethal）」的概念。</p>
<ul>
<li class="">如果「反擊」或「攻擊」的數值高於對手的血量，則優先選擇斬殺（反擊優先）。</li>
<li class="">如果有多張牌能斬殺，優先選擇點數小的牌做斬殺。</li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[browser-sync 重複 reload 的解法]]></title>
            <link>https://til.trashposts.com/blog/browser-sync-reload-debounce</link>
            <guid>https://til.trashposts.com/blog/browser-sync-reload-debounce</guid>
            <pubDate>Mon, 23 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[上次在 更新網站產生器 的時候，有提到預覽功能 browser-sync 變得緩慢的問題。]]></description>
            <content:encoded><![CDATA[<p>上次在 <a class="" href="https://til.trashposts.com/blog/update-blog-engine">更新網站產生器</a> 的時候，有提到預覽功能 browser-sync 變得緩慢的問題。</p>
<p>今天才發現變慢的主因不是 build 產生太多檔案，而是因為偵測到太多檔案變動而不穩定。</p>
<p>一開始我改成偵測到檔案變動之後就去 build，然後產生一個 <code>.reload</code> 的檔案，裡面放 timestamp，這樣 browser-sync 只要去偵測這個檔案就可以了。</p>
<p>但是我也有一些檔案是不需要 build 的阿，這樣又要把路徑區分開來寫在 browser-sync，有點麻煩。</p>
<p>最後決定還是讓 browser-sync 偵測整個 public 資料夾，再加上兩個參數就解決了：</p>
<ul>
<li class=""><code>--reload-debounce 300</code>：等檔案變動安靜下來再 reload。</li>
<li class=""><code>--reload-delay 100</code>：多等一點時間再刷新，避免被連續事件打爆。</li>
</ul>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="20260225-微更新">2026/02/25 微更新<a href="https://til.trashposts.com/blog/browser-sync-reload-debounce#20260225-%E5%BE%AE%E6%9B%B4%E6%96%B0" class="hash-link" aria-label="2026/02/25 微更新的直接連結" title="2026/02/25 微更新的直接連結" translate="no">​</a></h3>
<p>還是限制一下範圍比較好，像是這樣：</p>
<div class="language-bat codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bat codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">--files "public/assets/**/*.css"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--files "public/assets/**/*.js"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--files "public/*.html"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">--files "content/**/*"</span><br></span></code></pre></div></div>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="筆記">筆記<a href="https://til.trashposts.com/blog/browser-sync-reload-debounce#%E7%AD%86%E8%A8%98" class="hash-link" aria-label="筆記的直接連結" title="筆記的直接連結" translate="no">​</a></h3>
<ul>
<li class=""><a class="" href="https://til.trashposts.com/notes/web/browser-sync-reload">browser-sync 網站預覽</a></li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[更新：部落格網站產生器]]></title>
            <link>https://til.trashposts.com/blog/update-blog-engine</link>
            <guid>https://til.trashposts.com/blog/update-blog-engine</guid>
            <pubDate>Tue, 10 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[前幾天在調整部落格時，有幾個痛點一直放著沒動，想說乾脆趁這個機會改一改。]]></description>
            <content:encoded><![CDATA[<p>前幾天在調整部落格時，有幾個痛點一直放著沒動，想說乾脆趁這個機會改一改。</p>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="痛點一">痛點一<a href="https://til.trashposts.com/blog/update-blog-engine#%E7%97%9B%E9%BB%9E%E4%B8%80" class="hash-link" aria-label="痛點一的直接連結" title="痛點一的直接連結" translate="no">​</a></h3>
<p>在生成器出現之前，我編輯的檔案跟最後部署的檔案是同一份，所以編輯時都是用 <code>browser-sync</code> 套件來預覽，只要按下儲存，網頁就會自動更新。</p>
<p>但是在生成器出現之後，如果我想要預覽新文章，就只能選這兩種方法：</p>
<ol>
<li class="">每次想要預覽就只要重新 build 整個網站。</li>
<li class="">暫時在 <code>index.html</code> 或 <code>preview.html</code> 寫新文章，等編輯到滿意之後再放到真正的文章檔案，然後再重新 build 一次。</li>
</ol>
<p>其實使用方法二也沒有多不方便，就是有點繞路而已。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="解法">解法<a href="https://til.trashposts.com/blog/update-blog-engine#%E8%A7%A3%E6%B3%95" class="hash-link" aria-label="解法的直接連結" title="解法的直接連結" translate="no">​</a></h3>
<ul>
<li class="">新增 <code>watch.php</code>，監聽 <code>content/articles</code> 與 <code>templates</code> 目錄變動，自動觸發 build。</li>
<li class="">接著再整合 <code>browser-sync</code>，只要有變動，就同步到瀏覽器上。</li>
</ul>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="痛點二">痛點二<a href="https://til.trashposts.com/blog/update-blog-engine#%E7%97%9B%E9%BB%9E%E4%BA%8C" class="hash-link" aria-label="痛點二的直接連結" title="痛點二的直接連結" translate="no">​</a></h3>
<p>生成器在執行 build 的時候，會把所有文章都重新生成一次，久了會導致 browser-sync 變得緩慢，而且還「沒有刪除功能」，需要自己檢查有沒有殘留的頁面。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="解法-1">解法<a href="https://til.trashposts.com/blog/update-blog-engine#%E8%A7%A3%E6%B3%95-1" class="hash-link" aria-label="解法的直接連結" title="解法的直接連結" translate="no">​</a></h3>
<p>這個老實說應該要分開做，正常來說應該是：</p>
<ol>
<li class="">build 是正式環境要用的，應該刪除整個資料夾，然後全部重新建構一次，這樣最安全。</li>
<li class="">dev 是當下預覽用的，第一次啟動要全部 build 一遍，接下來則是根據有變動的檔案去 build 就好。</li>
</ol>
<p>但我為求簡單，把它整合到一起了，而且 build 的時間基本上只有 0.1 秒，體感上幾乎感受不到。</p>
<ul>
<li class="">新增 Smart Write 機制，僅在檔案內容變動時才寫入，避免不必要的 I/O。</li>
<li class="">新增 cleanStaleFiles()，自動清理多餘的分頁資料夾與文章資料夾（透過 slug 比對）。</li>
<li class="">新增 summary()，建置完成後顯示更新的檔案列表。</li>
</ul>
<p>這樣的話，每次 build 雖然會掃過所有文章，但如果只有修改內文，實際上只會生成：</p>
<ol>
<li class="">首頁（或分頁）的文章內容</li>
<li class="">文章檔案（含資料夾）</li>
<li class=""><code>search.json</code></li>
<li class=""><code>rss.xml</code></li>
</ol>
<hr>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="痛點三">痛點三<a href="https://til.trashposts.com/blog/update-blog-engine#%E7%97%9B%E9%BB%9E%E4%B8%89" class="hash-link" aria-label="痛點三的直接連結" title="痛點三的直接連結" translate="no">​</a></h3>
<p>RSS 的 <code>lastBuildDate</code> 欄位每次 build 都會改成最後建置時間，但其實 RSS 內容完全沒變的時候是不需要上版的。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="解法-2">解法<a href="https://til.trashposts.com/blog/update-blog-engine#%E8%A7%A3%E6%B3%95-2" class="hash-link" aria-label="解法的直接連結" title="解法的直接連結" translate="no">​</a></h3>
<ul>
<li class="">RSS 的 <code>lastBuildDate</code> 改為最新文章發布日期，避免每次 build 的時候都變動。</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="新的發文流程">新的發文流程<a href="https://til.trashposts.com/blog/update-blog-engine#%E6%96%B0%E7%9A%84%E7%99%BC%E6%96%87%E6%B5%81%E7%A8%8B" class="hash-link" aria-label="新的發文流程的直接連結" title="新的發文流程的直接連結" translate="no">​</a></h2>
<ul>
<li class="">點兩下 <code>new-article.bat</code>，建立新文章模板，並且自動填入今天日期。</li>
<li class="">點兩下 <code>auto-sync.bat</code>，自動打開 <code>browser-sync</code> 跟 <code>watch.php</code>，編輯儲存的時候會同步顯示到瀏覽器上。</li>
<li class="">（Optional）保險一點，自己再 build 一次。</li>
<li class="">最後直接 commit + push 就行了。</li>
</ul>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[檔案傳送工具]]></title>
            <link>https://til.trashposts.com/blog/file-transfer-tools</link>
            <guid>https://til.trashposts.com/blog/file-transfer-tools</guid>
            <pubDate>Sat, 07 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[昨天晚上臨時有個「電腦→電腦」傳大檔案的需求，大概是 80 GB 左右，因為不是在區域網路，所以平常用的 LocalSend 派不上用場（後來發現可以搭配 Tailscale 來傳），透過雲端服務的話，檔案會太大不好上傳，而且也滿沒效率的。]]></description>
            <content:encoded><![CDATA[<p>昨天晚上臨時有個「電腦→電腦」傳大檔案的需求，大概是 80 GB 左右，因為不是在區域網路，所以平常用的 LocalSend 派不上用場（後來發現可以搭配 Tailscale 來傳），透過雲端服務的話，檔案會太大不好上傳，而且也滿沒效率的。</p>
<p>後來找到 Croc 跟 FilePizza 這兩種做法，我最後是選擇穩定好用的 Croc。</p>
<p>一開始我是用他們公用的 Relay 伺服器傳，但馬上就發現網路速度吃不滿，跑起來有點慢，看了文件之後發現可以自己架 Relay 伺服器，於是我就把我家 Router 的 NAT 轉址打開，直接用我的電腦來當 Relay 伺服器，這樣就可以把網路全部吃滿了。</p>
<blockquote>
<p>這裡要吐槽自己一下，既然有 Public IP + NAT，那架 FTP Server 或用 LocalSend 指向 IP 其實就可以用了嘛～</p>
</blockquote>
<p>這邊提一下，如果沒有辦法搞到 Public IP 或 NAT 轉址的話，也是有其他的做法的，像是可以把 Relay 伺服器架在 VPS 上面（但要注意流量限制），或者更好的選擇......用 Tailscale 啊！</p>
<p><strong>Tailscale 也太好用了吧！</strong><small>（久仰大名，但這其實是我第一次用，以前都沒機會用到 XD）</small></p>
<p>總之，結論如下：</p>
<ul>
<li class="">如果你是要自己傳給自己，內網 LocalSend，外網搭配 Tailscale 就很夠用了。</li>
<li class="">如果你臨時想要傳一些東西給別人，或者懶得裝軟體的話，就用 FilePizza。</li>
<li class="">如果你想要穩定傳大檔案，又剛好有終端機可以用的話，可以選 Croc，速度不夠的話再搭配 Tailscale 架 Relay 伺服器。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="使用情境">使用情境<a href="https://til.trashposts.com/blog/file-transfer-tools#%E4%BD%BF%E7%94%A8%E6%83%85%E5%A2%83" class="hash-link" aria-label="使用情境的直接連結" title="使用情境的直接連結" translate="no">​</a></h3>
<table><thead><tr><th>工具</th><th>網路環境</th><th>裝置</th><th>特點</th></tr></thead><tbody><tr><td><a href="https://localsend.org/" target="_blank" rel="noopener noreferrer" class="">LocalSend</a></td><td>區域網路</td><td>跨裝置</td><td>圖形介面、簡單易用</td></tr><tr><td><a href="https://file.pizza/" target="_blank" rel="noopener noreferrer" class="">FilePizza</a></td><td>跨網路</td><td>跨裝置</td><td>打開網頁就能用</td></tr><tr><td><a href="https://github.com/schollz/croc" target="_blank" rel="noopener noreferrer" class="">Croc</a></td><td>跨網路</td><td>電腦之間</td><td>大檔案、斷點續傳、自架 Relay</td></tr></tbody></table>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="筆記">筆記<a href="https://til.trashposts.com/blog/file-transfer-tools#%E7%AD%86%E8%A8%98" class="hash-link" aria-label="筆記的直接連結" title="筆記的直接連結" translate="no">​</a></h3>
<ul>
<li class=""><a class="" href="https://til.trashposts.com/notes/software/file-transfer">檔案傳送工具</a></li>
</ul>]]></content:encoded>
        </item>
    </channel>
</rss>