
Ljg Library
- 1.8k installs
- 6.7k repo stars
- Updated August 4, 2026
- lijigang/ljg-skills
ljg-library is an agent skill that 一本书 → 一幅清晰的「取景框」意向画面 → 一张 2050 图书馆借书卡(png)。取景框 = 作者从哪个角度看什么问题、看到了哪幅画面;卡上有真实封面、作者头像、书目信息。取景框 block 用费曼式讲解把这幅意向画面讲得通俗又准确,图解 block 白底黑墨手绘风、精确呈现该意向画面让人一眼即懂(画面里本来有「你」才嵌继刚墨像,否则只画画面)。浅色光学玻璃风、卡
About
ljg-library is an agent skill from lijigang/ljg-skills that 一本书 → 一幅清晰的「取景框」意向画面 → 一张 2050 图书馆借书卡(png)。取景框 = 作者从哪个角度看什么问题、看到了哪幅画面;卡上有真实封面、作者头像、书目信息。取景框 block 用费曼式讲解把这幅意向画面讲得通俗又准确,图解 block 白底黑墨手绘风、精确呈现该意向画面让人一眼即懂(画面里本来有「你」才嵌继刚墨像,否则只画画面)。浅色光学玻璃风、卡身强调色从封面动态提取、宽高自. # ljg-library:取景框借书卡 一本书,铸成一张 2050 图书馆借书卡。封面、作者、书目是身份;**核心是把这本书独创的「取景框」压成一幅意向画面**——作者从某个角度看某个问题,看到了一幅别人没看到的画面。文字 block 用费曼式把这幅画面讲透,图形 block 把它精确画出来。合上书半年后,瞥一眼这张卡,那幅画面回来——这是「没白读」的物证。 > 图解 block 用手绘解释的风格、白底黑墨,**精确呈现意向画面**;继刚墨像(`assets/ljg-portrait.png`,由其头像抠底而成)是可选构图件,仅当画面里本来有个「你」才嵌入。完整设计历程见 `~/.claude/PAI/MEMORY/WORK/ljg-oneliner-design/ISA.md`。 Developers invoke ljg-library during build/integrations work for ai & agent building tasks. The skill documents triggers, prerequisites, and step-by-step workflows grounded in SKILL.md. Compatible with Claude Code, Cursor, and Codex agent runtimes that load marketplace skills.
- 输出为视觉文件(PNG),不适用 Org-mode / Denote / ASCII-only 规范。
- 卡好不好看是壳,**能不能从一本书提炼出它独创的看世界方式、压成一幅意向画面、用费曼讲解 + 手绘图形分别呈现它,才是命**。这一步若失手,整张卡退化成豆瓣读书卡。
- 核心:取景框 = 角度 + 问题 + 画面。** 作者从某个机位看某个问题,看到一幅别人没看到的画面。这幅意向画面是枢轴——文字讲它、图形画它,两者是同一幅画面的两次呈现。
- 第一要义:把画面讲清楚,不求压短。** 取消一切「压成一句」之类的字数约束——画面具体、讲解通俗准确,比讲短重要。
- 输入弹性**:继刚常常自己已经想透(读完顺手就想铸卡)。给了思想就直接用(只走校验 + 画图);没给则走全程提炼。
Ljg Library by the numbers
- 1,793 all-time installs (skills.sh)
- +87 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #719 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
ljg-library capabilities & compatibility
- Capabilities
- 输出为视觉文件(png),不适用 org mode / denote / ascii only · 卡好不好看是壳,**能不能从一本书提炼出它独创的看世界方式、压成一幅意向画面、用费曼讲解 + 手 · 核心:取景框 = 角度 + 问题 + 画面。** 作者从某个机位看某个问题,看到一幅别人没看到的 · 第一要义:把画面讲清楚,不求压短。** 取消一切「压成一句」之类的字数约束——画面具体、讲解通俗 · 输入弹性**:继刚常常自己已经想透(读完顺手就想铸卡)。给了思想就直接用(只走校验 + 画图);
- Use cases
- orchestration
What ljg-library says it does
一本书,铸成一张 2050 图书馆借书卡。封面、作者、书目是身份;**核心是把这本书独创的「取景框」压成一幅意向画面**——作者从某个角度看某个问题,看到了一幅别人没看到的画面。文字 block 用费曼式把这幅画面讲透,图形 block 把它精确画出来。合上书半年后,瞥一眼这张卡,那幅画面回来——这是「没白读」的物证。
> 图解 block 用手绘解释的风格、白底黑墨,**精确呈现意向画面**;继刚墨像(`assets/ljg-portrait.png`,由其头像抠底而成)是可选构图件,仅当画面里本来有个「你」才嵌入。完整设计历程见 `~/.claude/PAI/MEMORY/WORK/ljg-oneliner-design/ISA.md`。
输出为视觉文件(PNG),不适用 Org-mode / Denote / ASCII-only 规范。
npx skills add https://github.com/lijigang/ljg-skills --skill ljg-libraryAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.8k |
|---|---|
| repo stars | ★ 6.7k |
| Last updated | August 4, 2026 |
| Repository | lijigang/ljg-skills ↗ |
What it does
一本书 → 一幅清晰的「取景框」意向画面 → 一张 2050 图书馆借书卡(PNG)。取景框 = 作者从哪个角度看什么问题、看到了哪幅画面;卡上有真实封面、作者头像、书目信息。取景框 block 用费曼式讲解把这幅意向画面讲得通俗又准确,图解 block 白底黑墨手绘风、精确呈现该意向画面让人一眼即懂(画面里本来有「你」才嵌继刚墨像,否则只画画面)。浅色光学玻璃风、卡身强调色从封面动态提取、宽高自
Who is it for?
Developers working on ai & agent building during build tasks.
Skip if: Tasks outside AI & Agent Building scope described in SKILL.md.
When should I use this skill?
一本书 → 一幅清晰的「取景框」意向画面 → 一张 2050 图书馆借书卡(PNG)。取景框 = 作者从哪个角度看什么问题、看到了哪幅画面;卡上有真实封面、作者头像、书目信息。取景框 block 用费曼式讲解把这幅意向画面讲得通俗又准确,图解 block 白底黑墨手绘风、精确呈现该意向画面让人一眼即懂(画面里本来有「你」才嵌继刚墨像,否则只画画面)。浅色光学玻璃风、卡身强调色从封面动态提取、宽高自
What you get
Completed ai & agent building workflow aligned with SKILL.md steps.
- library card PNG
- generated illustration PNG
- filled library_template.html
By the numbers
- Skill version 3.2.0 in SKILL.md front matter
- Renders library cards at 1080×1440 via capture.js fullpage mode
- weread t7_ cover URLs resolve to 285×411 pixel images
Files
ljg-library:取景框借书卡
一本书,铸成一张 2050 图书馆借书卡。封面、作者、书目是身份;核心是把这本书独创的「取景框」压成一幅意向画面——作者从某个角度看某个问题,看到了一幅别人没看到的画面。文字 block 用费曼式把这幅画面讲透,图形 block 把它精确画出来。合上书半年后,瞥一眼这张卡,那幅画面回来——这是「没白读」的物证。
图解 block 用手绘解释的风格、白底黑墨,精确呈现意向画面;继刚墨像(assets/ljg-portrait.png,由其头像抠底而成)是可选构图件,仅当画面里本来有个「你」才嵌入。完整设计历程见~/.claude/PAI/MEMORY/WORK/ljg-oneliner-design/ISA.md。
约束
输出为视觉文件(PNG),不适用 Org-mode / Denote / ASCII-only 规范。
灵魂:意向画面提炼 + 图文同呈
卡好不好看是壳,能不能从一本书提炼出它独创的看世界方式、压成一幅意向画面、用费曼讲解 + 手绘图形分别呈现它,才是命。这一步若失手,整张卡退化成豆瓣读书卡。
核心:取景框 = 角度 + 问题 + 画面。 作者从某个机位看某个问题,看到一幅别人没看到的画面。这幅意向画面是枢轴——文字讲它、图形画它,两者是同一幅画面的两次呈现。
第一要义:把画面讲清楚,不求压短。 取消一切「压成一句」之类的字数约束——画面具体、讲解通俗准确,比讲短重要。
执行前,先 Read `references/extraction.md`:第一部分走取景六步(对象 → 角度 → 旧画面 → 意向画面 → 费曼讲解 → 校验)产出意向画面 + 文字(主句 {{FRAME}} + 费曼讲解 {{EXP}},`{{EXP}}` 必走 `feynman-eli5` skill);第二部分把意向画面精确画成图({{SKETCH_SVG}},复用 <defs> 组件与骨架)——继刚墨像听画面调度:画面里有「你」才嵌,没有就只画画面。
输入弹性:继刚常常自己已经想透(读完顺手就想铸卡)。给了思想就直接用(只走校验 + 画图);没给则走全程提炼。
视觉规格
生成 HTML 前,先 Read `references/visual.md`——浅色玻璃卡身规格、卡身动态色 vs 图解板白底黑墨两套配色、字体、图解板(意向画面、墨像可选)规格、踩过的坑全在里面。这是视觉质量底线。
流程
输入:书名(或 书名 + 已想透的取景框思想)
↓
1. weread 取真封面 + 书目(见下「素材获取」)
2. web 抓作者头像
3. 提封面主色 → 卡身动态强调色(python assets/extract_color.py <封面>)
4. 提炼意向画面:对象 + 角度 → 意向画面(用户给了→校验,没给→走 extraction.md 取景六步)
5. 费曼讲解 → {{FRAME}}(一句话点画面)+ {{EXP}}(走 feynman-eli5 把画面讲透)
6. 画意向画面 SVG {{SKETCH_SVG}}:精确呈现那幅画面,墨像听调度(含「你」才嵌 ljg-portrait.png;复用 extraction.md 的 defs + 骨架)
7. 填 assets/library_template.html 的占位变量
8. 渲染(capture.js,fullpage 自适应高度)
9. Read 自验(含放大看图形板,确认图文同一幅画面)→ 交付路径素材获取(关键,按此顺序降级)
封面 + 书目(weread)
继刚有微信读书。走 weread skill 的 /store/search(先 Read ~/.claude/skills/weread/search.md):
curl -s -X POST "https://i.weread.qq.com/api/agent/gateway" \
-H "Authorization: Bearer $WEREAD_API_KEY" -H "Content-Type: application/json" \
-d '{"api_name":"/store/search","keyword":"<书名>","scope":10,"skill_version":"1.0.3"}'- 回包
results[].books[].bookInfo(每个 result 组一本)有title / author / translator / cover / publisher。 - 封面 cover URL 是 `s_` 缩略图(70×100,太小会糊)。把 `s_` 换成 `t7_` 拿高清(285×411):
.../cover/942/635942/t7_635942.jpg。下载时带-H "Referer: https://weread.qq.com/"。 - 取不到 weread → 联网搜豆瓣封面(web-access / markdown-proxy)→ 仍无则 CSS 占位书封。
作者头像(web)
维基百科原图最稳。Wikipedia API 直接拿 original 图 URL:
curl -s -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)" \
"https://en.wikipedia.org/w/api.php?action=query&titles=<英文名>&prop=pageimages&piprop=original&format=json"
# 拿到 .original.source 后下载(带 UA):
curl -sL -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)" -o /tmp/lib_avatar.jpg "<original-url>"- 坑:thumb 路径(`/thumb/.../480px-xxx.jpg`)若该尺寸未缓存会返 HTML 错误页。用原图路径(去掉 /thumb/ 和尺寸段),并必须带 User-Agent(缺 UA 被 Wikimedia 拦)。
- 无头像 → 省略头像(模板作者行不显示 avatar),不阻塞。
墨像(可选,已就位)
图解板若需放「你」,用继刚本人墨像,资产 assets/ljg-portrait.png(黑墨线稿 on 透明,落白板上即白底墨像)已生成、固定复用,无需每次重做。但墨像不是每张必上——只在意向画面本来含「你」时嵌入(判断见 extraction.md 第二部分)。源头像若更新需重做:PIL 读 head.png,lum<120 暗墨像素映射为 #241a12、其余透明,裁掉透明边。
卡身动态强调色
python3 assets/extract_color.py /tmp/lib_cover.jpg
# 输出形如:#c43d30从封面提取最显著的彩色作卡身强调色(换书自动换色:红封→红卡、蓝封→蓝卡)。脚本默认挑「最频繁的彩色」——若封面主体是大面积米 / 灰背景,它会挑出发闷的背景色;这时改按「鲜艳度 × 频次」重排,从真实像素里挑一个撑得住的彩色(别凭空写死)。注意:这只是卡身色;图解板固定白底 #fdfdfb + 墨 #241a12,不动。
模板变量(library_template.html)
| 变量 | 内容 |
|---|---|
{{ACCENT}} | 卡身动态强调色 hex(如 #c43d30,从封面提取) |
{{COVER}} | 封面的 file:// 绝对路径 |
{{AVATAR_IMG}} | 整个头像 <img class="avatar" src="file://…">(无头像填空字符串,作者行自动省 avatar) |
{{TITLE}} {{EN}} {{SUBTITLE}} | 书名中 / 英 / 副标题 |
{{TAGS}} | 3-4 个主题标签(书的核心概念),每个 <span class="tag">…</span> |
{{AUTHOR_CN}} {{AUTHOR_META}} | 作者中文名 / 「英文名 · 出版社 年份」 |
{{FRAME}} | 意向画面主句:一句话点出这幅画面的换眼睛主张,关键词用 <span class="hl">…</span> 染卡身强调色 |
{{EXP}} | 费曼讲解:走 feynman-eli5 把这幅意向画面讲通俗讲准、完整流畅,关键词同样 <span class="hl"> |
{{SKETCH_TITLE}} | 图形板的名字(英文 + 中文,如 Ergodicity 遍历性) |
{{SKETCH_SVG}} | 手绘图形整段 <svg>…</svg>(白底黑墨、精确呈现意向画面、墨像听画面调度,见 extraction.md 第二部分) |
渲染
node ~/.claude/skills/ljg-card/assets/capture.js \
/tmp/ljg_library_{name}.html ~/Downloads/{name}.png 1080 1440 fullpage复用 ljg-card 的 capture.js(playwright 已装在 ljg-card/node_modules)。必须 `fullpage`——卡片高度自适应内容,不留底部空白。file:// 引用本地封面 / 头像 / 墨像可直接渲染。
交付
1. Read 输出的 PNG 亲眼验图,并放大看图形板(封面/头像加载 ✓、费曼讲解把意向画面讲透 ✓、卡身色协调 ✓、图形精确呈现意向画面一眼即懂 ✓、含「你」时墨像清晰群众无脸成对比/无「你」时纯画画面 ✓、墨线手绘抖 + 批注清晰 ✓、图文同一幅画面 ✓、右侧无空白 ✓)。 2. 报告文件路径 + 一句意向画面提炼说明。
Gotchas(务必避开)
- 封面尺寸:weread
s_前缀是 70×100 缩略图,必糊。换t7_拿 285×411 高清,下载带Referer。 - 头像 thumb 陷阱:Wikimedia
/thumb/.../NNNpx-特定尺寸未缓存会返 HTML 错误页。用原图路径 + User-Agent。 - 墨像可选,要放就嵌真墨像不手绘:决定放继刚墨像时,用
<image href="…/assets/ljg-portrait.png">,鲜明 + 像素级一致;手绘小人既不像他又每次漂移,已弃。但不是每张必上——画面无「你」就别放,硬塞反糊画面、违背「一眼即懂」。 - 图解板是手写 SVG:线条 / 图形套
filter="url(#rough)"出手绘抖动;文字 / 批注 / 墨像绝不套滤镜(糊)。复用组件 + 骨架见 extraction.md。 - 无脸群众只在有墨像「你」时用:放了墨像「你」,群众才用
#person无脸小墨人作对比——「你 vs 一群人」靠这个,别给群众画脸。画面无「你」时,群众也未必需要。 - 图解板白底黑墨两色:白
#fdfdfb底 + 墨#241a12。两套色别串:卡身动态色从封面提取、不写死;图解板白底 + 墨、写死。 - 意向画面是认知位移的成像,不是摘要:主句「原来不是 X,其实是 Y」+ 费曼讲解讲透机制,不是「本书讲了……」。验收尺:凉脑子瞥一眼,那幅画面回不回得来。
{
"COVER": "file:///tmp/oneliner_cover.jpg",
"COVER_LOCAL": "/tmp/oneliner_cover.jpg",
"AVATAR": "file:///tmp/avatar_orig.jpg",
"TITLE": "反脆弱",
"EN": "Antifragile",
"SUBTITLE": "从不确定性中获益",
"TAGS": [
"<span class=\"tag\">不确定性</span>",
"<span class=\"tag\">凸性</span>",
"<span class=\"tag\">黑天鹅</span>",
"<span class=\"tag\">风险</span>"
],
"AUTHOR_CN": "纳西姆·尼古拉斯·塔勒布",
"AUTHOR_META": "Nassim Nicholas Taleb · 中信出版社 2014",
"FRAME": "脆弱的反义词不是坚固,而是<span class=\"hl\">反脆弱</span>。",
"ECHO": "它从波动和混乱里长力气——风吹灭蜡烛,却把火越烧越旺。",
"CHART_TITLE": "Convexity 凸性",
"CHART": [
"<span class=\"lbl\">收益</span>",
"<span class=\"ax\">│</span> <span class=\"cv\">●</span>",
"<span class=\"ax\">│</span> <span class=\"cv\">●</span>",
"<span class=\"ax\">│</span> <span class=\"cv\">●</span>",
"<span class=\"ax\">│</span> <span class=\"cv\">●</span>",
"<span class=\"ax\">│</span> <span class=\"cv\">●</span>",
"<span class=\"ax\">│</span> <span class=\"cv\">●</span>",
"<span class=\"ax\">│</span> <span class=\"cv\">●</span>",
"<span class=\"ax\">│</span><span class=\"cv\">●━━</span>",
"<span class=\"ax\">└───────────→</span> <span class=\"lbl\">波动</span>"
],
"NOTE": [
"<div class=\"cn-item\"><div class=\"k\">下行<b>封死</b></div><div class=\"v\">损失有底,亏得起的小注</div></div>",
"<div class=\"cn-item\"><div class=\"k\">上行<b>敞开</b></div><div class=\"v\">收益无顶,赌罕见的巨大命中</div></div>",
"<div class=\"cn-item\"><div class=\"k\">偏离越大,越<b>获益</b></div><div class=\"v\">波动和混乱,成了它的养料</div></div>"
]
}
#!/usr/bin/env python3
"""从书封提取最显著的彩色,作为这张卡的动态强调色。
用法:
python3 extract_color.py <cover.jpg>
输出:
一个 UI-ready 的 hex 强调色,如 #c43d30(已适度收敛饱和/明度,避免荧光刺眼)。
逻辑:
缩图取像素 → 过滤掉近黑/近白/灰(无饱和的中性色不能当强调)→
取最频繁的彩色 → 适度向沉稳收一档 → 输出。
封面若整体灰白无显著彩色 → 回退到沉稳蓝 #3d5a80。
"""
import sys
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
from collections import Counter
try:
from PIL import Image
except ImportError:
print("#3d5a80") # PIL 不在 → 安全回退,不阻塞出卡
sys.exit(0)
def colorful(c):
"""有饱和度、非近黑近白的像素才算‘彩色’。"""
mx, mn = max(c), min(c)
return mx - mn > 38 and mx > 70 and mn < 210
def tame(c):
"""向沉稳收一档:太鲜的荧光色降饱和+压一点明度,得到高级、克制、点缀面积小也不刺眼的强调色。"""
r, g, b = c
mx, mn = max(c), min(c)
lum = 0.299 * r + 0.587 * g + 0.114 * b
# 太亮的彩色压暗一点(浅玻璃上才压得住),与中性灰按比例混合降饱和
target_lum = min(lum, 165)
k = target_lum / max(lum, 1)
r, g, b = (int(v * k) for v in (r, g, b))
gray = int(0.299 * r + 0.587 * g + 0.114 * b)
mix = 0.20 # 混 20% 同明度灰,收一档饱和
r = int(r * (1 - mix) + gray * mix)
g = int(g * (1 - mix) + gray * mix)
b = int(b * (1 - mix) + gray * mix)
return (max(0, min(255, r)), max(0, min(255, g)), max(0, min(255, b)))
def main(path):
im = Image.open(path).convert("RGB").resize((60, 86))
px = list(im.getdata())
cands = [c for c in px if colorful(c)]
if not cands:
print("#3d5a80")
return
top = Counter(cands).most_common(1)[0][0]
r, g, b = tame(top)
print("#%02x%02x%02x" % (r, g, b))
if __name__ == "__main__":
if len(sys.argv) < 2:
print("usage: extract_color.py <cover.jpg>", file=sys.stderr)
sys.exit(1)
main(sys.argv[1])
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@500;600;700&family=Noto+Sans+SC:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&family=Long+Cang&display=swap" rel="stylesheet">
<style>
*{ margin:0; padding:0; box-sizing:border-box; }
:root{
--txt:#1a1f2e;
--txt2:#5b6472;
--txt3:#8a93a1;
--accent:{{ACCENT}};
--accent-soft:color-mix(in srgb, {{ACCENT}} 9%, transparent);
--accent-line:color-mix(in srgb, {{ACCENT}} 28%, transparent);
--accent-glow:color-mix(in srgb, {{ACCENT}} 35%, transparent);
--ink:#241a12; /* 墨色 — 图解板的线条 / 群众 / 批注 / 墨像(墨像 assets/ljg-portrait.png 可选,仅画面含「你」时嵌) */
--sans:'Noto Sans SC',sans-serif;
--serif:'Noto Serif SC',serif;
--mono:'JetBrains Mono','Noto Sans SC',monospace;
--hand:'Long Cang',cursive; /* 手写批注体 */
}
/* 宽度固定 1080 作版心,高度自适应(fullpage 截图) */
body{ width:1080px; position:relative; padding:60px 0; font-family:var(--sans);
background:linear-gradient(155deg, #eef1f7 0%, #e6ebf3 50%, #e3e8f2 100%); }
.bg{ position:absolute; inset:0;
background:
radial-gradient(70% 30% at 50% 0%, rgba(255,255,255,0.7), transparent 60%),
radial-gradient(60% 32% at 86% 8%, color-mix(in srgb, {{ACCENT}} 5%, transparent), transparent 62%),
radial-gradient(64% 36% at 12% 100%, rgba(120,140,180,0.10), transparent 60%); }
.grain{ position:absolute; inset:0; opacity:0.025; mix-blend-mode:multiply;
background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }
/* 浅色光学玻璃 — flow 布局,高度自适应 */
.card{ position:relative; width:948px; margin:0 auto;
background:rgba(255,255,255,0.55);
backdrop-filter:blur(40px) saturate(1.3); -webkit-backdrop-filter:blur(40px) saturate(1.3);
border:1px solid rgba(255,255,255,0.85); border-radius:32px;
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.9),
0 8px 32px rgba(31,41,72,0.12),
0 40px 80px -32px rgba(31,41,72,0.18);
padding:50px 54px; display:flex; flex-direction:column; }
.ident{ display:flex; gap:34px; align-items:stretch; }
.cover{ width:198px; height:287px; border-radius:9px; object-fit:cover; flex-shrink:0;
box-shadow:0 14px 34px -10px rgba(31,41,72,0.32), 0 0 0 1px rgba(31,41,72,0.06); }
.ibody{ flex:1; display:flex; flex-direction:column; justify-content:space-between; padding:2px 0; min-width:0; }
.title{ font-family:var(--serif); font-size:64px; font-weight:700; color:var(--txt); line-height:1.0; letter-spacing:0.01em; }
.en{ font-family:var(--mono); font-size:19px; font-weight:500; color:var(--accent); letter-spacing:0.18em; margin-top:11px; text-transform:uppercase; }
.subtitle{ font-family:var(--serif); font-size:22px; color:var(--txt2); margin-top:13px; font-weight:500; }
.tags{ display:flex; gap:9px; margin-top:20px; flex-wrap:wrap; }
.tag{ font-family:var(--mono); font-size:13px; letter-spacing:0.05em; color:var(--accent); padding:5px 13px;
border:1px solid var(--accent-line); border-radius:20px; background:var(--accent-soft); }
.authorline{ display:flex; align-items:center; gap:15px; padding-top:18px; border-top:1px solid rgba(31,41,72,0.12); }
.avatar{ width:54px; height:54px; border-radius:50%; object-fit:cover; object-position:center top;
box-shadow:0 0 0 1.5px var(--accent-glow), 0 5px 14px -4px rgba(31,41,72,0.3); }
.authorname b{ font-family:var(--sans); font-size:20px; color:var(--txt); font-weight:600; display:block; }
.authorname span{ font-family:var(--mono); font-size:13px; color:var(--txt3); letter-spacing:0.04em; }
.rule{ height:1px; background:linear-gradient(90deg, var(--accent-line), rgba(31,41,72,0.10) 38%, rgba(31,41,72,0.02)); margin:38px 0; }
.block-label{ font-family:var(--mono); font-size:14px; letter-spacing:0.32em; color:var(--accent); text-transform:uppercase; margin-bottom:22px; display:flex; align-items:center; gap:12px; font-weight:500; }
.block-label::before{ content:''; width:24px; height:2px; background:var(--accent); }
/* BLOCK 1 取景框 — 主句 + 费曼讲解,两端对齐填满 */
.frame-text{ font-family:var(--serif); font-size:40px; line-height:1.42; color:var(--txt); font-weight:600; letter-spacing:0.004em;
text-align:justify; text-justify:inter-ideograph; text-align-last:left; }
.frame-text .hl{ color:var(--accent); }
.frame-exp{ font-family:var(--serif); font-size:21px; color:var(--txt2); font-weight:500; margin-top:20px; line-height:1.74;
text-align:justify; text-justify:inter-ideograph; text-align-last:left; }
.frame-exp .hl{ color:var(--accent); font-weight:600; }
/* BLOCK 2 图解 — 精确呈现意向画面的白色插画板(黑墨 on 白;继刚墨像 assets/ljg-portrait.png 可选,听画面调度) */
.plate{ background:#fdfdfb; border:1px solid rgba(31,41,72,0.08); border-radius:16px;
box-shadow:inset 0 1px 0 rgba(255,255,255,0.9), 0 6px 22px -10px rgba(31,41,72,0.16);
padding:10px 16px; }
.plate svg{ display:block; width:100%; height:auto; }
.plate .hand{ font-family:var(--hand); }
.sign{ padding-top:26px; display:flex; align-items:center; gap:10px; }
.sign .chop{ display:inline-block; width:24px; height:24px; background:var(--accent); border-radius:5px; color:#fff; font-family:var(--serif); font-size:13px; line-height:24px; text-align:center; }
.sign span{ font-family:var(--serif); font-size:17px; color:var(--txt2); letter-spacing:0.04em; }
</style>
</head>
<body>
<div class="bg"></div>
<div class="grain"></div>
<div class="card">
<div class="ident">
<img class="cover" src="{{COVER}}" alt="cover">
<div class="ibody">
<div>
<div class="title">{{TITLE}}</div>
<div class="en">{{EN}}</div>
<div class="subtitle">{{SUBTITLE}}</div>
<div class="tags">{{TAGS}}</div>
</div>
<div class="authorline">
{{AVATAR_IMG}}
<div class="authorname"><b>{{AUTHOR_CN}}</b><span>{{AUTHOR_META}}</span></div>
</div>
</div>
</div>
<div class="rule"></div>
<div class="block-label">取景框 · The Frame</div>
<div class="frame-text">{{FRAME}}</div>
<div class="frame-exp">{{EXP}}</div>
<div class="rule"></div>
<div class="block-label">图解 · {{SKETCH_TITLE}}</div>
<div class="plate">{{SKETCH_SVG}}</div>
<div class="rule" style="margin:34px 0 0;"></div>
<div class="sign"><span class="chop">印</span><span>李继刚</span></div>
</div>
</body>
</html>
#!/usr/bin/env python3
"""ljg-library 渲染器 —— 给一本书的数据 JSON,出卡。
用法:
python3 render.py <data.json> <out.png>
分工:AI 负责智力内容(FRAME / ECHO / CHART / NOTE,见 references/extraction.md),
写进 JSON;本脚本做机械的提色 + 模板填充 + 渲染。
data.json 字段见 assets/example_antifragile.json。要点:
- CHART / NOTE / TAGS 可为字符串,或字符串数组(数组自动按行 join,写起来更省心)。
- 未给 ACCENT 但给了 COVER_LOCAL(封面本地路径)→ 自动从封面提取强调色。
- 未给 AVATAR → 省略头像,作者行不显示。
- COVER / AVATAR 用 file:// 绝对路径。
"""
import sys, json, subprocess, pathlib
ROOT = pathlib.Path(__file__).resolve().parent
CAPTURE = ROOT.parent.parent / "ljg-card" / "assets" / "capture.js"
KEYS = ["ACCENT", "COVER", "AVATAR_IMG", "TITLE", "EN", "SUBTITLE", "TAGS",
"AUTHOR_CN", "AUTHOR_META", "FRAME", "ECHO", "CHART_TITLE", "CHART", "NOTE"]
def asstr(v):
return "\n".join(v) if isinstance(v, list) else str(v)
def main(data_path, out_path):
d = json.loads(pathlib.Path(data_path).read_text(encoding="utf-8"))
if not d.get("ACCENT") and d.get("COVER_LOCAL"):
d["ACCENT"] = subprocess.check_output(
["python3", str(ROOT / "extract_color.py"), d["COVER_LOCAL"]]
).decode().strip()
d.setdefault("ACCENT", "#3d5a80")
d["AVATAR_IMG"] = (f'<img class="avatar" src="{d["AVATAR"]}" alt="author">'
if d.get("AVATAR") else "")
tpl = (ROOT / "library_template.html").read_text(encoding="utf-8")
for k in KEYS:
tpl = tpl.replace("{{" + k + "}}", asstr(d.get(k, "")))
if "{{" in tpl:
print("warn: unreplaced placeholder remains", file=sys.stderr)
html = "/tmp/ljg_library_render.html"
pathlib.Path(html).write_text(tpl, encoding="utf-8")
subprocess.run(["node", str(CAPTURE), html, out_path, "1080", "1440", "fullpage"], check=True)
print("OK:", out_path, "| accent:", d["ACCENT"])
if __name__ == "__main__":
if len(sys.argv) < 3:
print("usage: render.py <data.json> <out.png>", file=sys.stderr)
sys.exit(1)
main(sys.argv[1], sys.argv[2])
意向画面提炼 + 图文同呈
这是 ljg-library 的命门。卡好看是壳;从一本书提炼出它独创的看世界方式(取景框)、把它压成一幅意向画面、再让文字和图形分别把这幅画面呈现出来,才是命。失手则整张卡退化成豆瓣读书卡。
核心:取景框 = 角度 + 问题 + 画面。 作者从某个角度(机位)看某个问题(被摄物),看到了一幅别人没看到的画面(成像)。这幅意向画面是整张卡的枢轴——文字 block 用费曼式把它讲透,图形 block 把它精确画出来,两者是同一幅画面的两次呈现。合上书半年后记住的,就是这幅画面。
第一要义:把画面讲清楚,不求压短。 取消一切「压成一句」之类的字数约束——画面要具体、讲解要通俗准确,永远比讲短重要。
一、提炼意向画面(取景六步)
1. 对象(被摄物):这本书在看什么问题? 2. 角度(机位):作者站在哪个位置、用什么视角看它?——「取景」的「取」,就在这一步选了机位。 3. 旧画面(零点):在它之前,常人 / 各流派从惯常机位看到的是哪幅画面(旧共识)? 4. 意向画面(核心产物):换到作者这个机位,看到了哪幅新画面?——一个具体、画得出来、一句话说得清的心象。它和旧画面的落差(delta),就是这副新眼睛的全部价值。
- 检验它真是「画面」而非「命题」:你能不能把它当一幅画描述出来?有没有可见的物、可见的动作、可见的对比?讲不出画面,说明还停在抽象命题,回第 2 步重取机位。
5. 费曼讲解(文字 block:{{FRAME}} + {{EXP}}):把这幅意向画面讲给一个聪明的外行听。
- 必走 `feynman-eli5` skill,不手搓(费曼讲解是它的专长,继刚定过这条规矩)。喂给它:意向画面 + 旧画面 + 机制(为什么从这个机位会看到这幅画面);要回:通俗、准确、带具体类比、零黑话的解释。
- {{FRAME}} = 一句话说清这幅画面的「换眼睛」主张——「原来不是 X,其实是 Y」式,认知位移 + 动作动词;禁名词定义、禁「本书讲了……」摘要。关键词
<span class="hl">染卡身强调色。 - {{EXP}} = feynman-eli5 的产物落地:完整、流畅、通俗地把这幅画面讲透——它是什么画面、为什么从这个机位会看到它、它改了你怎么看什么。关键词同样
<span class="hl">。
6. 校验:删掉书名作者,{{FRAME}} + {{EXP}} 能否独立成立为「一种看世界的方式」?是摘要 → 重炼;是画面 + 位移 → 过。再过翻译腔五连问(主语 / 动词 / 介词 / 定语 / 朗读卡),确保 native。最后一关:文字讲的画面,和图形画的画面,是不是同一幅? 不是 → 对齐再交付。
验收尺:凉了的脑子,瞥一眼,那幅画面回不回得来。
示例 A ·《非对称风险》(遍历性)—— 画面里有「你」
- 对象:一个期望值为正的赌局,该不该参与?
- 角度:不站在「一群人各玩一次的平均」上看,蹲到「你一个人玩很久」那条时间线上看。
- 旧画面:一百个平行的你摊平,期望为正就该上(集合平均)。
- 意向画面:两条命运线分叉——无脸人群在高线匀速前行(+5%),而「你」沿一条时间线坠向一道吸收壁(破产/死亡,进去出不来),正期望也通向归零。
- 立框 {{FRAME}}:
一个赌局好不好,不看「很多人各玩一次」的平均,要看「你一个人<span class="hl">玩很久</span>」的命运。 - 铺陈 {{EXP}}(feynman-eli5 产物):
经典决策论用<span class="hl">集合平均</span>判断——一百个平行的你摊平,期望为正就该上。可你不活在平行宇宙的平均里,只走<span class="hl">一条时间线</span>;路上但凡有一道<span class="hl">吸收壁</span>(破产、死亡、崩塌,进去就出不来),正期望也会把你稳稳推向归零。所以真正决定命运的是时间平均,不是集合平均。 - 校验:删书名独立成立 ✓;朗读 native ✓;图文同一幅画面 ✓
- 图形:画面里本来有个「你」(你走的那条时间线)→ 放继刚墨像当「你」。见第二部分骨架。
示例 B ·《自私的基因》—— 画面里没有「你」
- 对象:生命为什么长成现在这样?演化里谁是主角?
- 角度:不站在「个体 / 物种」的位置,蹲到「基因」的位置往上看。
- 旧画面:人(或动物个体)是主角,基因是它用来传宗接代的工具。
- 意向画面:反过来——一段基因坐在驾驶座上,身体只是它造出来、用完即弃的一辆车(survival machine);一代代车生灭报废,同一段基因穿过它们,一路向前。
- 立框 {{FRAME}}:
原来不是<span class="hl">你</span>在用基因传宗接代,是<span class="hl">基因</span>在用你这具身体,把它自己复制下去。 - 铺陈 {{EXP}}(feynman-eli5 产物):
把基因想成一段「照着造身体」的说明书。哪段说明书造出的身体更能活、更能再印一份,哪段就留下来。于是身体不是目的,是说明书印自己的<span class="hl">手段</span>;你这一辈子,本质是一段古老说明书搭起来的一辆<span class="hl">临时车</span>,载着它再跑一程——到站换车,说明书继续往前。 - 校验:删书名独立成立 ✓;图文同一幅画面 ✓
- 图形:主角是基因,这幅画面的主张恰恰是「你不是主角」——这时放继刚墨像反而违背画面。只画意向画面:驾驶座上的基因 + 身体当车壳 + 路上一串报废旧车 + 「同一段基因穿过一代代身体」的箭头。墨像缺席,正是这幅画面该有的样子。
二、把意向画面画出来({{SKETCH_SVG}} + {{SKETCH_TITLE}})
block 2 把意向画面精确画出来,一眼即懂。手绘解释风、白底黑墨。
画面当主人,墨像听调度。 先有意向画面,再决定继刚墨像上不上:
- 画面里本来有个「你」(一个承受者 / 观看者 / 走在某条路上的人,如遍历性「你走一条时间线」)→ 放墨像当「你」,群众用无脸小墨人作对比,「你 vs 一群人」不点自明。
- 画面是一个非人的结构(生态、网络、流、场、一段基因、一炉熵)→ 不放墨像,老实画那幅画面。硬塞个「你」进去,反而糊了画面,违背「一眼即懂」。
>
判断只问一句:这幅意向画面里,本来有没有一个「你」? 有就放,没有就别。
视觉语法(写死,照搬)—— 白底黑墨
- 白底板
#fdfdfb,大留白,主体占 ~50%。 - 黑墨线
#241a12(--ink),stroke 2-2.2,线条 / 图形套filter="url(#rough)"出抖动手绘感。文字与批注绝不 roughen,否则糊。 - 墨像(可选) =
<image href="file:///…/assets/ljg-portrait.png">嵌入的继刚墨像,约 200×200,立在左侧(视线朝右、望进图里)。仅当画面含「你」时使用——像素级一致、一眼是他,比手绘小人鲜明得多。 - 群众(仅配墨像时用) = 微型无脸墨人(
#person:圆头 + 水滴身 + 细腿 + 白点眼),代表「很多人」,正好和墨像「你」的真脸成对比。画面无「你」时,群众也未必需要,别为凑对比硬加。 - 批注 =
Long Cang手写体,黑墨#241a12,配小箭头(#ar)。3-5 条,点关键不堆字。 - 构图骨架 viewBox
0 0 860 400配.plate刚好;可复用<defs>的#rough / #ar / #person是工具箱,按需取用。
怎么把「意向画面」画成图
意向画面的核心张力 → 一个空间隐喻(图示)→ 该有「你」就把墨像接进去,没有就让图示自己说话。
- 遍历性(含你):左侧继刚墨像(你),右侧两条命运线分叉——无脸群众在高线匀速(+5%),从「你」拉箭头进入那条沿时间坠向深坑(吸收壁)的线。标题「同一注,两种命运」钉住。
- 自私的基因(无你):驾驶座上一段 DNA 螺旋(拟人一点点或纯螺旋),车身是身体轮廓,路上一串「用完丢弃的旧车壳」,一根长箭头标「同一段基因穿过一代代身体」。无墨像、无「你」——主角是基因。只复用
#rough(抖线)+#ar(箭头),不用#person当主角、不嵌墨像。
换书换隐喻:复用 `<defs>` 的 `#rough / #ar / #person`(工具箱),墨像<image>按「画面有没有你」决定上不上。{{SKETCH_TITLE}}= 图名(如Ergodicity 遍历性)。viewBox0 0 860 400配.plate刚好。
>
墨像资产assets/ljg-portrait.png已生成。若源头像更新需重做:PIL 读 head.png,lum<120的暗墨像素映射为#241a12、其余设透明,再裁掉透明边即可(黑墨线稿 on 透明,落白板上就是白底墨像)。
遍历性整图({{SKETCH_SVG}} 参照骨架 ——「含你」范例,直接改隐喻复用)
<svg viewBox="0 0 860 400" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="rough" x="-5%" y="-5%" width="110%" height="110%">
<feTurbulence type="fractalNoise" baseFrequency="0.016" numOctaves="2" seed="7" result="n"/>
<feDisplacementMap in="SourceGraphic" in2="n" scale="3.0" xChannelSelector="R" yChannelSelector="G"/>
</filter>
<marker id="ar" viewBox="0 0 10 10" refX="7" refY="5" markerWidth="6.4" markerHeight="6.4" orient="auto-start-reverse">
<path d="M0,1 L9,5 L0,9" fill="none" stroke="#241a12" stroke-width="1.7"/>
</marker>
<g id="person">
<path d="M0,0 C-7,0 -8,-12 -3,-16 L3,-16 C8,-12 7,0 0,0 Z" fill="#241a12"/>
<circle cx="0" cy="-20" r="5.2" fill="#241a12"/>
<circle cx="-1.6" cy="-21" r="1.1" fill="#fff"/>
<line x1="-2" y1="0" x2="-3" y2="7" stroke="#241a12" stroke-width="2"/>
<line x1="2" y1="0" x2="3" y2="7" stroke="#241a12" stroke-width="2"/>
</g>
</defs>
<!-- 墨像(可选,本图含「你」故嵌入):继刚本人墨像,像素级一致 -->
<image href="file:///Users/lijigang/.claude/skills/ljg-library/assets/ljg-portrait.png" x="14" y="128" width="208" height="209"/>
<!-- 图解:双命运(roughened ink) -->
<g filter="url(#rough)" fill="none" stroke="#241a12" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round">
<path d="M262,118 L262,344 L800,344"/>
<path d="M262,118 L258,128 M262,118 L266,128"/>
<path d="M800,344 L790,340 M800,344 L790,348"/>
<!-- ensemble high line -->
<path d="M286,228 C420,222 640,216 786,212" stroke-dasharray="2 7" stroke-width="2.3"/>
<!-- time line into the pit -->
<path d="M286,244 C380,278 470,304 548,322 C588,331 624,336 652,338"/>
<ellipse cx="694" cy="340" rx="42" ry="11.5" fill="#fdfdfb"/>
<path d="M654,336 C654,349 734,349 734,336"/>
<path d="M662,344 L656,357 M684,347 L680,362 M710,347 L716,362 M730,343 L737,356"/>
</g>
<!-- 一群无脸小人在高线匀速 -->
<use href="#person" x="372" y="225"/>
<use href="#person" x="468" y="221"/>
<use href="#person" x="566" y="217"/>
<use href="#person" x="664" y="214"/>
<!-- 从「你」指向时间线起点 -->
<path d="M230,250 C244,250 256,248 280,246" fill="none" stroke="#241a12" stroke-width="1.7" marker-end="url(#ar)"/>
<!-- 墨色手写批注 -->
<g fill="#241a12">
<text class="hand" x="500" y="34" font-size="30" text-anchor="middle">同一注,两种命运</text>
<text class="hand" x="600" y="190" font-size="22">很多人各玩一次 +5%</text>
<path d="M628,198 C612,206 598,210 582,210" fill="none" stroke="#241a12" stroke-width="1.7" marker-end="url(#ar)"/>
<text class="hand" x="338" y="332" font-size="22">你一个人玩很久</text>
<text class="hand" x="690" y="384" font-size="22">一道吸收壁 → 0</text>
<path d="M706,368 C700,358 692,352 686,350" fill="none" stroke="#241a12" stroke-width="1.7" marker-end="url(#ar)"/>
<text class="hand" x="246" y="116" font-size="19">财富</text>
<text class="hand" x="806" y="338" font-size="19">时间</text>
</g>
</svg>视觉规格 + 踩坑
生成 HTML 前过一遍。这是 ljg-library 的视觉质量底线。
浅色光学玻璃卡身(继刚精确规格,写死在 template,勿动)
| 角色 | 值 |
|---|---|
| 背景渐变 | #eef1f7 → #e3e8f2 冷调雾白(不是死白) |
| 玻璃卡面 | rgba(255,255,255,0.55) + backdrop-filter:blur(40px) |
| 高光边 | 1px solid rgba(255,255,255,0.85)(玻璃反光边) |
| 柔投影 | 0 8px 32px rgba(31,41,72,0.12)(让它悬空) |
| 正文 | #1a1f2e 近黑不死黑,对比足、久看不累 |
| 次要 | #5b6472 中性灰蓝 |
三层明度浮起:雾白底 → 玻璃面 → 文字。浅底配深字(纸书传统,最护眼)。
两套配色:卡身动态色 + 图解板白底黑墨
卡身动态强调色(skill 灵魂特性):python3 assets/extract_color.py <封面> 从封面提主色,注入 {{ACCENT}}。--accent-soft/line/glow 由 color-mix 自动派生。换书自动换色:红封→红卡、蓝封→蓝卡。用于身份区 + 取景框:标签、英文行、关键词高亮、署名印。
图解板白底黑墨(固定):图解板是「黑墨 on 白」——白底 #fdfdfb,线条 / 群众 / 批注一律墨色 --ink:#241a12,墨像(若用)同色。不随封面变。 卡身动态色与图解板互不干扰,白板与玻璃卡身天然相配。
克制:卡身大面积是雾白底 + 深墨正文(占八成),动态色只点两成;图解板是独立的白底墨绘。
字体
| 用途 | 字体 |
|---|---|
| 取景框主句 / 铺陈 / 书名 / 副标 | Noto Serif SC(书卷气) |
| 标签 / block-label / 机读字段 | JetBrains Mono |
| 作者名 | Noto Sans SC |
图解板手写批注(.hand) | Long Cang(手写体) |
自适应 + 两端对齐
- 卡片
flow + height:auto,渲染必须fullpage——高度跟内容,底部不留白。 - 文本
text-align:justify; text-justify:inter-ideograph——中文字距均匀撑满、右侧齐平,根治「左对齐右侧豁口」。 - SVG 图解板
width:100%,viewBox0 0 860 400配.plate刚好。
结构(两 block + 身份区 + 署名)
身份区:封面(198×287) | 书名+英文+副标+标签+作者头像 ← 填满右侧
─────
取景框 block:标签 + 主句 {{FRAME}} + 费曼讲解 {{EXP}}(把意向画面讲通俗讲准,justify)
─────
图解 block:白底墨绘插画板 {{SKETCH_SVG}} —— 精确呈现意向画面,墨像按「画面有没有你」调度
─────
极简署名:印 李继刚(唯一框架墨水,data-ink)无 header、无 footer 日期、无收藏编号——Tufte 最大化信息墨水比,框架装饰全砍。
取景框第一要义:先有一幅意向画面,再图文同呈。 主句 {{FRAME}} 一句话点出这幅画面的换眼睛主张,{{EXP}} 走 feynman-eli5 把它讲通俗讲准。清楚高于短;图与文须是同一幅画面。
图解板(block 2)—— 白底黑墨,精确呈现意向画面
白底板 .plate(#fdfdfb)嵌在霜玻璃卡里,像一页夹进去的钢笔墨绘。主角是意向画面本身——block 2 把第一部分提炼的那幅画面精确画出来,一眼即懂。继刚墨像(assets/ljg-portrait.png,头像抠底而成、像素级一致)是可选构图件,听画面调度:画面里本来有个「你」(如遍历性「你走一条时间线」)就放他当「你」、配无脸群众作对比;画面是非人结构(生态 / 网络 / 流 / 一段基因)就不放,老实画画面。判断只问一句:这幅画面里本来有没有「你」。完整视觉语法、可复用 `<defs>`(`#rough/#ar/#person`)+ 墨像 `<image>`、两个范例(含你 / 无你)骨架全在 `references/extraction.md` 第二部分——照搬,换隐喻,墨像按需。
踩坑清单(务必避开)
1. 封面尺寸:weread s_ 前缀 = 70×100 缩略图,必糊。换 t7_ = 285×411 高清,下载带 Referer: https://weread.qq.com/。 2. 头像 thumb 陷阱:Wikimedia /thumb/.../NNNpx- 若该尺寸未缓存 → 返 HTML 错误页。用原图路径(去 /thumb/ 和尺寸段)+ User-Agent(缺 UA 被拦)。 3. 墨像可选,要放就嵌真墨像不手绘:决定放继刚墨像时用 <image href="…/assets/ljg-portrait.png">,鲜明 + 像素级一致;手绘小人既不像他、又每次漂移,已弃。但墨像不是每张必上——画面无「你」就别放,硬塞反糊画面。 4. 图解板是手写 SVG:线条 / 图形套 filter="url(#rough)" 出手绘抖动;文字 / 批注 / 主角墨像绝不套滤镜(糊)。 5. 无脸群众只在有墨像「你」时用:放了墨像「你」,群众才用 #person 无脸小墨人(白点眼)作对比——「你 vs 一群人」靠这个,别给群众画脸。画面无「你」时,群众也未必需要。 6. 图解板白底黑墨两色:白 #fdfdfb 底 + 墨 #241a12。镂空亮点(群众眼)用白。 7. 两套色别串:卡身动态色从封面提取、不写死;图解板白底 + 墨、写死。 8. 右侧空白:justify + SVG 满宽,别让任何 block 只占左半。 9. 取景框是认知位移非摘要:主句「原来不是 X,其实是 Y」+ 铺陈讲透机制,不是「本书讲了……」。
出厂自检
- [ ] 封面、头像加载出来了(file:// 路径对)?
- [ ] 取景框:主句 + 铺陈把这副眼睛完整流畅讲透、关键词染色?
- [ ] 卡身动态色从封面提取、与封面协调、只点两成?
- [ ] 图解板:意向画面一眼即懂;含「你」则墨像清晰、群众无脸成对比,无「你」则纯画画面、不硬塞墨像?
- [ ] 板是白底黑墨、线手绘抖、批注清晰不糊、留白足?
- [ ] 文本两端对齐、右侧无豁口?
- [ ] 高度自适应、底部无留白(fullpage)?
- [ ] 无 header/footer 框架,只角落署名?
Related skills
How it compares
Pick ljg-library over text-only summarization skills when the deliverable must be a single illustrated PNG card rather than markdown notes.
FAQ
What does ljg-library do?
一本书 → 一幅清晰的「取景框」意向画面 → 一张 2050 图书馆借书卡(PNG)。取景框 = 作者从哪个角度看什么问题、看到了哪幅画面;卡上有真实封面、作者头像、书目信息。取景框 block 用费曼式讲解把这幅意向画面讲得通俗又准确,图解 block 白底黑墨手绘风、精确呈现该意向画面让人一眼即懂(画面里本来有「你」才嵌继刚墨像,否则只画画面)。浅色光学玻璃风、卡身强调色从封面动态提取、宽高自
When should I use ljg-library?
During build integrations work for ai & agent building.
Is ljg-library safe to install?
Review the Security Audits panel on this listing before production use.