Skip to content

Conversation

avivkeller
Copy link
Member

@avivkeller avivkeller commented Sep 1, 2025

Fixes #7932


Introduces @shikijs/twoslash support in @node-core/rehype-shiki. Since twoslash depends on TypeScript declaration files, it cannot be bundled and must instead be listed under serverExternalPackages.

Because TypeScript declarations aren’t imported like regular files (they’re loaded through a TSVFS), they need to be explicitly included in the output bundle.

Because Cloudflare doesn't support WASM or Top-Level awaits, rehype-shiki has been rewritten to not rely on them.

@avivkeller avivkeller self-assigned this Sep 1, 2025
Copy link

vercel bot commented Sep 1, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
nodejs-org Ready Ready Preview Oct 11, 2025 1:26pm

Copy link

codecov bot commented Sep 1, 2025

Codecov Report

❌ Patch coverage is 45.56962% with 86 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.39%. Comparing base (11fa0e5) to head (b1e201d).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
packages/rehype-shiki/src/index.mjs 11.39% 70 Missing ⚠️
packages/rehype-shiki/src/plugin.mjs 76.74% 10 Missing ⚠️
packages/rehype-shiki/src/highlighter.mjs 80.00% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8132      +/-   ##
==========================================
- Coverage   76.64%   76.39%   -0.26%     
==========================================
  Files         115      115              
  Lines        9623     9643      +20     
  Branches      322      317       -5     
==========================================
- Hits         7376     7367       -9     
- Misses       2246     2275      +29     
  Partials        1        1              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@AugustinMauroy
Copy link
Member

Hype 😁 !

@avivkeller
Copy link
Member Author

Locally:
image

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds TypeScript TwoSlash support to the syntax highlighting system, enabling interactive TypeScript error displays and type information tooltips in code blocks.

Key Changes:

  • Integrated TwoSlash transformer for TypeScript/JavaScript code highlighting
  • Refactored metadata parsing system from string-based to object-based approach
  • Added CSS styling for TwoSlash popup containers and error displays

Reviewed Changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/rehype-shiki/src/index.mjs Added TwoSlash transformer import and configuration
packages/rehype-shiki/src/highlighter.mjs Updated functions to accept metadata parameter and pass transformers
packages/rehype-shiki/src/plugin.mjs Replaced string-based metadata parsing with comprehensive object-based system
packages/rehype-shiki/src/twoslash.css Added CSS styling for TwoSlash popup containers
packages/rehype-shiki/package.json Added TwoSlash dependency and exported CSS file
packages/ui-components/src/Common/BaseCodeBox/index.module.css Added CSS transforms for proper positioning
apps/site/next.config.mjs Configured external packages and file tracing for TwoSlash
apps/site/package.json Added twoslash dependency
apps/site/styles/index.css Imported TwoSlash CSS styles
apps/site/pages/en/learn/typescript/transpile.md Updated TypeScript example to use TwoSlash error annotations
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@jakebailey
Copy link
Member

Is this all server side?

I'm asking because given the TS port to Go, I'm not sure what the deal will be for shiki on the web; probably having to include a large Go binary in Wasm to work with all of the fancy stuff if not prerendered...

@avivkeller
Copy link
Member Author

@nodejs/nodejs-website @nodejs/web-infra for reviews. Currently, this is disabled on CF, but there's a TODO to enable it.

Copy link
Member

@AugustinMauroy AugustinMauroy left a comment

Choose a reason for hiding this comment

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

Light/dark theme didn't work well but I didn't see why
Capture d’écran 2025-09-25 à 08 53 20
Capture d’écran 2025-09-25 à 08 53 35

@avivkeller
Copy link
Member Author

I'll get to Augustin's review today, @nodejs/web any other comments / concerns

Copy link
Member

@flakey5 flakey5 left a comment

Choose a reason for hiding this comment

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

thank you!

@avivkeller
Copy link
Member Author

I need an @nodejs/nodejs-website approval, and then I'll rebase

return parameter !== undefined && parameter.length > 0
? parameter
: undefined;
while ((match = rMeta.exec(meta)) !== null) {
Copy link
Member

Choose a reason for hiding this comment

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

This feels like some voodoo wizardry and so prone of going wrong I guess

Copy link
Member Author

Choose a reason for hiding this comment

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

How so? The RegEx (AFAICT) is pretty robust.

Copy link
Member

@ovflowd ovflowd Oct 11, 2025

Choose a reason for hiding this comment

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

This regex pattern seems to be vulnerable to ReDoS.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think it is:
image
image
image

return transformers;
}

export const LANGS = [
Copy link
Member

Choose a reason for hiding this comment

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

Does this need to be on the same file?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ideally yes, the index.mjs LANGS and the minimal.mjs LANGS

Copy link
Member

Choose a reason for hiding this comment

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

IDK, feels like this should have a dedicated langs.mjs file tho

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think so. The index.mjs exports all of the highlighting utilities needed for our server, and the minimal.mjs exports all for our client. A langs.mjs file for index.mjs doesn't make sense to me.

WDYT @nodejs/nodejs-website

import BadgeGroup from '@node-core/ui-components/Common/BadgeGroup';
import Blockquote from '@node-core/ui-components/Common/Blockquote';
import MDXCodeTabs from '@node-core/ui-components/MDX/CodeTabs';
import {
Copy link
Member

Choose a reason for hiding this comment

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

These should all be separated files

Copy link
Member

Choose a reason for hiding this comment

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

Also are these client components? This file should only contain server components. There's another file for client components no?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, we merged them into a single file in #8167

Copy link
Member

@ovflowd ovflowd left a comment

Choose a reason for hiding this comment

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

I have a few reservations, would love some comments to be addressed and some benchmark images of build times / bundle sizes with this addition.

This is a cool visual addition but if it's to heavy, might not be worth it.

@avivkeller
Copy link
Member Author

avivkeller commented Oct 11, 2025

I have a few reservations, would love some comments to be addressed and some benchmark images of build times / bundle sizes with this addition.

The bundle is a bit bigger, since it needs to load the extra JS (See #8160). The most recent Twoslash build took ~1:33, almost identical to the most recent main build (~1:29)

@ovflowd ovflowd merged commit 0aa1281 into main Oct 12, 2025
12 checks passed
@ovflowd ovflowd deleted the twoslash branch October 12, 2025 17:06
@ovflowd
Copy link
Member

ovflowd commented Oct 12, 2025

Bypassing ownership from typescript team as it is a false positive.

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.

Type Info on the Docs & Guides

7 participants