项目协作与运行约定

项目协作与运行约定

环境与操作范围

  • 项目是 Jekyll / AcademicPages 个人主页,默认分支为 master。
  • 本地开发目录:/home/wei/Documents/repos/my-academic-page。
  • SSH 主机别名:dg-sf;远端项目目录为 /root/my-academic-page(注意不是 my-acadamic-page)。
  • 独立预览目录:dg-sf:/root/academic-preview。
  • GitHub:git@github.com:liuweiky/my-academic-page.git。
  • 正式网站:https://weiliu.pro/。
  • 本地只在当前项目目录内修改文件;临时文件放在已忽略的 local/ 下。
  • 本地是开发机,绝不运行 page.sh update,不向本地系统的 www 目录复制网页,不修改项目之外的路径。
  • 远端调试限于上述 /root 项目和预览目录;使用现有依赖,不安装 Ruby、Bundler、npm 包或系统依赖。
  • 只有用户明确要求发布时,才允许在 dg-sf 上运行 page.sh update。调试和预览不构成发布授权;用户在当前任务中已授权发布时,不要重复询问。

开始工作前

本地检查 git status -sb、git log -3 --oneline 和相关文件。远端检查:

ssh dg-sf 'cd /root/my-academic-page && git status -sb && git log -3 --oneline && bundle check'

不要覆盖用户改动、重置分支或强制推送。先确认两边已有改动,再同步明确的源文件。同步不使用会删除远端文件的命令。

截至 2026-10-18,已发布并推送的远端提交为 f38267f;本地提交 78dad7a 与其文件树相同,但历史不同(远端另外挑选了两条 X 分享相关提交)。这只是本次流程的历史记录,后续以实时 Git 状态为准。遇到相同文件树、不同历史时,不盲目从本地推送或 reset;优先从已与 GitHub 同步的远端仓库推送,保留本地历史。

开发与同步

  • 本地编辑源文件,通过 scp 将明确的改动同步到远端项目;再同步到独立预览目录。
  • 保持本地、远端项目与预览目录的源文件一致,尤其是 _pages/about.md、样式、模板和编译后的 JavaScript。
  • PDF 等新资源放在 files/,同步文件时同时更新页面链接。
  • 不把 local/、_site/、预览脚本、日志、传输压缩包、依赖目录或缓存加入 Git。
  • JavaScript 实际加载的是 assets/js/main.min.js;改动 assets/js/_main.js 时要同步更新实际加载的文件。使用现成的构建工具,不为此安装依赖。若缺少工具,可以做经过检查的最小修改,并对两个文件运行 node --check。

示例(路径以本次实际改动为准):

scp _sass/_talks.scss dg-sf:/root/my-academic-page/_sass/_talks.scss
ssh dg-sf 'cp /root/my-academic-page/_sass/_talks.scss /root/academic-preview/_sass/'

初次准备或整体更新预览源文件时,可在远端执行以下不带删除选项的同步。不要覆盖预览专用配置与服务脚本;删除过的源文件需逐个确认后在预览目录处理。

mkdir -p /root/academic-preview
rsync -a --exclude=.git --exclude=_site --exclude=local \
  --exclude=node_modules --exclude=_config.preview.yml \
  --exclude=serve.py --exclude=preview.log --exclude=preview.pid \
  /root/my-academic-page/ /root/academic-preview/

远端调试与本地预览

本地没有 Ruby/Bundler;在 dg-sf 使用已有的 Jekyll 环境,不安装依赖。预览构建只输出到 /root/academic-preview/_site,不使用线上目录。

在预览目录创建或维护 _config.preview.yml:

url: ""
baseurl: ""
exclude:
  - local
  - node_modules
  - serve.py
  - preview.log
  - preview.pid
  - source.tar.gz
  - resource-buttons.tar.gz
  - talk-spacing.tar.gz
  - release-current.tar.gz
  - update_lmtracer.py
  - fix_footer_script.py

这里的空 URL 保证页面、资源和导航都使用当前预览地址。Jekyll 3 的 build 不接受 --url,应使用配置覆盖:

ssh dg-sf 'cd /root/academic-preview && bundle exec jekyll build --config _config.yml,_config.preview.yml --destination /root/academic-preview/_site'

远端预览使用 4173 端口。serve.py 是预览专用文件,放在 /root/academic-preview,不放入正式项目。它需要支持无 .html 扩展名的链接;普通 python3 -m http.server 会让 /talks/2025-11-17-ase25 返回 404,即使对应 .html 文件存在。

可复用的 serve.py 内容如下(使用 Python 标准库,无需安装依赖):

from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path

class PreviewHandler(SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, directory='/root/academic-preview/_site', **kwargs)

    def translate_path(self, path):
        resolved = super().translate_path(path)
        if not Path(resolved).exists():
            html = resolved.rstrip('/') + '.html'
            if Path(html).is_file():
                return html
        return resolved

ThreadingHTTPServer(('127.0.0.1', 4173), PreviewHandler).serve_forever()

先用 ss -ltnp 'sport = :4173' 检查是否已运行,不重复启动。需要启动时:

cd /root/academic-preview
nohup python3 serve.py > preview.log 2>&1 < /dev/null &
echo $! > preview.pid

在本地建立带保活的 SSH 转发:

ssh -fN -o BatchMode=yes -o ConnectTimeout=10 \
  -o ExitOnForwardFailure=yes -o ServerAliveInterval=15 \
  -o ServerAliveCountMax=3 \
  -L 127.0.0.1:4174:127.0.0.1:4173 dg-sf

本地预览入口:http://localhost:4174/。不要依赖外网直连 dg-sf 的 4173 端口,也不要修改防火墙或 Apache 配置来提供预览。

若预览不通:

  1. 在远端请求 http://127.0.0.1:4173/,确认服务状态。
  2. 在本地请求 http://127.0.0.1:4174/,确认隧道状态。
  3. 若本地端口仍监听但请求挂起,检查监听进程的完整命令,只终止本任务对应的失效 SSH 隧道,再用上述命令重建;不终止其他 SSH 会话。
  4. 用 curl --noproxy '*' --max-time 10 排除代理影响,检查页面、CSS 和报告详情 URL。
  5. 样式或脚本缓存可能需要强制刷新;脚本发生重要修复时可更新 _includes/scripts.html 中的版本参数。

提交、发布与推送

提交和正式发布必须使用现有 page.sh,不要替换成手写的提交或部署命令。脚本的 commit 不会暂存文件,需先 git add 明确的本次改动。

本地提交(不在本地构建、发布):

git diff --check
# 按改动范围暂存,不把临时文件加入版本控制。
git add <本次修改和新增的源文件>
bash page.sh commit

若本地缺少 Git 身份,可参考已有提交的作者身份,仅设置当前仓库的 user.name 和 user.email,不要改全局配置。

用户明确要求发布后,在 dg-sf 的正式项目目录执行:

cd /root/my-academic-page
git diff --check
# 先核对本地与远端源文件,确认发布内容就是已验收的预览版本。
git add <本次修改和新增的源文件>
bash page.sh commit
bash page.sh build
# 只有构建成功、产物检查通过后,才单独执行下一条命令。
bash page.sh update

page.sh build 输出到项目自身的 _site/,使用正式 _config.yml,不能带入预览配置。page.sh update 会把 _site/ 用 rsync -a --delete 发布至 /var/www/html/www.weiliu.pro 并设置所属用户。因此这一步仅限 dg-sf、仅用于用户明确授权的正式发布。

检查各命令退出状态;不要在构建失败后继续发布。若没有新增改动,无需制造空提交。两边历史不同时可分别用脚本提交,但要核对最终文件树或文件内容一致,不只比较提交哈希。

发布验证:

  • 检查首页、/publications/、/talks/、无扩展名报告详情及新增 PDF 的 HTTP 状态。
  • 核对线上 HTML 中的新按钮、链接和脚本版本;确认没有 localhost 预览地址。
  • 必要时用 cmp 对比远端构建产物与已发布文件,用 SHA-256 核对 PDF。
  • 确认工作区状态,并向用户报告提交哈希、发布结果和验证结果。

GitHub 推送是独立操作。用户要求推送后,优先在与线上版本一致的 dg-sf 项目中执行:

cd /root/my-academic-page
git status -sb
git push origin master
git rev-parse HEAD
git ls-remote origin refs/heads/master

确认远端分支哈希与 HEAD 一致。不强制推送;如有新上游提交,先检查差异、保留当前改动,再合并处理。

已知布局注意事项

  • 页脚使用正常布局 / Flex,不能恢复旧脚本给 body 动态设置 footer 高度的 margin-bottom;它会在页脚下制造大块空白。源文件与 main.min.js 都已移除此逻辑。
  • Talks 摘要使用独立的 .talk__description,保留灰色斜体层次。调节留白时优先改 margin/padding,不随意改变文字风格。
  • 不嵌套 <p>;markdownify 输出段落时,外层应使用 <div>。
  • Talks 最后一条不显示分隔线,国旗保持轻微圆角。
  • 论文资源按钮用 _includes/resource-link.html 和 _sass/_resource-links.scss 维护,保留原始链接目标与窄屏换行。