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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants