Skip to content

fix: resolve interactive-book rendering issue#519

Open
yashmanjunath-74 wants to merge 1 commit intoCircuitVerse:masterfrom
yashmanjunath-74:master
Open

fix: resolve interactive-book rendering issue#519
yashmanjunath-74 wants to merge 1 commit intoCircuitVerse:masterfrom
yashmanjunath-74:master

Conversation

@yashmanjunath-74
Copy link
Copy Markdown

@yashmanjunath-74 yashmanjunath-74 commented Mar 3, 2026

Fixes #496

Describe the changes you have made in this PR -

Summary
This PR addresses a critical assertion failure (_inlines.isEmpty) in the flutter_markdown builder that occurred during interactive scrolling in the Interactive Book section. The fix implements a robust, stack-safe architecture to ensure the markdown parser and builder remain perfectly synchronized.

The Problem
The diagnostic logs revealed that the _inlines.isEmpty error was caused by a fundamental leak in the markdown builder's inline stack. This happened when:

BlockSyntax nodes returned null or "Empty Text" children after advancing the parser.
Custom tags were interpreted as inlines instead of blocks, preventing the builder from clearing the inline stack correctly during its traversal.
The Solution: 100% Stack-Safe Architecture

  1. Parser Synchronization
    Updated BlockSyntax implementations (
    IbMdTagSyntax,
    IbLiquidSyntax,
    IbFilterSyntax
    ) to never return null after advancing the parser. If content is skipped, the parser now returns an empty block node wrapped in a

    tag. This prevents the parser from getting stuck or producing unbalanced nodes.

  2. Paragraph Protection
    Forced the MarkdownBuilder to follow its most stable and well-tested stack-clearing pathway by wrapping all custom block elements (like chapter_contents, interaction, and iframe) in native Paragraph (p) elements. Since p is a built-in block tag, it ensures the inline stack is cleared before proceeding to the next node.

  3. Data-via-Attributes Refactoring
    Refactored builders to read their IDs and content from attributes instead of text content. This allows the syntaxes to return nodes with strictly empty children lists, which prevents the builder from ever pushing a "leaky" entry onto the inline stack.

Interactions: Now use attributes['id'].
Pop Quizzes: Now use attributes['content'].
4. Invisible Empty Placeholder
Introduced a dedicated
IbEmptyBuilder
that renders SizedBox.shrink() for placeholder nodes (). This allows the parser to remain synchronized without impacting the UI layout.

Screenshots of the changes (If any) -
image

Note: Please check Allow edits from maintainers. if you would like us to assist in the PR.

Summary by CodeRabbit

  • Bug Fixes
    • Improved reliability of content extraction for interactive elements and pop quiz features
    • Enhanced HTML structure handling for embedded content to ensure proper rendering and display
    • Strengthened parser robustness to gracefully handle missing or malformed content without interruption

@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 3, 2026

Deploy Preview for cv-mobile-app-web ready!

Name Link
🔨 Latest commit 934787b
🔍 Latest deploy log https://app.netlify.com/projects/cv-mobile-app-web/deploys/69a678b426e5f60008e67967
😎 Deploy Preview https://deploy-preview-519--cv-mobile-app-web.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 3, 2026

Walkthrough

This pull request modifies the interactive book rendering pipeline across multiple syntax parsers and builders. Changes include: extracting content from element attributes instead of text content, wrapping various elements (iframes, interactions, quiz content) in paragraph containers, replacing null returns with placeholder blocks for stack safety, and introducing an empty builder that renders nothing. These modifications adjust how markdown elements are parsed and structured before rendering.

Suggested labels

potential-ai-slop

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: resolve interactive-book rendering issue' clearly and specifically references the main problem being addressed: the interactive book rendering issue mentioned in #496.
Linked Issues check ✅ Passed The PR addresses all coding requirements from #496: parser synchronization by preventing null returns after advancing parsers, paragraph protection by wrapping custom elements, data-via-attributes refactoring for reading IDs/content, and invisible placeholder builder implementation.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the interactive book rendering issue. Modifications across syntax parsers, builders, and data access patterns all target the assertion failure and rendering problem described in #496.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
lib/ui/views/ib/syntaxes/ib_liquid_syntax.dart (1)

19-31: ⚠️ Potential issue | 🟠 Major

Guard malformed include tags to prevent parser crashes.

The image and interaction branches still assume required tokens/attributes exist. Missing url, description, or a second tag token can throw and break page rendering.

Proposed defensive parsing fix
-      } else if (tags[1] == 'image.html' && tags.length >= 3) {
+      } else if (tags.length > 1 && tags[1] == 'image.html') {
         // Images
-        var url =
-            RegExp(r'''url=("|')([^"'\n\r]+)("|')''').firstMatch(match[1]!)![2];
-        var alt =
-            RegExp(
-              r'''description=("|')([^"'\n\r]*)("|')''',
-            ).firstMatch(match[1]!)![2];
-
-        var img = md.Element.withTag('img');
-        img.attributes['src'] = '${EnvironmentConfig.IB_BASE_URL}$url';
-        img.attributes['alt'] = alt!;
-        node = md.Element('p', [img]);
+        final urlMatch =
+            RegExp(r'''url=("|')([^"'\n\r]+)("|')''').firstMatch(match[1]!);
+        final altMatch = RegExp(
+          r'''description=("|')([^"'\n\r]*)("|')''',
+        ).firstMatch(match[1]!);
+
+        final url = urlMatch?.group(2);
+        final alt = altMatch?.group(2) ?? '';
+        if (url == null || url.isEmpty) {
+          node = md.Element('p', [md.Element.withTag('empty')]);
+        } else {
+          final img = md.Element.withTag('img');
+          img.attributes['src'] = '${EnvironmentConfig.IB_BASE_URL}$url';
+          img.attributes['alt'] = alt;
+          node = md.Element('p', [img]);
+        }
       } else {
         // Interactions using html
         // Use attribute 'id' for data-via-attributes fix
-        var intNode = md.Element.withTag('interaction');
-        intNode.attributes['id'] = tags[1];
-        node = md.Element('p', [intNode]);
+        if (tags.length > 1) {
+          final intNode = md.Element.withTag('interaction');
+          intNode.attributes['id'] = tags[1];
+          node = md.Element('p', [intNode]);
+        } else {
+          node = md.Element('p', [md.Element.withTag('empty')]);
+        }
       }

Also applies to: 34-37

lib/ui/views/ib/builders/ib_interaction_builder.dart (1)

17-21: ⚠️ Potential issue | 🟠 Major

Short-circuit when interaction id is empty.

When id is missing, the builder still issues fetchHtmlInteraction(''), which can trigger avoidable failed requests and repeated loading/error UI.

Proposed fix
-    var id = element.attributes['id'] ?? '';
+    final id = (element.attributes['id'] ?? '').trim();
+    if (id.isEmpty) {
+      return const SizedBox.shrink();
+    }

     return FutureBuilder<dynamic>(
       future: model.fetchHtmlInteraction(id),

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f621531 and 934787b.

📒 Files selected for processing (7)
  • lib/ui/views/ib/builders/ib_interaction_builder.dart
  • lib/ui/views/ib/builders/ib_pop_quiz_builder.dart
  • lib/ui/views/ib/ib_page_view.dart
  • lib/ui/views/ib/syntaxes/ib_embed_syntax.dart
  • lib/ui/views/ib/syntaxes/ib_filter_syntax.dart
  • lib/ui/views/ib/syntaxes/ib_liquid_syntax.dart
  • lib/ui/views/ib/syntaxes/ib_md_tag_syntax.dart

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Interactive-Book not getting rendered

2 participants