<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title>照烧鳗鱼</title><link href="https://blog.zhaoshaomanyu.com/" rel="alternate"/><link href="https://blog.zhaoshaomanyu.com/feeds/all.atom.xml" rel="self"/><id>https://blog.zhaoshaomanyu.com/</id><updated>2026-09-12T11:25:00+08:00</updated><entry><title>交互发布助手使用指南</title><link href="https://blog.zhaoshaomanyu.com/2026/09/12/blog-publisher-guide/" rel="alternate"/><published>2026-09-12T11:25:00+08:00</published><updated>2026-09-12T11:25:00+08:00</updated><author><name>照烧鳗鱼</name></author><id>tag:blog.zhaoshaomanyu.com,2026-09-12:/2026/09/12/blog-publisher-guide/</id><summary type="html">&lt;p&gt;介绍如何在桌面使用交互式发布网页，实现所见即所得的双栏实时预览与一键原子部署。&lt;/p&gt;</summary><content type="html">&lt;div class="post__content"&gt;
&lt;h2 id="_1"&gt;交互发布助手的诞生&lt;/h2&gt;
&lt;p&gt;为了让日常写作更加流畅、无感，我们在桌面打造了一款轻量交互发布助手。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“极简的创作环境，是持续深度思考的最佳催化剂。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="_2"&gt;核心体验亮点&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;桌面一键即开&lt;/strong&gt;：双击桌面图标即可打开沉浸式双栏工作区。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;100% 真实线上还原&lt;/strong&gt;：右侧实时调用 Anatole 模板渲染，字号、边栏、图标与线上完全一致。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;一键原子上传&lt;/strong&gt;：点击“提交发布”后，全自动完成校验、编译、媒体同步与服务器软链秒切。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# 优雅发布体验&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;publish_thought&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;preview&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deploy_to_world&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;</content><category term="思考随笔"/><category term="Pelican"/><category term="写作"/><category term="发布助手"/></entry><entry><title>Canvas 粒子引力与动态连线实验</title><link href="https://blog.zhaoshaomanyu.com/2026/09/12/canvas-particle-physics-network/" rel="alternate"/><published>2026-09-12T08:00:00+08:00</published><updated>2026-09-12T08:00:00+08:00</updated><author><name>照烧鳗鱼</name></author><id>tag:blog.zhaoshaomanyu.com,2026-09-12:/2026/09/12/canvas-particle-physics-network/</id><summary type="html">&lt;p&gt;基于原生 HTML5 Canvas 构建的高性能粒子物理网络模拟，支持鼠标引力/排斥交互、连线距离调节与发散脉冲。&lt;/p&gt;</summary><content type="html">&lt;div class="demo-embed-card"&gt;
&lt;div class="demo-embed-header"&gt;
&lt;span&gt;交互预览 (Interactive Demo)&lt;/span&gt;
&lt;div class="project-actions"&gt;
&lt;a class="btn-anatole" href="https://blog.zhaoshaomanyu.com/demos/interactive-calc/" rel="noopener" target="_blank"&gt;全屏体验 ↗&lt;/a&gt;
&lt;a class="btn-anatole" href="/downloads/interactive-calc.zip" rel="noopener" target="_blank"&gt;查看源码 →&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="demo-iframe-wrapper"&gt;
&lt;iframe loading="lazy" sandbox="allow-scripts allow-same-origin" src="https://blog.zhaoshaomanyu.com/demos/interactive-calc/" title="Canvas 粒子引力与动态连线实验"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="post__content"&gt;
&lt;p&gt;这是一个完全使用现代原生 Web 技术（HTML5 Canvas + 纯 JavaScript）构建的轻量级物理仿真交互项目。&lt;/p&gt;
&lt;h2 id="_1"&gt;项目亮点与特性&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;零外部框架依赖&lt;/strong&gt;：整个演示不引入任何庞大的三方库（无需 Three.js、Pixi.js 等），完全使用浏览器 2D Canvas Context 驱动，加载耗时不到 10 毫秒。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;物理交互响应&lt;/strong&gt;：&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;鼠标排斥/引力&lt;/strong&gt;：当鼠标在画布上滑动时，周围半径内的粒子会受到速度冲量并发生偏移；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动态网状连线&lt;/strong&gt;：实时计算每两个粒子之间的欧几里得距离，在设定的阈值范围内绘制半透明连线，随距离拉远自然淡出；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;脉冲爆炸效果&lt;/strong&gt;：点击顶部控制栏的“发散脉冲”按钮，所有粒子将从中心点向外围施加径向冲击波。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;独立目录与沙箱隔离&lt;/strong&gt;：
该演示的源码保存在 &lt;code&gt;content/demos/interactive-calc/&lt;/code&gt; 下，Pelican 配置了 &lt;code&gt;ARTICLE_EXCLUDES&lt;/code&gt; 确保其不被篡改为博客文章；通过 &lt;code&gt;iframe&lt;/code&gt; 嵌入本页展示，完全不影响外部排版样式。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="_2"&gt;源码与离线运行包&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;全屏独立体验&lt;/strong&gt;：&lt;a href="/demos/interactive-calc/"&gt;点击此处全屏打开演示&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;离线源码下载&lt;/strong&gt;：&lt;a href="/downloads/interactive-calc.zip"&gt;下载项目完整 Zip 源码包&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;你可以直接解压该 zip 包，在任意电脑上双击其中的 &lt;code&gt;index.html&lt;/code&gt; 即可在本地离线运行。&lt;/p&gt;
&lt;/div&gt;</content><category term="projects"/><category term="Canvas"/><category term="JavaScript"/><category term="动画"/><category term="交互项目"/></entry><entry><title>原生音频播放与分段加载技术实践</title><link href="https://blog.zhaoshaomanyu.com/2026/09/12/native-audio-playback-in-pelican/" rel="alternate"/><published>2026-09-12T08:00:00+08:00</published><updated>2026-09-12T08:00:00+08:00</updated><author><name>照烧鳗鱼</name></author><id>tag:blog.zhaoshaomanyu.com,2026-09-12:/2026/09/12/native-audio-playback-in-pelican/</id><summary type="html">&lt;p&gt;探讨在静态博客中如何使用浏览器原生 HTML5 Audio 标签播放音频，并配合 Nginx HTTP Range 206 实现秒级拖拽与流畅播放。&lt;/p&gt;</summary><content type="html">&lt;div class="post__content"&gt;
&lt;p&gt;在个人博客中分享播客单集、音乐片段或语音随笔时，许多人习惯直接嵌入第三方商业播放器平台的小挂件。然而，第三方挂件往往包含冗余的脚本、广告、跟踪代码，且加载缓慢。&lt;/p&gt;
&lt;p&gt;其实，现代浏览器的 HTML5 &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; 标签已经非常强大，结合 HTTP Range 206 请求，即可实现体验极佳的原生音频播放。&lt;/p&gt;
&lt;h2 id="_1"&gt;原生音频播放体验&lt;/h2&gt;
&lt;p&gt;下面嵌入了一段通过 FFmpeg 生成的标准 44.1kHz / 320kbps MP3 样例音频：&lt;/p&gt;
&lt;div class="media-container"&gt;
&lt;audio controls="" preload="metadata"&gt;
&lt;source src="/media/sample-audio.mp3" type="audio/mpeg"/&gt;
您的浏览器不支持原生 HTML5 音频播放，请下载后播放。
&lt;/audio&gt;
&lt;div class="media-caption"&gt;
音频来源：&lt;code&gt;/media/sample-audio.mp3&lt;/code&gt; | 支持快进、倒退、拖拽进度条
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="_2"&gt;实现原理与服务器配置要点&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;为什么不需要第三方 JS 库&lt;/strong&gt;：
原生的 &lt;code&gt;&amp;lt;audio controls&amp;gt;&lt;/code&gt; 体积为 0 KB，无需执行任何臃肿的 JS 逻辑，手机与电脑均能调用系统级解码芯片，省电且响应迅速。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP Range 支持 (Status 206 Partial Content)&lt;/strong&gt;：
当你在播放器中拖动进度条时，浏览器会自动发送带 &lt;code&gt;Range: bytes=start-end&lt;/code&gt; 请求头。Nginx 静态文件服务器原生支持 Range 响应，返回 &lt;code&gt;206 Partial Content&lt;/code&gt;，无需下载整首音频即可从任意位置瞬间开始播放。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;独立媒体存储策略&lt;/strong&gt;：
媒体文件存放在独立的 &lt;code&gt;/media/&lt;/code&gt; 目录下，与每次发布网站页面的 &lt;code&gt;releases/&lt;/code&gt; 隔离，避免每次部署博客时重复全量上传大型媒体。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下载备用链接：&lt;a href="/media/sample-audio.mp3"&gt;点击下载音频文件&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</content><category term="媒体实验"/><category term="音频"/><category term="Web技术"/><category term="HTML5"/><category term="媒体"/></entry><entry><title>编写可靠的自动化构建与原子发布脚本</title><link href="https://blog.zhaoshaomanyu.com/2026/09/12/reliable-build-and-atomic-publish-scripts/" rel="alternate"/><published>2026-09-12T08:00:00+08:00</published><updated>2026-09-12T08:00:00+08:00</updated><author><name>照烧鳗鱼</name></author><id>tag:blog.zhaoshaomanyu.com,2026-09-12:/2026/09/12/reliable-build-and-atomic-publish-scripts/</id><summary type="html">&lt;p&gt;详细展示如何通过 Python 与 Shell 构建支持版本目录 (Releases)、无缝软链接切换 (Symlink) 与状态回滚的静态博客部署机制。&lt;/p&gt;</summary><content type="html">&lt;div class="post__content"&gt;
&lt;p&gt;在部署静态网站时，最危险的操作莫过于直接在生产根目录执行带有 &lt;code&gt;--delete&lt;/code&gt; 参数的 &lt;code&gt;rsync&lt;/code&gt;。一旦构建损坏或网络在上传中间断开，访问者就会看到残缺不全甚至完全空白的网页。&lt;/p&gt;
&lt;p&gt;本文演示一种简单、安全且广泛应用于专业工业界的&lt;strong&gt;原子软链接发布模型 (Atomic Symlink Deployment)&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="1-shell"&gt;1. 核心发布流程 (Shell)&lt;/h2&gt;
&lt;p&gt;以下是自动化发布脚本 &lt;code&gt;publish.sh&lt;/code&gt; 的关键部分：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-euo&lt;span class="w"&gt; &lt;/span&gt;pipefail
&lt;span class="c1"&gt;# 1. 严格预检查&lt;/span&gt;
./scripts/check.sh
&lt;span class="c1"&gt;# 2. 生产环境构建&lt;/span&gt;
pelican&lt;span class="w"&gt; &lt;/span&gt;content&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;publishconf.py
&lt;span class="c1"&gt;# 3. 创建带时间戳的版本目录并上传&lt;/span&gt;
&lt;span class="nv"&gt;RELEASE_TAG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;+&lt;span class="s2"&gt;"%Y%m%d%H%M%S"&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;REMOTE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/www/pelican-blog"&lt;/span&gt;
ssh&lt;span class="w"&gt; &lt;/span&gt;dmit&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mkdir -p &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REMOTE_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/releases/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RELEASE_TAG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
rsync&lt;span class="w"&gt; &lt;/span&gt;-avz&lt;span class="w"&gt; &lt;/span&gt;--delete&lt;span class="w"&gt; &lt;/span&gt;output/&lt;span class="w"&gt; &lt;/span&gt;dmit:&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REMOTE_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/releases/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RELEASE_TAG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/
&lt;span class="c1"&gt;# 4. 原子符号链接切换 (Atomic Symlink Switch)&lt;/span&gt;
ssh&lt;span class="w"&gt; &lt;/span&gt;dmit&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ln -sfn &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REMOTE_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/releases/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RELEASE_TAG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REMOTE_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/current_tmp &amp;amp;&amp;amp; \&lt;/span&gt;
&lt;span class="s2"&gt; mv -Tf &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REMOTE_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/current_tmp &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REMOTE_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/current"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"==&amp;gt; 部署成功！当前版本: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RELEASE_TAG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="2-python"&gt;2. 静态死链与草稿校验器 (Python)&lt;/h2&gt;
&lt;p&gt;为了防止未完成的草稿（&lt;code&gt;Status: draft&lt;/code&gt;）或者拼写错误的图片链接泄露到线上，我们在构建前使用检查器进行扫描：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;verify_markdown_posts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="n"&gt;has_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content_dir&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s1"&gt;'.md'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.markdown'&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
&lt;span class="k"&gt;continue&lt;/span&gt;
&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# 校验必需元数据&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Title:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Date:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Slug:'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;rf&lt;/span&gt;&lt;span class="s1"&gt;'^&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MULTILINE&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"[Error] &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 缺少必要元数据: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;has_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;has_error&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;verify_markdown_posts&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"[OK] 内容元数据校验通过"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="3-css"&gt;3. 前端交互与隔离样式 (CSS)&lt;/h2&gt;
&lt;p&gt;为了保证代码块在移动端屏幕上不会把整个页面撑爆产生横向滚动条，代码块内部必须显式声明横向自适应滚动：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;pre&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;--nc-bg-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;solid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;--nc-border&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="kt"&gt;rem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="kt"&gt;rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;overflow-x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="kt"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.45&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;code&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ui-monospace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SFMono-Regular&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Menlo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Monaco&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Consolas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;monospace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;代码高亮由 Pelican 自带的 Pygments 预渲染生成，无需在客户端运行庞大的 JS 语法解析器，省电且速度极快。&lt;/p&gt;
&lt;/div&gt;</content><category term="工程开发"/><category term="Python"/><category term="运维"/><category term="自动化"/><category term="代码展示"/></entry><entry><title>响应式视频与浏览器原生硬件解码实践</title><link href="https://blog.zhaoshaomanyu.com/2026/09/12/responsive-video-streaming-practice/" rel="alternate"/><published>2026-09-12T08:00:00+08:00</published><updated>2026-09-12T08:00:00+08:00</updated><author><name>照烧鳗鱼</name></author><id>tag:blog.zhaoshaomanyu.com,2026-09-12:/2026/09/12/responsive-video-streaming-practice/</id><summary type="html">&lt;p&gt;演示如何使用符合通用工业标准的 H.264/AAC MP4 视频，借助原生 HTML5 Video 标签实现全平台无缝硬件解码与时间轴任意拖动。&lt;/p&gt;</summary><content type="html">&lt;div class="post__content"&gt;
&lt;p&gt;在移动设备与现代高分辨率屏幕上展示自制视频片段时，选择合适的编码容器与 HTML 标签属性至关重要。&lt;/p&gt;
&lt;h2 id="_1"&gt;原生视频演示&lt;/h2&gt;
&lt;p&gt;下方是一个标准的 H.264（Baseline/High profile）+ AAC 音频流 MP4 视频样本。它在 iOS Safari、Android Chrome、macOS 及 Windows 均能自动激活硬件加速：&lt;/p&gt;
&lt;div class="media-container"&gt;
&lt;video controls="" playsinline="" poster="/images/headshot.jpg" preload="metadata"&gt;
&lt;source src="/media/sample-video.mp4" type="video/mp4"/&gt;
您的浏览器不支持 HTML5 原生视频播放。
&lt;/video&gt;
&lt;div class="media-caption"&gt;
视频格式：MP4 (H.264 / AAC) | 包含 playsinline 属性，防止移动端强制全屏脱焦
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="_2"&gt;移动端与编码关键注意点&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;playsinline&lt;/code&gt; 属性不可忽略&lt;/strong&gt;：
在 iPhone Safari 浏览器中，如果没有这个属性，点击播放往往会被操作系统强行拉起全屏独占播放器，打断页面阅读心流。加上 &lt;code&gt;playsinline&lt;/code&gt; 可以实现内嵌原地流畅播放。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;preload="metadata"&lt;/code&gt; 节约带宽&lt;/strong&gt;：
对于单篇文章包含多个视频的情况，默认设置为 &lt;code&gt;metadata&lt;/code&gt;。浏览器只会提前拉取视频时长、尺寸和首帧关键信息，不会提前把几十兆的视频流全量缓冲进来，极大地节省了访客流量与服务器带宽。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP Range 支持&lt;/strong&gt;：
拖动视频进度条同样依赖 Web 服务器的 Range 206 响应。经测试，无论是在 Chrome 还是 Safari 中拖到任意时间点，均可秒级响应解码。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如遇到网络限制，您亦可直接通过备用链接获取：&lt;a href="/media/sample-video.mp4"&gt;下载原始视频&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</content><category term="媒体实验"/><category term="视频"/><category term="H.264"/><category term="MP4"/><category term="响应式"/></entry><entry><title>极简主义设计与静态网站的回归</title><link href="https://blog.zhaoshaomanyu.com/2026/09/12/return-of-minimalist-static-sites/" rel="alternate"/><published>2026-09-12T08:00:00+08:00</published><updated>2026-09-12T08:00:00+08:00</updated><author><name>照烧鳗鱼</name></author><id>tag:blog.zhaoshaomanyu.com,2026-09-12:/2026/09/12/return-of-minimalist-static-sites/</id><summary type="html">&lt;p&gt;为什么在重型动态应用与复杂前端框架盛行的今天，以阅读为中心、轻量快速的静态博客依然具有无可替代的生命力。&lt;/p&gt;</summary><content type="html">&lt;div class="post__content"&gt;
&lt;p&gt;在这个动态应用框架、微前端和实时数据库盛行的时代，建立一个个人网站变得比以往任何时候都更加容易，但也变得异常臃肿。往往加载数十个庞大的 JavaScript 包、几十个跟踪脚本之后，访客才能看到几段纯文本内容。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“做减法往往比做加法更需要克制。当一个网站完全服务于文字本身，阅读才会重新成为一件纯粹而愉悦的事情。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="_1"&gt;为什么选择静态生成器？&lt;/h2&gt;
&lt;p&gt;回归静态生成（如 Pelican、Hugo 等），核心收益在于三个维度：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;极致的访问速度&lt;/strong&gt;：编译出的文件是纯 HTML/CSS，首屏几乎在浏览器发出网络请求的瞬间即刻呈现（毫秒级）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;零维护与绝对安全&lt;/strong&gt;：没有后端 MySQL、PHP 解释器或常驻进程，从物理层面上杜绝了 SQL 注入与远程代码执行漏洞。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;内容即代码 (Content as Code)&lt;/strong&gt;：所有文章都以纯 Markdown 格式保存在本地，通过 Git 做版本追踪与管理。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="_2"&gt;常用静态方案对比&lt;/h2&gt;
&lt;p&gt;我们可以通过下面的对比表格看清不同方案的取舍：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;方案&lt;/th&gt;
&lt;th style="text-align: left;"&gt;语言生态&lt;/th&gt;
&lt;th style="text-align: left;"&gt;优势&lt;/th&gt;
&lt;th style="text-align: left;"&gt;适用场景&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Pelican&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Python / Jinja2&lt;/td&gt;
&lt;td style="text-align: left;"&gt;架构精炼，纯文本原生解析，插件信号完善&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Pythonista、极客、独立博客&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Hugo&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Go&lt;/td&gt;
&lt;td style="text-align: left;"&gt;构建速度极快（千页秒级），二进制分发&lt;/td&gt;
&lt;td style="text-align: left;"&gt;超大规模文档站点&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;&lt;strong&gt;Astro&lt;/strong&gt;&lt;/td&gt;
&lt;td style="text-align: left;"&gt;JavaScript / Node&lt;/td&gt;
&lt;td style="text-align: left;"&gt;组件化、部分激活 (Islands)&lt;/td&gt;
&lt;td style="text-align: left;"&gt;现代多组件交互前端&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="_3"&gt;未来的计划&lt;/h2&gt;
&lt;p&gt;这个小站将作为我长期记录技术探索、交互设计与日常学习心得的根据地。欢迎通过 RSS / Atom 订阅更新，或在关于页面找到我的联系方式与我交流。&lt;/p&gt;
&lt;/div&gt;</content><category term="思考随笔"/><category term="静态网站"/><category term="设计"/><category term="极简主义"/><category term="Pelican"/></entry></feed>