Hive Hive
Sign in

fix(forage): render inline markdown in GitHub issue titles and excerpts

GitHub issue · Closed

Metadata
Source
tuist/hive #31
Updated
Jun 24, 2026
Domains
Hive
Details

Summary

  • HiveWeb.Markdown.inline/1 renders a single line through MDEx with the same options + sanitize policy as render/1, then strips the wrapping <p> so the result can sit inside an existing block element (issue title link, excerpt paragraph).
  • The GitHub issues forage list now routes issue.title and the body excerpt through Markdown.inline/1, so backticks become real <code> spans instead of raw characters.
  • issue_excerpt/1 skips lines that match ^#+\s+, so GitHub issue templates that start with ### What happened? don’t surface that heading as the description.
  • Styled inline <code> inside [data-part="issue-copy"] using Noora tokens (--noora-spacing-1, --noora-radius-1, --noora-surface-background-secondary, --noora-font-family-mono), following the project’s anchor + data-part CSS convention.

Motivation

Synced GitHub issues were displayed in the forage list with raw markdown leaking through. Titles like Static framework with \.metal` produces `default.metallib`showed the backticks verbatim, and the body excerpt picked the first non-blank line of the body which, for any issue using GitHub's standard issue template, is### What happened?`. Both made the list look unfinished.

Approach considered

A regex-only solution for backticks would have matched GitHub’s own issue-title rendering (which only renders inline code), but the project already standardizes on MDEx in HiveWeb.Markdown with a configured sanitize policy. Reusing that surface was preferred over introducing a one-off regex so escapes, autolinks, and HTML safety stay consistent and future markdown additions don’t need new plumbing. The catch is that MDEx wraps output in <p>; inline/1 parses with the existing options and strips the leading/trailing <p> via a tight regex so the caller decides the surrounding element.

For the excerpt, walking the MDEx AST to find the first paragraph node was considered but felt heavy for a one-line summary. The line-based filter (skip heading-marker lines, then route through Markdown.inline/1) is small, readable, and handles the actual failure mode in the screenshot.

Verification

  • mix test test/hive_web/markdown_test.exs test/hive_web/components/forage_components_test.exs test/hive_web/live/forage_live/github_issues_test.exs — 25 tests, 0 failures.
  • New tests lock in: inline rendering produces no wrapping <p>, raw HTML stays escaped, nil returns an empty safe string, the issue title renders <code> spans, and heading-only excerpt lines are skipped.
  • mix format + mix credo --strict clean (only pre-existing repo-wide warnings remained).
Comments

No GitHub comments yet.