Skip to content

fix: parse hyphenated example fence languages#2734

Open
lisiqi1983 wants to merge 2 commits into
npmx-dev:mainfrom
lisiqi1983:fix/example-fence-language
Open

fix: parse hyphenated example fence languages#2734
lisiqi1983 wants to merge 2 commits into
npmx-dev:mainfrom
lisiqi1983:fix/example-fence-language

Conversation

@lisiqi1983
Copy link
Copy Markdown

Summary

  • parse @example fence languages up to whitespace/backticks so hyphenated Shiki language ids are preserved
  • add a regression test for a glimmer-ts fenced example

Testing

  • STORYBOOK=true pnpm vp test --project unit test/unit/server/utils/docs/render.spec.ts
  • pnpm vp lint server/utils/docs/render.ts test/unit/server/utils/docs/render.spec.ts
  • pnpm vp fmt --check server/utils/docs/render.ts test/unit/server/utils/docs/render.spec.ts

Fixes #2437

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 13, 2026

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

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment May 23, 2026 3:02am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview May 23, 2026 3:02am
npmx-lunaria Ignored Ignored May 23, 2026 3:02am

Request Review

@github-actions
Copy link
Copy Markdown

Hello! Thank you for opening your first PR to npmx, @lisiqi1983! 🚀

Here’s what will happen next:

  1. Our GitHub bots will run to check your changes.
    If they spot any issues you will see some error messages on this PR.
    Don’t hesitate to ask any questions if you’re not sure what these mean!

  2. In a few minutes, you’ll be able to see a preview of your changes on Vercel

  3. One or more of our maintainers will take a look and may ask you to make changes.
    We try to be responsive, but don’t worry if this takes a few days.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ca66d6f2-9b1e-4c33-8b04-e96a390ded2f

📥 Commits

Reviewing files that changed from the base of the PR and between 4fb8e09 and 59d245d.

📒 Files selected for processing (2)
  • server/utils/docs/render.ts
  • test/unit/server/utils/docs/render.spec.ts

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved rendering of JSDoc example blocks: code fences with extra whitespace or hyphenated language identifiers now display correctly, default to TypeScript when unspecified, and no longer expose raw suffixes or stray backticks.
  • Tests

    • Added unit tests verifying rendering and highlighting of JSDoc example blocks, including hyphenated and missing language identifiers.

Walkthrough

The PR updates JSDoc @example parsing to support hyphenated fenced language identifiers (e.g. glimmer-ts) by using a more tolerant fence regex and defaults to typescript when no language is present. Tests are added/updated to validate rendering and the test helper accepts jsDoc.

Changes

Hyphenated JSDoc Example Language Support

Layer / File(s) Summary
Language identifier parsing for code fences
server/utils/docs/render.ts
The regex matching @example code fences is updated to allow whitespace after opening backticks and to extract language identifiers including hyphens, defaulting to typescript when absent.
Test helper extension and hyphenated language test case
test/unit/server/utils/docs/render.spec.ts
The createFunctionSymbol test helper is extended to accept optional jsDoc parameters, and a test case is added verifying that hyphenated language identifiers render correctly in Example sections without exposing the raw language suffix or unrendered backticks.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change—updating parsing of hyphenated example fence languages—which directly addresses the core issue.
Description check ✅ Passed The description clearly relates to the changeset by explaining the fix for parsing hyphenated Shiki language IDs and the regression test added.
Linked Issues check ✅ Passed The code changes fully address the requirement in issue #2437 to update the regex and parsing logic to accept hyphenated language identifiers up to whitespace/backticks.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the stated objectives: updating fence language parsing logic and adding a regression test for hyphenated languages.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@gameroman gameroman added the needs review This PR is waiting for a review from a maintainer label May 16, 2026
@gameroman
Copy link
Copy Markdown
Contributor

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 19, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
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.

🧹 Nitpick comments (1)
test/unit/server/utils/docs/render.spec.ts (1)

214-214: ⚡ Quick win

Make the -ts assertion less brittle.

expect(html).not.toContain('-ts') is too broad and can fail on valid highlighted HTML changes unrelated to this regression.

Proposed test assertion tightening
-    expect(html).not.toContain('-ts')
+    // Ensure the raw leaked suffix token is not rendered as standalone content.
+    expect(html).not.toMatch(/(^|[>\s])-ts([<\s]|$)/)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/unit/server/utils/docs/render.spec.ts` at line 214, The current
assertion expect(html).not.toContain('-ts') is too broad; tighten it to only
fail if the literal "-ts" appears inside rendered code/inline-code elements (the
html variable in render.spec.ts). Replace the broad contains check with an
assertion that searches html for "-ts" specifically within <code> or <pre>
elements (or the renderer's code wrapper class used in the test) — e.g., assert
that a regex matching "-ts" inside code tags does not match — so unrelated
highlighted HTML changes won't trigger the test; target the html variable and
the test surrounding this expect to implement the narrower check.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@test/unit/server/utils/docs/render.spec.ts`:
- Line 214: The current assertion expect(html).not.toContain('-ts') is too
broad; tighten it to only fail if the literal "-ts" appears inside rendered
code/inline-code elements (the html variable in render.spec.ts). Replace the
broad contains check with an assertion that searches html for "-ts" specifically
within <code> or <pre> elements (or the renderer's code wrapper class used in
the test) — e.g., assert that a regex matching "-ts" inside code tags does not
match — so unrelated highlighted HTML changes won't trigger the test; target the
html variable and the test surrounding this expect to implement the narrower
check.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1b98042a-5581-4613-a61d-c512ce450800

📥 Commits

Reviewing files that changed from the base of the PR and between f91f8c4 and 90e3c54.

📒 Files selected for processing (2)
  • server/utils/docs/render.ts
  • test/unit/server/utils/docs/render.spec.ts

@gameroman gameroman self-requested a review May 19, 2026 21:55
Comment thread server/utils/docs/render.ts Outdated
Comment on lines +194 to +196
const langMatch = example.doc.match(/```(\w+)?/)
const langMatch = example.doc.match(/```[ \t]*([^` \t\r\n]*)/)
const lang = langMatch?.[1] || 'typescript'
const code = example.doc.replace(/```\w*\n?/g, '').trim()
const code = example.doc.replace(/```[ \t]*[^` \t\r\n]*[ \t]*(?:\r\n|\r|\n)?/g, '').trim()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Image

It seems to me that the new exp allows extra characters

If the previous one didn't include only the dash, I would suggest adding only it

Image
([\w\-]+)

Or

([\w\-_]+)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks, good catch. I narrowed the fence language matching back to the original \w set plus -, so it no longer accepts arbitrary non-whitespace characters. I also tightened the regression assertion so it only checks for a leaked standalone -ts token instead of rejecting any incidental -ts substring.

Validated locally:

  • STORYBOOK=true pnpm vp test --project unit test/unit/server/utils/docs/render.spec.ts
  • pnpm vp lint server/utils/docs/render.ts test/unit/server/utils/docs/render.spec.ts
  • pnpm vp fmt --check server/utils/docs/render.ts test/unit/server/utils/docs/render.spec.ts
  • git diff --check -- server/utils/docs/render.ts test/unit/server/utils/docs/render.spec.ts

Copy link
Copy Markdown
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.

🧹 Nitpick comments (1)
server/utils/docs/render.ts (1)

194-196: 💤 Low value

Consider escaping hyphens in character classes for clarity.

The character class [\w-] is valid (hyphen at the end is treated as literal), but explicitly escaping it as [\w\-] would be clearer and addresses the previous reviewer's suggestion. This applies to both the language-matching regex (line 194) and the fence-removal regex (line 196).

📝 Proposed refinement
-    const langMatch = example.doc.match(/```[ \t]*([\w-]+)?/)
+    const langMatch = example.doc.match(/```[ \t]*([\w\-]+)?/)
     const lang = langMatch?.[1] || 'typescript'
-    const code = example.doc.replace(/```[ \t]*[\w-]*[ \t]*(?:\r\n|\r|\n)?/g, '').trim()
+    const code = example.doc.replace(/```[ \t]*[\w\-]*[ \t]*(?:\r\n|\r|\n)?/g, '').trim()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/utils/docs/render.ts` around lines 194 - 196, Update the two regexes
that parse code fences to escape the hyphen for clarity: replace occurrences of
[\w-] in the language capture regex used to compute langMatch (the expression
that sets langMatch from example.doc) and in the fence-removal regex used to
compute code (the expression that calls example.doc.replace(...)). Change [\w-]
to [\w\-] in both places so the character class explicitly treats the hyphen as
a literal.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@server/utils/docs/render.ts`:
- Around line 194-196: Update the two regexes that parse code fences to escape
the hyphen for clarity: replace occurrences of [\w-] in the language capture
regex used to compute langMatch (the expression that sets langMatch from
example.doc) and in the fence-removal regex used to compute code (the expression
that calls example.doc.replace(...)). Change [\w-] to [\w\-] in both places so
the character class explicitly treats the hyphen as a literal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 15a4043b-7718-4d85-9c68-399c7d9e9048

📥 Commits

Reviewing files that changed from the base of the PR and between 90e3c54 and 4fb8e09.

📒 Files selected for processing (2)
  • server/utils/docs/render.ts
  • test/unit/server/utils/docs/render.spec.ts

expect(html).toContain('<h4>Example</h4>')
expect(html).toContain('shiki')
expect(html).toContain('greeting')
expect(html).not.toMatch(/(^|[>\s])-ts([<\s]|$)/)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You can probably keep both tests? Or that wouldn't work?

Suggested change
expect(html).not.toMatch(/(^|[>\s])-ts([<\s]|$)/)
expect(html).not.toMatch(/(^|[>\s])-ts([<\s]|$)/)
expect(html).not.toContain('-ts')

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

Labels

needs review This PR is waiting for a review from a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs feature codeblock hyphenated lang regex

3 participants