Skip to content

fix(web): prevent fallback code line number overlap - #2347

Closed
yicun wants to merge 2 commits into
MoonshotAI:mainfrom
yicun:codex/fix-web-fallback-line-number-overlap
Closed

fix(web): prevent fallback code line number overlap#2347
yicun wants to merge 2 commits into
MoonshotAI:mainfrom
yicun:codex/fix-web-fallback-line-number-overlap

Conversation

@yicun

@yicun yicun commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Related Issue

None. The problem is described below.

Problem

When a fenced code block is rendered through markstream-vue's line-numbered fallback, the line numbers can overlap the code text or drift out of vertical alignment.

In markstream-vue@1.0.7, the standalone fallback <pre> is rendered as the component root, while its scoped layout rules are emitted as descendant selectors. Those rules do not match that root element, so the fallback loses its gutter padding, font, and line height. The line-number gutter keeps its own metrics while the code falls back to different metrics.

What changed

  • Restored the complete standalone fallback <pre> layout: gutter space, typography, wrapping, overflow, border, background, and radius.
  • Made the fallback child <code> inherit the container typography and removed child padding, preventing loading fallbacks from reserving the gutter twice.
  • Excluded diff previews and left the Shiki rendering path unchanged.
  • Added a patch changeset for @moonshot-ai/kimi-code.

Verification

  • pnpm --filter @moonshot-ai/kimi-web check:style
  • pnpm --filter @moonshot-ai/kimi-web typecheck
  • pnpm --filter @moonshot-ai/kimi-web test (34 files, 653 tests)
  • pnpm --filter @moonshot-ai/kimi-web build
  • Verified in both Moon Bright and Moon Dark themes.
  • Verified standalone fallback code and gutter heights match (72 px for four lines), with gutter spacing preserved and child padding at 0.
  • Verified loading fallback code and gutter heights match (198 px for eleven lines), without duplicate gutter padding.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update. (No documentation update is needed because commands, configuration, and user workflows are unchanged.)

@changeset-bot

changeset-bot Bot commented Jul 29, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5045431

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 29, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@5045431
npx https://pkg.pr.new/@moonshot-ai/kimi-code@5045431

commit: 5045431

@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: 82fdcbce37

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread apps/kimi-web/src/components/chat/Markdown.vue Outdated
@wbxl2000

Copy link
Copy Markdown
Collaborator

Update from our side (cc @yicun — your report and analysis were spot on, thanks!):

The root cause is now fixed upstream. We traced it to markstream-vue's CodeBlockNode: when the Monaco enhancement is unavailable (which is the default state in kimi-web today, since the 1.0.7 upgrade in 425cfdf didn't add the new optional stream-diffs/stream-monaco peers), the component renders its standalone fallback <pre> as the component root, while the scoped styles are emitted as ancestor selectors ([data-v-x] pre.code-pre-fallback) that cannot match a root node. Filed and fixed upstream: Simon-He95/markstream-vue#602 (plain scoped selectors that match both the standalone root and the in-container fallback), released in markstream-vue@1.0.9-beta.1. Verified end-to-end in a minimal repro: standalone fallback computes padding-left: 45.35px (= the gutter), vs 0 and a 38px overlap before.

kimi-code-app took the upgrade path instead of a local workaround: https://github.com/MoonshotAI/kimi-code-app/pull/160 (1.0.7 → 1.0.9-beta.1, all checks green).

Suggestion for this PR: rather than shipping the compat CSS, bump apps/kimi-web to markstream-vue@^1.0.9-beta.1 (or wait for 1.0.9 stable). Two reasons:

  1. The workaround duplicates what upstream now renders natively — with this PR's CSS removed, the fallback already gets the right gutter, padding and font inheritance.
  2. The codex P2 above is right: as written, the rule also hits the in-container transition fallback on the enhanced path (every block during streaming / pre-highlight), adding border/margin/radius where upstream intends margin: 0; background: transparent. If we ever do need the interim CSS, the chrome must be scoped to the standalone root only, e.g. :not([data-markstream-code-block] *), and the gutter mirrored as padding-left: calc(6ch + 2px).

Happy to open the version-bump PR myself, or feel free to repurpose this one — either way works. (Also noting separately: since kimi-web doesn't have the stream-diffs peers installed, all enhanced blocks currently render through this fallback path; adding the peers to enable real Monaco highlighting, like kimi-code-app did in #155, is a bigger product decision worth its own discussion.)

@wbxl2000

Copy link
Copy Markdown
Collaborator

Closing in favor of #2415 — thank you @yicun, the report and the scoped-CSS analysis were exactly right and led us to the real fix.

Why not the local workaround after all:

  1. The root cause is fixed upstream now. fix: standalone code fallback loses gutter padding when rendered as component root Simon-He95/markstream-vue#602 landed and was released in markstream-vue@1.0.9-beta.1: the fallback <pre>'s scoped styles now also match when it renders as the component root, so the gutter reservation and font inheritance work without any app-side CSS. fix(web): upgrade markstream-vue to 1.0.9-beta.1 and enable Monaco code highlighting #2415 takes that upgrade.
  2. The workaround had a side effect (the codex P2 above): its selector also matched the in-container transition fallback on the enhanced path, adding border/margin/radius where upstream intends margin: 0; background: transparent — every block would briefly render as a nested box while streaming / pre-highlight.
  3. fix(web): upgrade markstream-vue to 1.0.9-beta.1 and enable Monaco code highlighting #2415 additionally installs the stream-diffs / stream-monaco / monaco-editor peers, so kimi-web gets real Monaco highlighting instead of rendering every code block through the fallback (which is what has been happening since 425cfdf).

Your changeset approach and verification notes were spot on — thanks again for pushing this to a proper fix.

@wbxl2000 wbxl2000 closed this Jul 30, 2026
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.

2 participants