Standardize poet attributions and reformat blog template
Convert all poet attribution lines to use an em dash, English name format, and consistent spacing. Re-indent the blog single page template for readability and adjust the typewriter element layout.
This commit is contained in:
@@ -5,7 +5,7 @@ draft: false
|
||||
poet: |
|
||||
The mind is its own place, and in itself
|
||||
Can make a Heaven of Hell, a Hell of Heaven.
|
||||
——John Milton,英国,1608–1674
|
||||
— John Milton, UK, 1608–1674
|
||||
description: "2026 年 AI 工具进入务实阶段。实测 DeepSeek V4 Flash 和 Pro 模型的不同场景表现,Agent 智能体的四个落地方向,以及怎么用更少 token 做更多事。"
|
||||
tags:
|
||||
- AI
|
||||
|
||||
@@ -5,7 +5,7 @@ draft: false
|
||||
poet: |
|
||||
To see a World in a Grain of Sand
|
||||
And a Heaven in a Wild Flower
|
||||
——William Blake,英国,1757–1827
|
||||
— William Blake, UK, 1757–1827
|
||||
description: "Go concurrency beyond the basics. Worker pools for bounded parallelism, context propagation for cancellation, select loops for channel coordination — three patterns that hold up in production."
|
||||
tags:
|
||||
- Go
|
||||
|
||||
@@ -5,7 +5,7 @@ draft: false
|
||||
poet: |
|
||||
My house, my house, though you are small,
|
||||
You are a mansion to me after all.
|
||||
——Robert Herrick,英国,1591–1674
|
||||
— Robert Herrick, UK, 1591–1674
|
||||
description: "从默认 Gnome 到一套顺手的桌面环境。GTK 主题、图标包、终端配色、窗口管理器的选择与配置思路。不追求花哨,追求每天盯着看不累。"
|
||||
tags:
|
||||
- Linux
|
||||
|
||||
@@ -4,7 +4,7 @@ date: 2026-05-12T11:00:00+08:00
|
||||
draft: false
|
||||
poet: |
|
||||
They also serve who only stand and wait.
|
||||
——John Milton,英国,1608–1674
|
||||
— John Milton, UK, 1608–1674
|
||||
description: "Understanding the event loop, writing proper async context managers, and avoiding the most common pitfalls with asyncio.gather and cancel scopes."
|
||||
tags:
|
||||
- Python
|
||||
|
||||
@@ -4,7 +4,7 @@ date: 2026-05-13T09:00:00+08:00
|
||||
draft: false
|
||||
poet: |
|
||||
Form follows function.
|
||||
——Louis Sullivan,美国,1856–1924
|
||||
— Louis Sullivan, US, 1856–1924
|
||||
description: "Lessons from real-world API design. Why version early, paginate everything, standardize error responses, and add idempotency keys. Plus a practical deprecation strategy with Sunset headers."
|
||||
tags:
|
||||
- API
|
||||
|
||||
@@ -5,7 +5,7 @@ draft: false
|
||||
poet: |
|
||||
If you can meet with Triumph and Disaster
|
||||
And treat those two impostors just the same;
|
||||
——Rudyard Kipling,英国,1865–1936
|
||||
— Rudyard Kipling, UK, 1865–1936
|
||||
description: "The journey from panic-driven development to proper error types. When to use thiserror for library crates and anyhow for applications."
|
||||
tags:
|
||||
- Rust
|
||||
|
||||
@@ -5,7 +5,7 @@ draft: false
|
||||
poet: |
|
||||
Do not go gentle into that good night.
|
||||
Rage, rage against the dying of the light.
|
||||
——Dylan Thomas,英国,1914–1953
|
||||
— Dylan Thomas, UK, 1914–1953
|
||||
description: "试用了 Svelte 5 的 runes 语法和 SvelteKit 框架。没有虚拟 DOM,编译时直接把组件转成 DOM 操作代码,打包体积小得惊人。"
|
||||
tags:
|
||||
- Svelte
|
||||
|
||||
@@ -7,7 +7,7 @@ poet: |
|
||||
your work need not be lost;
|
||||
that is where they should be.
|
||||
Now put the foundations under them.
|
||||
——Henry David Thoreau,美国,1817–1862
|
||||
— Henry David Thoreau, US, 1817–1862
|
||||
description: "Infrastructure as code from scratch: VPC, subnets, security groups, ECR repository, ECS service with Fargate, and an ALB in front. Every resource explained."
|
||||
tags:
|
||||
- AWS
|
||||
|
||||
@@ -5,7 +5,7 @@ draft: false
|
||||
poet: |
|
||||
Practice does not make perfect.
|
||||
Only perfect practice makes perfect.
|
||||
——Vince Lombardi,美国,1913–1970
|
||||
— Vince Lombardi, US, 1913–1970
|
||||
description: "Which Vim motions are worth the muscle memory investment? A practical three-tier ranking from non-negotiable (ci, %, dot) to nice-to-have (macros, jump list), based on three years of daily use."
|
||||
tags:
|
||||
- Vim
|
||||
|
||||
+146
-74
@@ -1,82 +1,154 @@
|
||||
{{ define "main" }}
|
||||
<div class="hx:mx-auto hx:flex hextra-max-page-width">
|
||||
{{ partial "sidebar.html" (dict "context" . "disableSidebar" true "displayPlaceholder" true) }}
|
||||
{{ partial "toc.html" . }}
|
||||
<article class="hx:w-full hx:break-words hx:flex hx:min-h-[calc(100vh-var(--navbar-height))] hx:min-w-0 hx:justify-center hx:pb-8 hx:pr-[calc(env(safe-area-inset-right)-1.5rem)]">
|
||||
<main id="content" class="hx:w-full hx:min-w-0 hextra-max-content-width hx:px-6 hx:pt-0 hx:md:px-12">
|
||||
{{ partial "breadcrumb.html" (dict "page" . "enable" true) }}
|
||||
{{ if .Title }}
|
||||
<div class="hx:flex hx:flex-col hx:sm:flex-row hx:items-start hx:sm:items-center hx:sm:justify-between hx:gap-4 hx:mt-2">
|
||||
<h1 class="hx:mb-0 hx:text-4xl hx:font-bold hx:tracking-tight hx:text-slate-900 hx:dark:text-slate-100">{{ .Title }}</h1>
|
||||
{{ partial "components/page-context-menu" . }}
|
||||
</div>
|
||||
{{ end }}
|
||||
<div class="hx:mt-4 hx:mb-16 hx:text-gray-500 hx:dark:text-gray-400 hx:text-sm hx:flex hx:items-center hx:flex-wrap hx:gap-y-2">
|
||||
{{- with $date := .Date }}<span class="hx:mr-1">{{ partial "utils/format-date" $date }}</span>{{ end -}}
|
||||
{{- $lazyLoading := site.Params.enableImageLazyLoading | default true -}}
|
||||
{{ if and .Date .Params.authors }}<span class="hx:mx-1">·</span>{{ end -}}
|
||||
{{- with $.Params.authors -}}
|
||||
{{- range $i, $author := . -}}
|
||||
{{- if reflect.IsMap $author -}}
|
||||
{{- if and $i (not $author.image) }}<span class="hx:mr-1">,</span>{{ end -}}
|
||||
<a
|
||||
{{ with $author.link }}href="{{ . }}" target="_blank"{{ end }}
|
||||
class="hx:group hx:inline-flex hx:items-center hx:text-current hx:gap-x-1.5 hx:mx-1"
|
||||
{{ with $author.name }}title="{{ . }}"{{ end }}
|
||||
<div class="hx:mx-auto hx:flex hextra-max-page-width">
|
||||
{{ partial "sidebar.html" (dict "context" . "disableSidebar" true
|
||||
"displayPlaceholder" true) }} {{ partial "toc.html" . }}
|
||||
<article
|
||||
class="hx:w-full hx:break-words hx:flex hx:min-h-[calc(100vh-var(--navbar-height))] hx:min-w-0 hx:justify-center hx:pb-8 hx:pr-[calc(env(safe-area-inset-right)-1.5rem)]"
|
||||
>
|
||||
<main
|
||||
id="content"
|
||||
class="hx:w-full hx:min-w-0 hextra-max-content-width hx:px-6 hx:pt-0 hx:md:px-12"
|
||||
>
|
||||
{{ partial "breadcrumb.html" (dict "page" . "enable" true) }} {{ if
|
||||
.Title }}
|
||||
<div
|
||||
class="hx:flex hx:flex-col hx:sm:flex-row hx:items-start hx:sm:items-center hx:sm:justify-between hx:gap-4 hx:mt-2"
|
||||
>
|
||||
<h1
|
||||
class="hx:mb-0 hx:text-4xl hx:font-bold hx:tracking-tight hx:text-slate-900 hx:dark:text-slate-100"
|
||||
>
|
||||
{{- with $image := $author.image }}
|
||||
{{- $isLocal := not (urls.Parse $image).Scheme -}}
|
||||
{{- $startsWithSlash := hasPrefix $image "/" -}}
|
||||
{{- if and $isLocal $startsWithSlash }}
|
||||
{{- $image = (relURL (strings.TrimPrefix "/" $image)) -}}
|
||||
{{ .Title }}
|
||||
</h1>
|
||||
{{ partial "components/page-context-menu" . }}
|
||||
</div>
|
||||
{{ end }}
|
||||
<div
|
||||
class="hx:mt-4 hx:mb-16 hx:text-gray-500 hx:dark:text-gray-400 hx:text-sm hx:flex hx:items-center hx:flex-wrap hx:gap-y-2"
|
||||
>
|
||||
{{- with $date := .Date }}<span class="hx:mr-1"
|
||||
>{{ partial "utils/format-date" $date }}</span
|
||||
>{{ end -}} {{- $lazyLoading :=
|
||||
site.Params.enableImageLazyLoading | default true -}} {{ if and
|
||||
.Date .Params.authors }}<span class="hx:mx-1">·</span>{{ end -}}
|
||||
{{- with $.Params.authors -}} {{- range $i, $author := . -}} {{-
|
||||
if reflect.IsMap $author -}} {{- if and $i (not $author.image)
|
||||
}}<span class="hx:mr-1">,</span>{{ end -}}
|
||||
<a
|
||||
{{
|
||||
with
|
||||
$author.link
|
||||
}}href="{{ . }}"
|
||||
target="_blank"
|
||||
{{
|
||||
end
|
||||
}}
|
||||
class="hx:group hx:inline-flex hx:items-center hx:text-current hx:gap-x-1.5 hx:mx-1"
|
||||
{{
|
||||
with
|
||||
$author.name
|
||||
}}title="{{ . }}"
|
||||
{{
|
||||
end
|
||||
}}
|
||||
>
|
||||
{{- with $image := $author.image }} {{- $isLocal := not
|
||||
(urls.Parse $image).Scheme -}} {{- $startsWithSlash :=
|
||||
hasPrefix $image "/" -}} {{- if and $isLocal
|
||||
$startsWithSlash }} {{- $image = (relURL (strings.TrimPrefix
|
||||
"/" $image)) -}} {{ end -}}
|
||||
<img
|
||||
src="{{ $image | safeURL }}"
|
||||
alt="{{ $author.name }}"
|
||||
class="hx:inline-block hx:h-4 hx:w-4 hx:rounded-full"
|
||||
{{
|
||||
if
|
||||
$lazyLoading
|
||||
}}loading="lazy"
|
||||
{{
|
||||
end
|
||||
}}
|
||||
/>
|
||||
{{ end -}}
|
||||
<img src="{{ $image | safeURL }}" alt="{{ $author.name }}" class="hx:inline-block hx:h-4 hx:w-4 hx:rounded-full" {{ if $lazyLoading }}loading="lazy"{{ end }} />
|
||||
{{ end -}}
|
||||
<div class="hx:group-hover:underline">{{ $author.name }}</div>
|
||||
<div class="hx:group-hover:underline">
|
||||
{{ $author.name }}
|
||||
</div>
|
||||
</a>
|
||||
{{- else -}}
|
||||
{{- if $i }}<span class="hx:mr-1">,</span>{{ end -}}<span class="hx:mx-1">{{ $author }}</span>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
</div>
|
||||
<div class="content">
|
||||
{{ .Content }}
|
||||
{{- else -}} {{- if $i }}<span class="hx:mr-1">,</span>{{ end
|
||||
-}}<span class="hx:mx-1">{{ $author }}</span>
|
||||
{{- end -}} {{- end -}} {{- end -}}
|
||||
</div>
|
||||
<div class="content">
|
||||
{{ .Content }} {{- with .Params.poet }}
|
||||
<div
|
||||
id="typewriter-box"
|
||||
style="opacity:0;transition:opacity .6s;margin-top:1.5em"
|
||||
>
|
||||
<p id="typewriter-text"></p>
|
||||
</div>
|
||||
<script>
|
||||
(function () {
|
||||
var all = `{{ . }}`;
|
||||
var i = 0,
|
||||
del = false,
|
||||
dc = 0;
|
||||
var te = document.getElementById("typewriter-text");
|
||||
var box = document.getElementById("typewriter-box");
|
||||
if (!te || !box) return;
|
||||
var obs = new IntersectionObserver(
|
||||
function (e) {
|
||||
if (e[0].isIntersecting) {
|
||||
box.style.opacity = "1";
|
||||
obs.disconnect();
|
||||
go();
|
||||
}
|
||||
},
|
||||
{ rootMargin: "120px" },
|
||||
);
|
||||
obs.observe(box);
|
||||
function go() {
|
||||
setTimeout(
|
||||
function () {
|
||||
if (
|
||||
!del &&
|
||||
Math.random() < 0.1 &&
|
||||
i > 8 &&
|
||||
all.charAt(i - 1) !== "\n"
|
||||
) {
|
||||
del = true;
|
||||
dc = Math.floor(Math.random() * 4) + 1;
|
||||
}
|
||||
if (del) {
|
||||
i = Math.max(0, i - 1);
|
||||
dc--;
|
||||
if (
|
||||
dc <= 0 ||
|
||||
i === 0 ||
|
||||
all.charAt(i - 1) === "\n"
|
||||
)
|
||||
del = false;
|
||||
} else {
|
||||
if (i < all.length) i++;
|
||||
}
|
||||
te.textContent = all.substring(0, i);
|
||||
if (i < all.length || del) go();
|
||||
},
|
||||
del
|
||||
? 55 + Math.random() * 30
|
||||
: 70 + Math.random() * 100,
|
||||
);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
{{- with .Params.poet }}
|
||||
<div id="typewriter-box" style="opacity:0;transition:opacity .6s">
|
||||
<p id="typewriter-text"></p>
|
||||
</div>
|
||||
<script>
|
||||
(function(){
|
||||
var all=`{{ . }}`;
|
||||
var i=0,del=false,dc=0;
|
||||
var te=document.getElementById("typewriter-text");
|
||||
var box=document.getElementById("typewriter-box");
|
||||
if(!te||!box)return;
|
||||
var obs=new IntersectionObserver(function(e){
|
||||
if(e[0].isIntersecting){box.style.opacity="1";obs.disconnect();go()}
|
||||
},{rootMargin:"120px"});obs.observe(box);
|
||||
function go(){setTimeout(function(){
|
||||
if(!del&&Math.random()<0.1&&i>8&&all.charAt(i-1)!=="\n"){del=true;dc=Math.floor(Math.random()*4)+1}
|
||||
if(del){i=Math.max(0,i-1);dc--;if(dc<=0||i===0||all.charAt(i-1)==="\n")del=false}
|
||||
else{if(i<all.length)i++}
|
||||
te.textContent=all.substring(0,i);
|
||||
if(i<all.length||del)go()
|
||||
},del?55+Math.random()*30:70+Math.random()*100)}
|
||||
})();
|
||||
</script>
|
||||
{{- end }}
|
||||
</div>
|
||||
|
||||
{{- end }}
|
||||
</div>
|
||||
|
||||
{{- partial "components/last-updated.html" . -}}
|
||||
{{- if (site.Params.blog.article.displayPagination | default true) -}}
|
||||
{{- .Store.Set "reversePagination" (.Params.reversePagination | default true) -}}
|
||||
{{- partial "components/pager.html" . -}}
|
||||
{{ end }}
|
||||
{{- partial "components/comments.html" . -}}
|
||||
</main>
|
||||
{{- partial "components/last-updated.html" . -}} {{- if
|
||||
(site.Params.blog.article.displayPagination | default true) -}} {{-
|
||||
.Store.Set "reversePagination" (.Params.reversePagination | default
|
||||
true) -}} {{- partial "components/pager.html" . -}} {{ end }} {{-
|
||||
partial "components/comments.html" . -}}
|
||||
</main>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
Reference in New Issue
Block a user