Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
appId: swmansion.enriched.markdown.example
tags:
- block
- advanced
- blockquote
- code_block
- text
---
# checks a fenced code block nested INSIDE a blockquote, and inside a nested quote -
# the GFM recursive-container behavior from #608 where a quoted code block becomes a
# real code-block container laid out within the quote's box (not inline text).
- launchApp

- runFlow:
file: '../../../../subflows/move_to_playground.yaml'

- runFlow:
file: '../../../subflows/set_enriched_text_value.yaml'
env:
VALUE: |
> Install the package:
>
> ```bash
> npm install my-package
> ```
>
> then import it.

> Outer quote
> > Nested quote with a code block:
> >
> > ```js
> > import pkg from 'my-package'
> > ```
> >
> > done.

- runFlow:
file: '../../../subflows/capture_or_assert_screenshot.yaml'
env:
SCREENSHOT_NAME: 'blockquote_nested_code_block_combo_display'
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
blockquoteStyledDefaults,
fontFamilyControl,
fontWeightControl,
githubFlavorArgTypes,
type BlockquoteStyleControls,
numberControl,
} from '../shared/storybookMarkdownStyles';
Expand All @@ -22,6 +23,32 @@ const NESTED_MARKDOWN = `> top-level blockquote
>> nested blockquote inside the first
>>> deeply nested blockquote`;

const BLOCK_ELEMENTS_MARKDOWN = `> Blockquote containing several block elements:
>
> ## A heading inside the quote
>
> A paragraph with **bold**, _italic_ and a [link](https://swmansion.com).
>
> - first bullet
> - second bullet
>
> 1. ordered one
> 2. ordered two
>
> \`\`\`ts
> const answer = 42;
> \`\`\`
>
> | Column A | Column B |
> | -------- | -------- |
> | 1 | 2 |
>
> $$E = mc^2$$
>
> > a nested blockquote inside
>
> and a trailing paragraph.`;

const argTypes = {
fontSize: numberControl('markdownStyle.blockquote.fontSize', {
min: 12,
Expand Down Expand Up @@ -95,9 +122,13 @@ function renderBlockquote(
);
}

const flavorArgTypes = githubFlavorArgTypes(
'commonmark renders quotes inline via spans; github renders each quote as a recursive container view (its own padding/background, nested code blocks become real code-block containers).'
);

const blockquoteStoryBase = {
argTypes,
args: blockquoteStyledDefaults,
argTypes: { ...argTypes, ...flavorArgTypes },
args: { ...blockquoteStyledDefaults, flavor: 'github' as const },
};

export default storyMeta('Block', 'Blockquote');
Expand All @@ -111,7 +142,7 @@ export const Default: TextStory<BlockquoteStyleControls> = {
render: (args) =>
renderBlockquote(
'Blockquote',
'Lines prefixed with >. Use the controls to tune markdownStyle.blockquote.',
'Lines prefixed with >. Flip the flavor control between commonmark and github to compare the inline (span) and container renderers. Use the controls to tune markdownStyle.blockquote.',
args
),
};
Expand All @@ -125,7 +156,21 @@ export const Nested: TextStory<BlockquoteStyleControls> = {
render: (args) =>
renderBlockquote(
'Nested Blockquote',
'Nest blockquotes with multiple > markers. Use the controls to tune markdownStyle.blockquote.',
'Nest blockquotes with multiple > markers. Flip flavor to compare commonmark (inline spans) with github (one recursive container box per level). Use the controls to tune markdownStyle.blockquote.',
args
),
};

export const WithBlockElements: TextStory<BlockquoteStyleControls> = {
...blockquoteStoryBase,
args: {
...blockquoteStoryBase.args,
markdown: BLOCK_ELEMENTS_MARKDOWN,
},
render: (args) =>
renderBlockquote(
'Blockquote with Block Elements',
'A blockquote holding many block elements - heading, lists, a fenced code block, a table, display math and a nested quote. With flavor="github" each becomes its own segment view (code block, table, math and nested quote as real containers) nested in the quote; with flavor="commonmark" they render inline. Use the controls to tune markdownStyle.blockquote.',
args
),
};
6 changes: 4 additions & 2 deletions docs/API_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,17 +285,19 @@ Code blocks are always rendered left-to-right regardless of this prop. Per-parag

### `flavor`

Markdown flavor. Set to `'github'` to enable GitHub Flavored Markdown features: tables and block-style code blocks.
Markdown flavor. Set to `'github'` to enable GitHub Flavored Markdown features: tables, block-style code blocks, and block-style blockquotes.

| Type | Default Value | Platform |
| --------------------------------- | --------------- | -------- |
| `'commonmark' \| 'github'` | `'commonmark'` | Both |

> **Note:**
> - **`'commonmark'`**: All Markdown content is rendered as a single TextView. Selecting text will select all content in the view.
> - **`'github'`**: The Markdown AST is split into segments. Consecutive text blocks (paragraphs, headings, lists, etc.) are grouped into separate TextView segments, while tables, fenced code blocks, and math blocks are rendered as separate block views. This allows for granular text selection within each segment and enables interactive block features (horizontal table scrolling, context menus, the code block header). Text selection cannot span across segments.
> - **`'github'`**: The Markdown AST is split into segments. Consecutive text blocks (paragraphs, headings, lists, etc.) are grouped into separate TextView segments, while tables, fenced code blocks, math blocks, and blockquotes are rendered as separate block views. This allows for granular text selection within each segment and enables interactive block features (horizontal table scrolling, context menus, the code block header). Text selection cannot span across segments.
>
> With `'github'`, a fenced code block renders as a dedicated component: a header bar with the language display name (` ```python ` shows "Python") and a copy-code button, a divider, and the code below. Long lines do not wrap — the code pane scrolls horizontally while the header stays fixed. Long-pressing the block opens the Copy / Copy as Markdown menu. With `'commonmark'`, code blocks stay inside the single TextView, styled via spans, and long lines wrap.
>
> With `'github'`, a blockquote also renders as a dedicated component — a recursive container that draws its own box (padding, `backgroundColor`, and accent border with `borderRadius`) and splits its own content into segments. A code block, table, or math block quoted inside therefore becomes a real nested block component, and each nesting level is its own box. With `'commonmark'`, blockquotes stay inside the single TextView, styled via spans.

### `streamingAnimation`

Expand Down
2 changes: 1 addition & 1 deletion docs/ELEMENTS_STRUCTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Markdown elements in `react-native-enriched-markdown` are organized into block a
|---------|--------|----------------|-------------|
| Headings | `# H1` to `###### H6` | `h1` - `h6` | Six levels of headings |
| Paragraphs | Plain text | `paragraph` | Default text container |
| Blockquotes | `> Quote` | `blockquote` | Quoted content with accent bar, unlimited nesting |
| Blockquotes | `> Quote` | `blockquote` | Quoted content with accent bar, unlimited nesting; with `flavor="github"` rendered as a recursive block container (own padding/background box, and quoted code blocks/tables become real nested block components) |
| Code Blocks | ` ``` code ``` ` | `codeBlock` | Multi-line code containers; with `flavor="github"` rendered as a block component with a language header and copy-code button |
| Unordered Lists | `- Item`, `* Item`, or `+ Item` | `list` | Bullet lists with unlimited nesting |
| Ordered Lists | `1. Item` | `list` | Numbered lists with unlimited nesting |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ Lcom/swmansion/enriched/markdown/renderer/BlockquoteRenderer;
Lcom/swmansion/enriched/markdown/renderer/CodeBlockRenderer;
Lcom/swmansion/enriched/markdown/renderer/CodeBlockRenderer$CodeBlockBoundaryPaddingSpan;
Lcom/swmansion/enriched/markdown/renderer/CodeRenderer;
Lcom/swmansion/enriched/markdown/renderer/DocumentRenderer;
Lcom/swmansion/enriched/markdown/renderer/EmphasisRenderer;
Lcom/swmansion/enriched/markdown/renderer/HeadingRenderer;
Lcom/swmansion/enriched/markdown/renderer/HighlightRenderer;
Expand Down Expand Up @@ -255,22 +254,22 @@ Lcom/swmansion/enriched/markdown/styles/UnderlineStyle;
# Utilities - Common
Lcom/swmansion/enriched/markdown/utils/common/BreakStrategyUtils;
Lcom/swmansion/enriched/markdown/utils/common/FeatureFlags;
Lcom/swmansion/enriched/markdown/utils/common/MarkdownSegment;
Lcom/swmansion/enriched/markdown/utils/common/MarkdownSegment$Math;
Lcom/swmansion/enriched/markdown/utils/common/MarkdownSegment$Table;
Lcom/swmansion/enriched/markdown/utils/common/MarkdownSegment$Text;
Lcom/swmansion/enriched/markdown/utils/common/MarkdownSegmentKt;
Lcom/swmansion/enriched/markdown/utils/common/MarkdownSegmentRenderer;
Lcom/swmansion/enriched/markdown/segments/MarkdownSegment;
Lcom/swmansion/enriched/markdown/segments/MarkdownSegment$Math;
Lcom/swmansion/enriched/markdown/segments/MarkdownSegment$Table;
Lcom/swmansion/enriched/markdown/segments/MarkdownSegment$Text;
Lcom/swmansion/enriched/markdown/segments/MarkdownSegmentKt;
Lcom/swmansion/enriched/markdown/segments/MarkdownSegmentRenderer;
Lcom/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtilsKt;
Lcom/swmansion/enriched/markdown/utils/common/MotionPreferencesKt;
Lcom/swmansion/enriched/markdown/utils/common/ReadableMapExtensionsKt;
Lcom/swmansion/enriched/markdown/utils/common/ReconciliationResult;
Lcom/swmansion/enriched/markdown/utils/common/RenderedSegment;
Lcom/swmansion/enriched/markdown/utils/common/RenderedSegment$Math;
Lcom/swmansion/enriched/markdown/utils/common/RenderedSegment$Table;
Lcom/swmansion/enriched/markdown/utils/common/RenderedSegment$Text;
Lcom/swmansion/enriched/markdown/utils/common/SegmentReconciler;
Lcom/swmansion/enriched/markdown/utils/common/SegmentSignature;
Lcom/swmansion/enriched/markdown/segments/RenderedSegment;
Lcom/swmansion/enriched/markdown/segments/RenderedSegment$Math;
Lcom/swmansion/enriched/markdown/segments/RenderedSegment$Table;
Lcom/swmansion/enriched/markdown/segments/RenderedSegment$Text;
Lcom/swmansion/enriched/markdown/segments/SegmentReconciler;
Lcom/swmansion/enriched/markdown/segments/SegmentSignature;
Lcom/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter;
Lcom/swmansion/enriched/markdown/utils/common/TableStreamingMode;
Lcom/swmansion/enriched/markdown/utils/common/layout/RTLUtilsKt;
Expand Down Expand Up @@ -309,19 +308,19 @@ Lcom/swmansion/enriched/markdown/utils/text/view/TextSelectionColorsKt;
Lcom/swmansion/enriched/markdown/utils/text/view/TextViewSetupKt;

# Views
Lcom/swmansion/enriched/markdown/views/BlockSegmentView;
Lcom/swmansion/enriched/markdown/segments/BlockSegmentView;
Lcom/swmansion/enriched/markdown/views/ContextMenuPopup;
Lcom/swmansion/enriched/markdown/views/ContextMenuPopup$Builder;
Lcom/swmansion/enriched/markdown/views/ContextMenuPopup$Icon;
Lcom/swmansion/enriched/markdown/views/ContextMenuPopup$MenuItem;
Lcom/swmansion/enriched/markdown/views/MathContainerView;
Lcom/swmansion/enriched/markdown/views/TableContainerView;
Lcom/swmansion/enriched/markdown/views/TableContainerView$CellBackgroundView;
Lcom/swmansion/enriched/markdown/views/TableContainerView$CellTextView;
Lcom/swmansion/enriched/markdown/views/TableContainerView$GridContainerView;
Lcom/swmansion/enriched/markdown/views/TableContainerView$HeaderTypefaceSpan;
Lcom/swmansion/enriched/markdown/views/TableContainerView$TableCellData;
Lcom/swmansion/enriched/markdown/segments/MathContainerView;
Lcom/swmansion/enriched/markdown/segments/TableContainerView;
Lcom/swmansion/enriched/markdown/segments/TableContainerView$CellBackgroundView;
Lcom/swmansion/enriched/markdown/segments/TableContainerView$CellTextView;
Lcom/swmansion/enriched/markdown/segments/TableContainerView$GridContainerView;
Lcom/swmansion/enriched/markdown/segments/TableContainerView$HeaderTypefaceSpan;
Lcom/swmansion/enriched/markdown/segments/TableContainerView$TableCellData;

# Math (optional, from src/math source set)
Lcom/swmansion/enriched/markdown/spans/MathMeasureHelper;
Lcom/swmansion/enriched/markdown/views/MathContainerView$RaTeXCanvasView;
Lcom/swmansion/enriched/markdown/segments/MathContainerView$RaTeXCanvasView;
Loading
Loading