Skip to content

refactor(plugin-git): render diffs in-house via service-shiki, drop @pierre/diffs - #264

Merged
antfu merged 4 commits into
mainfrom
feat/git-inhouse-diff-shiki
Aug 19, 2026
Merged

refactor(plugin-git): render diffs in-house via service-shiki, drop @pierre/diffs#264
antfu merged 4 commits into
mainfrom
feat/git-inhouse-diff-shiki

Conversation

@antfubot

Copy link
Copy Markdown
Collaborator

What & why

@devframes/plugin-git rendered diffs with @pierre/diffs, which bundled its own copy of Shiki into the client. This replaces it with an in-house unified-diff pipeline that highlights through the shared @devframes/service-shiki codeToTokens RPC — dropping the second Shiki copy and reusing the host's server-side, cached highlighter.

How

  • Parse client-side. Patches are parsed in the browser with diff's parser plus a thin git-header layer (change type — new/deleted/rename-pure/rename-changed/modified — old/new paths, binary). Tolerant of truncation: a hunk clipped by the server's size cap falls back to a lenient parse instead of dropping the file.
  • Highlight via the service. Each file's old/new sides are reconstructed and tokenized once per side through the service's dual-theme codeToTokens; tokens map back onto diff lines. Colors track the light/dark toggle instantly via --shiki-light/--shiki-dark CSS vars. Intra-line word emphasis is overlaid with diff's diffWords.
  • Own the markup. The renderer is decomposed into a container plus DiffFile / DiffHunk / DiffLine, with old+new line-number gutters, +/ markers, and @@ hunk headers, styled with @antfu/design tokens. Behavioral parity with the old viewer (flat + collapsible layouts, rename/binary handling, add/del counts, truncation notice).
  • Graceful degradation. service-shiki is declared as a devframe service so standalone git has it; when a host doesn't advertise it, the diff renders plain (un-highlighted).
  • Dependencies. Removes @pierre/diffs (and its now-dead @pierre/theme trust-policy entry); adds diff to the frontend catalog.

Tests

  • Unit tests cover the parser (modified/new/deleted/rename/binary/multi-hunk/no-newline/truncated), side reconstruction + line mapping, and the segment builder.
  • Storybook mocks the shiki service so the diff stories render real syntax colors.
  • Full gate green: lint, knip, typecheck, build, test.

This PR was created with the help of an agent.

…pierre/diffs

Replace the @pierre/diffs parser and React renderer with an in-house unified
diff pipeline that highlights through the shared @devframes/service-shiki
codeToTokens RPC, so the git client no longer bundles its own Shiki copy.

- Parse patches client-side with `diff`'s parser plus a thin git-header layer
  (rename/create/delete/binary, old/new paths), tolerant of truncated hunks.
- Reconstruct each file's old/new sides, tokenize each once via the service's
  dual-theme codeToTokens, and map tokens back onto diff lines; overlay
  intra-line word emphasis. Colors track the light/dark toggle via CSS vars.
- Decompose the renderer into a container plus DiffFile/DiffHunk/DiffLine,
  with old/new line-number gutters, +/- markers, and @@ hunk headers.
- Declare service-shiki as a devframe service and degrade to a plain,
  un-highlighted diff when the host doesn't advertise it.
- Cover the parser, side reconstruction, and segment builder with unit tests;
  Storybook mocks the service to show real highlighting.

Created with the help of an agent.
@netlify

netlify Bot commented Aug 19, 2026

Copy link
Copy Markdown

Deploy Preview for devfra ready!

Name Link
🔨 Latest commit ce0d580
🔍 Latest deploy log https://app.netlify.com/projects/devfra/deploys/6a85475e1ad11300089ec433
😎 Deploy Preview https://deploy-preview-264--devfra.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

antfubot and others added 3 commits August 19, 2026 04:55
Reconcile the in-house diff renderer with #263's @devframes/service-git
refactor: the shared git types (GitDiff, FileStatusCode, CommitDetail) now
come from @devframes/service-git, and the RPC scope moved to
devframes:service:git:*. Combine the two service declarations (service-git +
service-shiki) into one array on the git devframe, and drop the leftover
@pierre/diffs/@pierre/theme lockfile entries.
Wire services declared by descriptor (`services: [{ package }]`) are loaded
through a runtime `import()` of a resolved absolute path. Bundlers that compile
devframe's node code — notably a Next.js hub running under Turbopack — tried to
statically analyze that fully-dynamic import and failed with "Cannot find
module as expression is too dynamic", so every declared service
(service-git, service-shiki, service-open) was silently skipped and its
agent-flagged RPC never reached the aggregate MCP surface (e.g. the missing
`devframes_service_git_status` tool).

Mark the import webpack/vite/turbopack-ignored so hosts leave it as a real
runtime import, matching how the reference hub loads plugin packages. No effect
on the plain Node path (the markers are comments).

Created with the help of an agent.
@antfu
antfu merged commit 2a155a4 into main Aug 19, 2026
10 of 12 checks passed
@antfu
antfu deleted the feat/git-inhouse-diff-shiki branch August 19, 2026 06:04
antfubot added a commit to antfu/tsnapi that referenced this pull request Aug 20, 2026
Follows devframes/devframe#264: render signatures/diffs in-house and get
syntax highlighting from the shared `@devframes/service-shiki` wire
service's `code-to-tokens` RPC, instead of `@pierre/diffs` (which bundled
its own copy of Shiki — all ~200 grammars — into the SPA). The built SPA
drops from 300+ chunks / multiple MB to 2 assets / ~560 KB.

- Declare `@devframes/service-shiki` as a devframe service (langs
  typescript/javascript), resolved from the definition's `importMetaUrl`;
  standalone `tsnapi ui`/`ui build` and the Vite dev bridge all construct
  it, so highlighting works server-side and is LRU-cached.
- New in-house renderers: `CodeBlock` (single signature) and `CodeDiff`
  (unified line-level diff with old/new gutters + `+`/`-` markers), fed by
  dual-theme tokens; light colour is inline and `.dark` flips to the
  `--shiki-dark` var. Pure line-diff logic in `app/src/diff.ts` (unit
  tested). Highlighting degrades to plain text when the service is
  unavailable (e.g. a static `ui build` export has no server), so the diff
  structure still renders.
- Bump devframe + @devframes/vite to ^0.9.3 (matches the service peer and
  includes the descriptor-service dynamic-import bundler fix from #264).
- Remove `@pierre/diffs` (+ its now-dead `@pierre/theme` trust-policy
  entry); add `diff` to the SPA deps.

Verified live: the shiki service constructs under the CLI dev server, and
both CodeDiff (widened interface) and CodeBlock (dual runtime+types
surfaces) highlight correctly with a working light/dark toggle.

Co-authored-by: opencode <noreply@opencode.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants