Skip to content

Raw HTML in markdown renders as source text on mobile #7929

Closed

Description

@flamboh

This issue was written entirely by Fable 5 (running in T3 Code).

What happens

Raw HTML embedded in markdown renders as literal source text on mobile. A README that opens with the common centered-icon header:

<p align="center">
  <img src="public/icon-512.png" alt="" width="128" height="128" />
</p>
<h1 align="center">Project Name</h1>

shows up in the mobile file preview and thread feed as raw tags. No image element is ever created — this applies to external https: sources too, so it is a rendering capability gap, not a URL-resolution problem.

What #7857 already solves (and deliberately does not)

PR #7857 fixes workspace image URL resolution everywhere images already render: markdown-syntax images (![](public/icon.png)) now resolve through signed asset URLs on web and mobile (iOS native renderer and the JS fallback renderer), and web also covers raw HTML <img> because the web pipeline parses HTML. Mobile HTML rendering was explicitly scoped out of that PR as a separate capability.

What to look for

  • The native parser already runs with html: true — HTML arrives as html_block / html_inline nodes carrying raw source text (apps/mobile/modules/t3-markdown-text). Nothing needs to change in the parser or native code.
  • A tree transform (same pattern as nativeMarkdownWithPreservedSoftBreaks) that rewrites <img> tags inside those nodes into synthetic image nodes gets the entire existing image pipeline for free — NativeMarkdownImage, the renderImage override, and the signed asset flow from fix(web/mobile): render project images in nested markdown file previews and harden markdown images #7857. The JS fallback can hook the same logic through an html_block entry in CustomRenderers.
  • Suggested staging: (1) <img> extraction only (~150–250 lines) — caveat: sibling HTML like the <h1 align="center"> still shows as raw text, so blocks render half-fixed; (2) a safe-subset HTML normalizer (p/div/center/h1–h6/a/br/b/i → equivalent markdown nodes) so HTML-headed READMEs render properly. Stage 2 carries the real design decisions (tag allowlist, attribute degradation like align, nesting).
  • No sanitization puzzle on mobile: nothing executes — unknown tags simply remain text, so the allowlist is the safety boundary.

Related: SVG images in mobile markdown

Adjacent gap, worth fixing under this issue's umbrella: SVG sources in mobile markdown render as an empty frame because React Native's <Image> cannot decode SVG (external URLs included — this predates #7857, which deliberately excludes .svg from the signed-asset flow rather than fetch a URL the renderer cannot draw).

  • The fix is small (~120–200 lines, no new dependency): react-native-svg is already installed and exports SvgUri. Remove the resolver's .svg exclusion, add an SvgUri-based branch in the two renderer hook points (createWorkspaceImageRenderer, createFallbackMarkdownImageRenderer), and pass textStyle through the renderImage contract so the SVG frame matches the module's default image frame and caption.
  • Caveat 1: extension detection covers workspace .svg files but misses the highest-value case — badge URLs (shields.io) usually have no .svg suffix and only reveal their type via content-type. Covering those needs sniffing or try-SvgUri-first logic; that is real design work beyond the simple version.
  • Caveat 2: SvgUri fetches per mount with no cache — fine for file previews, worth attention in the thread feed given repaint/perf sensitivities.

Activity

  1. juliusmarminge commented on Oct 12, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Resolved by #16979. Mobile now renders Markdown with Enriched Markdown, and raw HTML images and blocks in chat and file previews render as media instead of source text (verified on iOS and Android in that PR). If a specific HTML snippet still shows up raw on a build that includes #16979, comment with it and we'll reopen.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions