Skip to content

feat: 抽取 Markdown 正文排版层并新增对照页 - #20

Closed
qqqqqf-q wants to merge 1 commit into
felinics:mainfrom
qqqqqf-q:feat/markdown-body-layer
Closed

qqqqqf-q wants to merge 1 commit into
felinics:mainfrom
qqqqqf-q:feat/markdown-body-layer

Conversation

@qqqqqf-q

@qqqqqf-q qqqqqf-q commented Sep 11, 2026

Copy link
Copy Markdown
Member

目的

Markdown/中文正文排版收敛的第一步:把 markstream 桥接层和聊天每脚本字重从 apps/web 收进组件库,单一事实源;showcase 新增对照页,排版参数对着四种正文形态调,不再对着单条消息调(避免修一条崩一条的 reward hacking)。

改动

  • 新增 src/markdown.css(导出 @felinic/ui/markdown.css,须在 markstream-vue/index.css 之后加载):
    • markstream token 桥接(--ms-text-/--ms-flow- 等,原样迁移自 apps/web)
    • 块级间距收敛为四个 token:--ms-slot-gap(块间 16px)/-section(正文→标题 18px)/-group(标题→内容、相邻列表碎片粘连 4px)/-title(h1 下方 16px)——markstream 2.0 的 .node-slot 包装使元素 margin 失效,slot 边界是唯一可靠的间距层
    • 标题档位 h1-3 1.45/1.28/1.14em;行内 code 380 字重/0.04em 字距/全角括号垂直补偿;表格/引用/链接/脚注/mermaid 样式原样迁移
    • 每脚本字重对作用域扩为 :is([data-chat-content], .markstream-vue):文件预览等无 chat 外壳的表面此前落回 markstream 原始 600,CJK 加粗/标题明显偏重。实测 MiSans @font-face 的 150..450 重量钳制在 Chrome 155 上不生效(600 请求墨迹量 24840 > 450 的 23288),不能依赖字体级钳制兜底
  • 新增 components/markdown:md-text(CJK/Latin 切分,权重对的第一帧即正确)、md-checkbox、md-footnote-*,registerSharedMarkdownComponents;splitScriptRuns 移入 src/lib。宿主经 extra 注入自己的 code_block / link
  • 新增 showcase Markdown body 页(Foundations):四种正文形态(结构化报告/扁平碎片列表/CJK 混排/代码与表格)+ 文件预览密度,真实管线并排对照;列宽对齐真实聊天列(760px 内容)
  • PageShell 新增 wall 宽度档(104rem,容纳两列真实聊天宽度)
  • package.json 导出 ./markdown.css,新增 markstream-vue 2.0.0 依赖

验证

  • ui typecheck / eslint 通过;check-ui-contract 通过
  • showcase 页面截图核对四种形态渲染(字重 350/520/510 与聊天一致)

关联

  • 配套主仓 PR:gitlink bump + app 侧复用(待建,合并顺序:本 PR 先落,主仓后落)

QA

  • 人工 QA:用户已在 showcase dev URL 走查确认差不多
  • ⚠️ No human QA — this PR has not been verified by a human yet. Remove this line once a human confirms the happy path.

- 新增 src/markdown.css:markstream token 桥接、slot 边界块级节奏
  (--ms-slot-gap/-section/-group/-title)、标题/行内码/表格/引用/脚注样式,
  以及聊天每脚本(CJK/Latin)字重对——作用域扩为
  :is([data-chat-content], .markstream-vue),文件预览等无 chat 外壳的
  表面不再落回原始 600 字重
- 新增 components/markdown:md-text(CJK/Latin 切分)、md-checkbox、
  md-footnote-*,registerSharedMarkdownComponents;script-runs 移入 src/lib
- 新增 showcase Markdown body 页:四种正文形态 + 文件预览密度并排对照,
  排版参数在此调,不再对着单条消息调
- PageShell 新增 wall 宽度档(104rem,容纳两列真实聊天宽度)
- package.json 导出 ./markdown.css,新增 markstream-vue 依赖
@qqqqqf-q
qqqqqf-q requested a review from a team as a code owner September 11, 2026 14:13
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 11, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-11T14:17:56.148918Z a28a5ee PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a28a5eed2e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread package.json
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-vue-next": "^0.562.0",
"markstream-vue": "2.0.0",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Update the lockfile with markstream-vue

Adding this dependency without updating pnpm-lock.yaml makes every frozen install fail before the project can build. Running pnpm install --frozen-lockfile reports ERR_PNPM_OUTDATED_LOCKFILE and identifies markstream-vue@2.0.0 as the missing specifier, while CI enables frozen lockfiles by default; regenerate and commit the lockfile with this package change.

Useful? React with 👍 / 👎.

// code_block nodes) and renders nothing. Route by node type so the fence
// reaches the surface's code block component instead.
function textNodeRouter(codeBlock: Component | undefined): Component {
if (!codeBlock) return MdText

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Route text fences without requiring a custom code block

When extra.code_block is omitted—as it is for both registrations on the new showcase page—this returns MdText directly, so a fenced block declared as text still resolves through the colliding text mapping. The resulting code_block node is passed to MdText, whose required node.content is absent, and the fence renders blank; the router needs to preserve or invoke markstream's default code-block renderer in this case.

Useful? React with 👍 / 👎.

Comment thread src/markdown.css
Comment on lines +46 to +50
:root {
/* Chat reading LEADING — the single source for every chat line-height below.
* After tuning, Latin/base sits tighter; CJK paragraphs are the one place the
* two scripts still diverge, keeping a hair more vertical room. To restyle
* leading, change these two numbers only — every rule references them. */

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep Markdown token values in the central token source

Move these new Markdown token definitions—and the later raw oklch(), color-mix(), sizing, spacing, and radius values—into src/style.css, leaving markdown.css to consume named tokens. Defining a second raw-value source means theme and scale changes now have two independent homes and directly violates the repository's single-source token contract.

AGENTS.md reference: AGENTS.md:L27-L31

Useful? React with 👍 / 👎.

<template>
<a
:href="`#fnref-${node.id}`"
class="ml-1 inline-flex items-center align-middle text-foreground hover:text-brand"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Move footnote hover chrome into style.css

Move this hover:text-brand state, together with the matching reference's hover:/group-hover: utilities, to a shared style.css rule keyed by a footnote data-slot. Keeping interaction color changes in the Vue templates creates a second chrome owner and bypasses the component-layer cascade that the repository requires for hover, press, focus, and open states.

AGENTS.md reference: AGENTS.md:L49-L53

Useful? React with 👍 / 👎.

@qqqqqf-q

Copy link
Copy Markdown
Member Author

关闭:排版层留在 apps/web 维护——该文件是全仓调整最频繁的表面,迁入组件库后每次微调都需走 ui PR → gitlink bump → 主仓 PR 三段式,长期摩擦大于单一事实源收益。本次修复(字重扩域、间距 token 化等)全部并入 memoh 主仓 PR #1211。

@qqqqqf-q qqqqqf-q closed this Sep 11, 2026
@qqqqqf-q
qqqqqf-q deleted the feat/markdown-body-layer branch September 11, 2026 14:27
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