Skip to content

EnrichedMarkdownText renders nothing when content contains | (spoiler syntax cannot be disabled) #645

Description

Version

react-native-enriched-markdown@0.7.4, React Native 0.8x via Expo SDK 57, Android.

What happens

Any content containing ASCII pipes renders as a completely empty view — no text, no error,
no warning. A markdown table, a shell command, prose using a vertical bar: all vanish.

For a chat app this is silent data loss. A table-only answer from an LLM arrives as a blank
message bubble, and the user has already paid for the tokens that produced it.

Reproduction

// Renders nothing at all
<EnrichedMarkdownText flavor="commonmark">
  {'| Model | Speed |\n|---|---|\n| Claude | Fast |'}
</EnrichedMarkdownText>

// Renders fine
<EnrichedMarkdownText flavor="commonmark">
  {'Model: Claude, Speed: Fast'}
</EnrichedMarkdownText>

Measured on a physical device by rendering the raw string beside the markdown:

Content Length Pipes Rendered
Model comparison, table form 593 chars 36 nothing
Same content, prose form 575 chars 0 correctly

Length is not the factor; the pipes are.

Cause (as far as we could determine)

The ||text|| spoiler syntax. The docs state that spoiler parsing is always enabled, and
the available md4cFlags cover underline / superscript / subscript / latexMath / highlight —
there is no flag to turn spoilers off. A table row (| a | b |) is full of pipe pairs.

Two things we tried that did not help, which may narrow it down:

  1. Styling the spoiler visible (spoiler: { color: 'transparent' }) changes nothing — the
    block appears to be dropped before styling is applied.
  2. flavor="github" does render tables, but segments the view per block, and the docs note
    that "text selection cannot span across segments" — which reintroduces a different bug for
    us, so it is not a usable workaround.

What would help

Any one of these:

  • An md4cFlag to disable spoiler parsing.
  • Requiring spoilers to be well-formed, so an unmatched or table-shaped pipe run falls through
    as literal text.
  • Failing visibly rather than silently — rendering the raw text, or warning in dev — so this is
    discoverable without a device experiment.

The silent part is what makes it expensive: there is no error to search for, and the code reads
as correct.

Our workaround

mobile-rn/src/lib/mdTable.js converts GFM tables to ASCII-bordered text inside a code fence
and replaces every remaining ASCII pipe with U+2758 (LIGHT VERTICAL BAR) before rendering. Its
test suite asserts "no ASCII pipe reaches the renderer" as the core invariant.

Side effect we accept: a shell command inside a fence shows instead of |. A mangled glyph
beats a blank reply.

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