Skip to content

feat(markdown): add tag extension#116504

Open
natemoo-re wants to merge 4 commits into
masterfrom
nm/seer/tag
Open

feat(markdown): add tag extension#116504
natemoo-re wants to merge 4 commits into
masterfrom
nm/seer/tag

Conversation

@natemoo-re
Copy link
Copy Markdown
Member

Adds a Markdoc-style tag lexer extension to the core Markdown component. This is the foundation for rendering Seer's structured output (entity refs, artifacts) as rich, interactive embeds inline in the markdown stream instead of plain text.

Two tag syntaxes via a marked tokenizer extension registered globally on the lexer:

  • Self-closing: {% ref type="issue" id="PROJ-123" /%}—inline within text
  • Block: {% artifact type="root-cause" %}{"description":"..."}{% /artifact %}—standalone or inline, with a JSON body merged into value

Tag names match [\w-]+ (valid HTML element identifiers); component-specific rendering (ref, artifact, etc.) will happen in the consumer registry as a follow-up. level on the token reflects where marked parsed it (block vs inline context).

Partial tag syntax ({% ref type="issue") is stripped unconditionally in the text token handler to avoid displaying raw source text when streaming. No issues with false positives in code spans/blocks since those use the code tokens.

The Tag component slot in MarkdownComponents follows the same WithDefault pattern as every other component override. DefaultTag returns null — the registry that maps tag names to concrete components will happen in a follow-up.

Syntax

Inline ref (self-closing, no body)

The crash is caused by {% ref type="issue" id="PROJ-ABC" /%} in the auth middleware.

Block ref (with snapshot data)

{% ref type="issue" id="PROJ-ABC" %}
{"title":"NullPointerException in auth","priority":"high","count":1832,"status":"escalating"}
{% /ref %}

Artifact (always block-level)

{% artifact type="root-cause" %}
{"one_line_description":"Race condition in session refresh","five_whys":["Session token expires during concurrent refresh","Two requests hit /refresh simultaneously","No mutex on token rotation","Auth middleware assumes single-writer"]}
{% /artifact %}

Attributes go on the opening tag (type, id). Complex data goes in the JSON body. They merge into a single value object for the renderer — attrs first, then JSON body.

@natemoo-re natemoo-re requested review from a team as code owners May 29, 2026 18:32
@github-actions github-actions Bot added the Scope: Frontend Automatically applied to PRs that change frontend components label May 29, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 29, 2026

📊 Type Coverage Diff

Metric Before After Delta
Coverage 93.59% 93.60% 🟢 +0.01%
Typed 133,289 133,328 🟢 +39
Untyped 9,122 9,122 ±0
🔍 2 new type safety issues introduced

Type assertions (as) (2 new)

File Line Detail
static/app/components/core/markdown/markdown.tsx 77 as ExtendedTokentoken as ExtendedToken
static/app/components/core/markdown/token.tsx 71 as ExtendedTokentoken as ExtendedToken

This is informational only and does not block the PR.

Comment thread static/app/utils/marked/extensions/tag.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant