Skip to content

Twoslash Zod/Valibot fixes#776

Merged
yamcodes merged 9 commits intomainfrom
733-add-zod-and-valibot-to-twoslash2
Jan 23, 2026
Merged

Twoslash Zod/Valibot fixes#776
yamcodes merged 9 commits intomainfrom
733-add-zod-and-valibot-to-twoslash2

Conversation

@yamcodes
Copy link
Owner

@yamcodes yamcodes commented Jan 23, 2026

Closes #733

Summary by CodeRabbit

  • Documentation

    • Added comprehensive documentation for development build scripts and their usage.
  • New Features

    • Introduced TypeScript code block annotation capabilities for MDX documentation with type hints and hover information.
    • Added new npm script for processing TypeScript documentation blocks.
  • Refactor

    • Consolidated Twoslash configuration into a centralized module, reducing build configuration boilerplate.

✏️ Tip: You can customize this high-level summary in your review settings.

- Extract twoslash options to dedicated file
- Add global types for improved diagnostics
- Implement custom hover and error filtering
- Include script for local tw
@yamcodes yamcodes linked an issue Jan 23, 2026 that may be closed by this pull request
@changeset-bot
Copy link

changeset-bot bot commented Jan 23, 2026

⚠️ No Changeset found

Latest commit: 395b288

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@github-actions github-actions bot added the www Improvements or additions to arkenv.js.org label Jan 23, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 23, 2026

Walkthrough

A new Twoslash configuration system is extracted from source.config.ts into a dedicated module (twoslash-options.ts) with filtering logic and JSDoc support. A CLI script (twoslash-mdx.ts) processes MDX files to extract and annotate TypeScript code blocks using Twoslasher, with corresponding documentation and npm script added.

Changes

Cohort / File(s) Summary
Configuration Extraction
apps/www/lib/twoslash-options.ts, apps/www/source.config.ts
Extracted Twoslash configuration from inline setup into dedicated module. New module exports TwoslashNode and ArkTypeTwoslashOptions types, along with arktypeTwoslashOptions config object containing compiler options, type augmentations, and complex filterNode predicate for normalizing hovers/errors and applying whitelisting logic. Source config simplified to import and use external options.
CLI Tooling
apps/www/bin/twoslash-mdx.ts, apps/www/bin/README.md
New CLI script processes MDX files to find and annotate \``ts twoslashcode blocks using Twoslasher. Outputs hovers with docs and errors filtered viafilterNode`. Documentation describes script behavior, usage, and output format.
Package Configuration
apps/www/package.json
Added "twoslash" npm script invoking tsx bin/twoslash-mdx.ts for direct CLI execution.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Script as twoslash-mdx.ts
    participant FS as File System
    participant Parser as Regex Parser
    participant Twoslasher
    participant Config as twoslash-options
    participant Output

    User->>Script: Run with MDX file path
    Script->>FS: Read MDX file
    FS-->>Script: File contents
    Script->>Parser: Find code blocks (```ts twoslash)
    Parser-->>Script: Matched blocks
    
    loop For each code block
        Script->>Config: Get twoslashOptions & filterNode
        Config-->>Script: arktypeTwoslashOptions
        Script->>Twoslasher: Process code with options
        Twoslasher-->>Script: Hovers & Errors
        Script->>Config: Filter hovers via filterNode
        Config-->>Script: Filtered hovers
        Script->>Config: Filter errors via filterNode
        Config-->>Script: Filtered errors
        Script->>Output: Print block header + results
    end
    
    Output-->>User: Annotated code blocks
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 Twoslash now dwells in a module so neat,
Configuration extracted, no longer bittersweet!
A CLI script hops through MDX with grace,
Filtering hovers in style, setting the pace.

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title check ⚠️ Warning The title mentions Twoslash fixes for Zod/Valibot but the PR implements a much broader refactor extracting twoslash configuration to a dedicated module with filtering, type improvements, and CLI scripts. Update title to reflect the core changes: 'Extract twoslash configuration to dedicated module with filtering and type safety' or similar, as the PR is primarily about infrastructure and configuration refactoring.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR successfully adds Zod and Valibot support to Twoslash filtering via the filterNode function in twoslash-options.ts and implements comprehensive configuration extraction that enables this support.
Out of Scope Changes check ✅ Passed All changes are directly related to the twoslash configuration refactoring needed to support Zod/Valibot in issue #733, including new CLI scripts and type definitions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

- Add Valibot and Zod to noise filter
- Ensure whitelisted CAPS keys are always shown
- Document utility scripts in bin directory
- Add `twoslash` pnpm script for convenience
- Fix potential error in twoslash
- Introduce ArkTypeTwoslashOptions interface
- Add filterNode property to twoslash options
- Remove 'any' assertion for filterNode usage
@github-actions github-actions bot added the docs Improvements or additions to documentation label Jan 23, 2026
- Introduce TwoslashNode type definition
- Apply TwoslashNode to ArkTypeTwoslashOptions
- Update filterNode parameter type
- Rename unused
@yamcodes yamcodes marked this pull request as ready for review January 23, 2026 12:14
@arkenv-bot
Copy link
Contributor

arkenv-bot bot commented Jan 23, 2026

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

Project Deployment Review Updated (Asia/Almaty)
arkenv Ready Ready Preview, Comment Jan 23 2026, 5:18 PM (Asia/Almaty)

@yamcodes yamcodes merged commit be93c44 into main Jan 23, 2026
14 of 15 checks passed
@yamcodes yamcodes deleted the 733-add-zod-and-valibot-to-twoslash2 branch January 23, 2026 12:30
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/www/bin/twoslash-mdx.ts`:
- Around line 17-26: The regex and loop only handle TypeScript and hardcode
"ts"; update codeBlockRegex to capture the language as the first capture group
limited to (ts|js) and allow CRLFs (use \r?\n), then change the match handling
to extract lang = match[1] ?? "ts" and code = match[2] (instead of match[1]),
and pass lang into twoslasher(code, lang, options); ensure this aligns with
arktypeTwoslashOptions.langs which contains ["ts","js"] so no tsx is included.
🧹 Nitpick comments (4)
apps/www/lib/twoslash-options.ts (3)

1-12: Make repo root resolution deterministic.

root depends on process.cwd(), which can vary across tooling and break the path mappings when run outside apps/www. Resolving relative to this module keeps paths stable.

🔧 Suggested fix
-import path from "node:path";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
@@
-const require = createRequire(import.meta.url);
-
-export const root = path.resolve(process.cwd(), "../../");
+const require = createRequire(import.meta.url);
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+
+export const root = path.resolve(__dirname, "../../..");

14-26: Add JSDoc for exported types/options.

These exports define the shared contract for the CLI and MDX transformer; a short doc comment will make the filter semantics easier to maintain. As per coding guidelines, please add JSDoc for public APIs and complex type logic.

✍️ Suggested doc additions
-export type TwoslashNode = {
+/** Twoslash output node passed to `filterNode`. */
+export type TwoslashNode = {
@@
-export type ArkTypeTwoslashOptions = TransformerTwoslashOptions & {
+/** Shared twoslash options used by MDX and CLI tooling. */
+export type ArkTypeTwoslashOptions = TransformerTwoslashOptions & {
@@
-export const arktypeTwoslashOptions: ArkTypeTwoslashOptions = {
+/** Centralized twoslash configuration for docs tooling. */
+export const arktypeTwoslashOptions: ArkTypeTwoslashOptions = {

190-212: Guard against missing errorLens.replace configuration.

If the arkdark package.json structure changes, this loop will throw at runtime; defaulting to an empty list avoids the crash.

🛡️ Suggested defensive guard
-			case "error":
-				for (const transformation of arkTypePackageJson.contributes
-					.configurationDefaults["errorLens.replace"]) {
+			case "error": {
+				const replacements =
+					arkTypePackageJson.contributes?.configurationDefaults?.[
+						"errorLens.replace"
+					] ?? [];
+				for (const transformation of replacements) {
@@
-				return true;
+				return true;
+			}
apps/www/bin/twoslash-mdx.ts (1)

5-9: Align the usage hint with the pnpm twoslash script.

The CLI is documented as pnpm twoslash, but the error message points to a different command; mentioning both reduces confusion.

✏️ Suggested tweak
-console.error("Usage: tsx twoslash-mdx.ts <path-to-mdx>");
+console.error(
+	"Usage: pnpm twoslash <path-to-mdx> (or: tsx bin/twoslash-mdx.ts <path-to-mdx>)",
+);

Comment on lines +17 to +26
const codeBlockRegex = /```ts twoslash(?:.*)\n([\s\S]*?)\n```/g;
let blockIndex = 1;

for (const match of content.matchAll(codeBlockRegex)) {
const code = match[1];
if (code === undefined) continue;
console.log(`\n--- Block ${blockIndex++} ---`);
try {
const result = twoslasher(code, "ts", options);

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n apps/www/bin/twoslash-mdx.ts

Repository: yamcodes/arkenv

Length of output: 1747


🏁 Script executed:

# Search for twoslasher configuration and usage patterns
rg "twoslasher|langs" apps/www --type ts -B 2 -A 2

Repository: yamcodes/arkenv

Length of output: 1227


🏁 Script executed:

# Check the actual twoslasher package to understand supported languages
fd package.json apps/www | head -5

Repository: yamcodes/arkenv

Length of output: 80


🏁 Script executed:

cat apps/www/package.json | grep -A 2 -B 2 "twoslash"

Repository: yamcodes/arkenv

Length of output: 480


🏁 Script executed:

# Search for "tsx" usage in code blocks or comments
rg "twoslash.*tsx|```tsx" apps/www --type ts --type tsx

Repository: yamcodes/arkenv

Length of output: 127


🏁 Script executed:

# Check the twoslash package in node_modules or find its type definitions
fd -e "d.ts" | grep twoslash | head -5

Repository: yamcodes/arkenv

Length of output: 41


🏁 Script executed:

# Check if twoslash is in node_modules and inspect its exports
find node_modules -name "twoslash" -type d 2>/dev/null | head -1

Repository: yamcodes/arkenv

Length of output: 41


🏁 Script executed:

# Look for twoslash package info and check its index file
find . -path "*/node_modules/twoslash*" -name "*.d.ts" -o -path "*/node_modules/twoslash*" -name "index.*" 2>/dev/null | head -10

Repository: yamcodes/arkenv

Length of output: 41


🏁 Script executed:

# Try to find documentation or check fumadocs integration
rg "lang|language" apps/www/lib/twoslash-options.ts -A 3 -B 3

Repository: yamcodes/arkenv

Length of output: 228


🌐 Web query:

twoslash 0.3.6 language parameter supported values twoslasher

💡 Result:

In twoslash@0.3.6, the twoslasher(code, lang, opts) lang parameter is not an enum—it’s typed as a plain string, so Twoslash itself does not restrict/validate the allowed values. It’s effectively treated as the file “language/extension” used for parsing. [1][2]

Practically, you should pass a TypeScript/JavaScript-like extension that the TS compiler understands, e.g. 'ts', 'tsx', 'js', 'jsx' (older docs/examples also mention 'typescript' / 'javascript'). [2]

If you want Vue SFC support, use twoslash-vue (it adds .vue handling). [3]

Sources: [1] [2] [3]


Update regex to capture code block language, but include only ts and js to align with configuration.

The current regex only processes TypeScript blocks and hardcodes "ts" as the language. Capture the language from the code fence and pass it to twoslasher() to support both ts and js blocks. The suggested diff also adds CRLF handling (\r?\n), which is appropriate for cross-platform files.

However, the suggested regex includes tsx, which is not declared in arktypeTwoslashOptions.langs (only ["ts", "js"]). Either remove tsx from the regex to strictly align with the declared configuration, or update the commit message to clarify that tsx support is intentionally extended beyond the explicit config.

🔧 Corrected update
-const codeBlockRegex = /```ts twoslash(?:.*)\n([\s\S]*?)\n```/g;
+const codeBlockRegex = /```(ts|js) twoslash(?:.*)\r?\n([\s\S]*?)\r?\n```/g;
@@
-for (const match of content.matchAll(codeBlockRegex)) {
-	const code = match[1];
+for (const match of content.matchAll(codeBlockRegex)) {
+	const lang = match[1] ?? "ts";
+	const code = match[2];
@@
-		const result = twoslasher(code, "ts", options);
+		const result = twoslasher(code, lang, options);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const codeBlockRegex = /```ts twoslash(?:.*)\n([\s\S]*?)\n```/g;
let blockIndex = 1;
for (const match of content.matchAll(codeBlockRegex)) {
const code = match[1];
if (code === undefined) continue;
console.log(`\n--- Block ${blockIndex++} ---`);
try {
const result = twoslasher(code, "ts", options);
const codeBlockRegex = /
🤖 Prompt for AI Agents
In `@apps/www/bin/twoslash-mdx.ts` around lines 17 - 26, The regex and loop only
handle TypeScript and hardcode "ts"; update codeBlockRegex to capture the
language as the first capture group limited to (ts|js) and allow CRLFs (use
\r?\n), then change the match handling to extract lang = match[1] ?? "ts" and
code = match[2] (instead of match[1]), and pass lang into twoslasher(code, lang,
options); ensure this aligns with arktypeTwoslashOptions.langs which contains
["ts","js"] so no tsx is included.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation www Improvements or additions to arkenv.js.org

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Zod and Valibot to Twoslash

1 participant