Skip to content

fix(comark): treat colon followed by digits as plain text, not a component#234

Merged
farnabaz merged 3 commits into
comarkdown:mainfrom
antfubot:task/r7sk5v
Jun 10, 2026
Merged

fix(comark): treat colon followed by digits as plain text, not a component#234
farnabaz merged 3 commits into
comarkdown:mainfrom
antfubot:task/r7sk5v

Conversation

@antfubot

@antfubot antfubot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

🔗 Linked issue

❓ Type of change

  • 📖 Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

A component name must start with a letter (or $), but the parser accepted digit-led names, with two crash modes:

  • InlineThe server is running on :8100 parsed :8100 as a component:

    ["p", {}, "The server is running on ", ["8100", {}]]

    Renderers then call createElement('8100') with a numeric tag name and crash the app.

  • Block:8100 (shorthand) and ::8100 (block) made parseBlockParams throw Invalid block params: 8100 during parsing.

Root cause: the block name grammar already requires a letter/$ start (RE_BLOCK_NAME = /^[a-z$]/i), but the inline rule (/[\w$-]/) and the block pre-filters (/^:\w/, and the un-guarded :: path) accepted digits.

Fix: a shared isComponentNameStart helper guards all three entry points in packages/comark/src/plugins/syntax.ts, mirroring the existing block grammar. A colon sequence whose name doesn't start with a letter or $ now stays plain text instead of becoming a component or throwing.

Behaviour after the fix:

Input Before After
… :8100 (inline) ['8100', {}]createElement('8100') crash text :8100
:8100 / ::8100 (block) throws Invalid block params text :8100 / ::8100
:inline-component, :badge[New], :h2, ::alert ✅ unchanged

Note: emoji shortcodes like :100: are unaffected — the emoji rule runs earlier (before('emphasis')) than the inline component rule (after('entity')).

Tests live in packages/comark/test/component-name.test.ts (9 cases: inline + block regressions plus no-regression checks for valid components). They fail on main (2 inline mismatches + 3 block throws) and pass with this change.

📝 Checklist

  • I have linked an issue or discussion.
  • I have run pnpm verify and it passes.
  • I have updated the documentation accordingly.

This PR was created with the help of an agent.

`:8100` is parsed as an inline component named `8100`, which makes
renderers call createElement('8100') and crash. A purely numeric name
should stay plain text. Added as a skipped SPEC repro (following the
existing leaf-block-directive.md precedent) so the suite stays green
until the inline-component parser rejects names that don't start with
a letter.
@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

@antfubot is attempting to deploy a commit to the NuxtLabs Team on Vercel.

A member of the Team first needs to authorize it.

…onent

A component name must start with a letter or `$`, but the inline and block
parsers accepted digit-led names:

- inline `:8100` was captured as a component (`['8100', {}]`), making
  renderers call `createElement('8100')` and crash the app;
- block `:8100` / `::8100` made `parseBlockParams` throw `Invalid block
  params` during parsing.

Guard all three entry points with a shared `isComponentNameStart` helper that
mirrors the existing block name grammar (`RE_BLOCK_NAME = /^[a-z$]/i`), so a
colon sequence whose name doesn't start with a letter or `$` stays plain text.

Replaces the earlier skipped SPEC repro with a real regression test
(`test/component-name.test.ts`) covering inline and block cases plus
no-regression checks for valid components.
@antfubot antfubot changed the title fix(comark): repro for numeric inline component names (:8100) fix(comark): treat colon followed by digits as plain text, not a component Jun 10, 2026
Replace the char-code `isComponentNameStart` with a regex-based
`isValidComponentName` (`/^[a-z$][\w$-]*/i`) that mirrors the block name
grammar. Behaviour is unchanged; the three guards now validate the candidate
name string instead of a single leading char code.
@antfubot antfubot marked this pull request as ready for review June 10, 2026 02:31

@antfu antfu left a comment

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.

Reviewed.

@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
comark-sveltekit Ready Ready Preview Jun 10, 2026 8:16am

@pkg-pr-new

pkg-pr-new Bot commented Jun 10, 2026

Copy link
Copy Markdown

Open in StackBlitz

comark

npm i https://pkg.pr.new/comark@234

@comark/ansi

npm i https://pkg.pr.new/@comark/ansi@234

@comark/html

npm i https://pkg.pr.new/@comark/html@234

@comark/nuxt

npm i https://pkg.pr.new/@comark/nuxt@234

@comark/react

npm i https://pkg.pr.new/@comark/react@234

@comark/svelte

npm i https://pkg.pr.new/@comark/svelte@234

@comark/vue

npm i https://pkg.pr.new/@comark/vue@234

commit: b81ef90

@farnabaz farnabaz left a comment

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.

Thanks

@farnabaz farnabaz merged commit cad7fa5 into comarkdown:main Jun 10, 2026
3 of 11 checks passed
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.

3 participants