Skip to content

feat: Themes from GitHub repositories, a Theme list, and publishing from the uploader skill - #41

Merged
geoqiao merged 6 commits into
mainfrom
feat/remote-themes
Sep 28, 2026
Merged

geoqiao merged 6 commits into
mainfrom
feat/remote-themes

Conversation

@geoqiao

@geoqiao geoqiao commented Sep 28, 2026

Copy link
Copy Markdown
Owner

问题与改动

用别人的 Theme 只能整个复制,更新要手工替换,所以 Theme 没法在站点之间流通。每个 Theme 单开一个仓库也太浪费。

  • GitHub 上的 Theme:theme.use 和 extends 可以写 github.com/OWNER/REPOSITORY/FOLDER@VERSION,版本号必填。每次 build 和 escpe theme check 都会按这个版本从 codeload.github.com 下载,不带 Token,只解压那一个文件夹,放在临时目录里,构建结束就删除。一个仓库可以放多个 Theme,打一个 tag 就统一了所有 Theme 的版本。见 ADR-0010。
  • 模板在 Jinja sandbox 里运行:别人的 Theme 跑在持有 Token 的构建里。sandbox 让模板碰不到 Python 内部、文件和环境变量。
  • Theme 列表:docs/themes/catalog.md 是一个文档,靠 PR 增加条目,不单开仓库。首批 6 个 Theme 在 geoqiao/escaping-themes,tag 为 v1.0.0:
    • Escape1、Escape2、geoqiao.me:原先的内置 Theme,已移植到 API 4,外观不变;
    • Paper、Ledger、Quiet Notes:0.3.0 验收时写的。
  • 上传草稿的 skill:只有用户明确授权发布,才会在创建 Issue 的同一条命令里加上 published;否则照旧不发布。契约、ADR-0001/0002 和 CONTEXT 已同步。
  • 小修:
    • 文档说明如何为 Theme 文件拼出完整 URL(site.url ~ 'assets/…'),两次移植都卡在这里;
    • 旧的 branding 设置的迁移提示不再只针对 Quiet。

不在范围内:私有 Theme 仓库、缓存、从本地文件夹 extends、发布 0.4.0。

验证结果

  • ruff check、ruff format --check、ty check:通过。
  • pytest:700 passed,包括浏览器测试。
    • 新增 tests/test_remote_theme.py:用一个本地服务模拟 GitHub 归档,覆盖只解压一个文件夹、404、没有这个文件夹、符号链接、extends 远程 Theme 并用 @name/ 复用、theme check 结束后删除下载、下载失败时的报错。
    • 地址校验和 sandbox 各有新用例。
  • 在真实 GitHub 上走通了完整流程:
    • 6 个 Theme 分别用 github.com/geoqiao/escaping-themes/<name>@v1.0.0 构建,产物和用本地副本构建的逐字节相同;
    • 在 extends escape2 的基础上替换 home.html 并用 @escape2/home.html 复用原文件,构建成功;
    • 固定到提交 SHA:成功;
    • @v9.9.9、不存在的文件夹、漏写 @、不存在的仓库:都给出了带修复办法的错误。
  • escaping-themes 的 CI 用 escaping v0.3.0 检查了 6 个 Theme 在站点根目录和子路径下的情况,共 12 项,全部通过。

风险与兼容性

  • 本地文件夹和 Quiet 的用法不变。

  • 使用 GitHub Theme 的构建需要能访问 codeload.github.com。

  • sandbox 会让读取 _ 开头属性的模板报 TEMPLATE_RENDER_FAILED(unsafe);Quiet 和所有测试用 Theme 都不受影响。

  • 回滚:revert 这个 PR;使用 GitHub Theme 的站点先改回本地文件夹。

  • 合并不等于发布 0.4.0 或迁移站点。

  • 已遵循维护指南与测试策略,说明适用检查的实际结果

  • 未弱化内容授权、sanitizer、路径 containment、artifact validation 或失败保旧产物

  • 公共行为变化已同步契约与迁移说明;远程发布或站点变更有单独授权(如适用)

🤖 Generated with Claude Code

geoqiao and others added 6 commits September 28, 2026 18:54
…s it

Publishing is a second authorization for one draft. Without it the Issue is
created unpublished, as before. With it, the published label is set in the
same gh issue create command, never by editing the Issue afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
theme.use and extends take github.com/OWNER/REPOSITORY[/FOLDER]@Version. Each
build and theme check downloads that version from codeload.github.com without
a token, unpacks only the folder into a temporary directory and deletes it
afterwards. One repository can hold many Themes; one tag versions them all.

Templates now run in Jinja's sandbox, because a Theme from someone else runs in
a build that holds a token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two Theme ports needed og:image as a full URL and found no documented way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… Quiet's

A Theme ported from 0.1, such as Escape2, splits branding into several
options of its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/themes/catalog.md links to Themes by their theme.use line; the first six
live in geoqiao/escaping-themes. Sites that used Escape1, Escape2 or
geoqiao.me can switch to their API 4 ports with one line.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@geoqiao
geoqiao merged commit 046ec45 into main Sep 28, 2026
1 check passed
@geoqiao
geoqiao deleted the feat/remote-themes branch September 28, 2026 11:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant