We are committed to enabling the streaming rendering of Markdown content generated by large language models on the client side within AI-driven business applications.
This library is designed for native Android and iOS developers. Built on the open-source CommonMark parsing library, it supports core Markdown syntax and selected HTML tags, rendering them progressively within UI components. It exposes Markdown styling as a structured model, enabling customization and integration into your specific application contexts. For faster integration, refer to the sample code to preview the rendering effect based on input text.
- Support for markdown syntax: titles, paragraphs, ordered lists, unordered lists, tables, code blocks, mathematical formulas, inline code blocks, quotes, dividing lines, footnotes, links, and images.
- Support for HTML tags:
<s>
<sup>
<sub>
<mark>
<a>
<span>
<cite>
<del>
<font>
<img>
<u>
, etc. - Streaming rendering and one-time full rendering modes.
- Customizable rendering styles for Markdown syntax.
- Adjustable streaming speed via custom parameters.
- Event support for clickable elements, including click handling, visibility callbacks, and rendering status updates, etc.
- Added some new extended HTML tags such as
<iconlink>
<icon>
inAMHTMLTransformer
class.
The source code of this project is open-source. For information on how to download and run the project, please refer to the file INSTALL.
- AntMarkdown —— a standard markdown parser and rendering module based on commonMark.
- FluidMarkdown —— Component for streaming output.
- fluid-markdown —— Component for streaming output.
- markwon-xxx —— Syntax parsing and style rendering implementation based on the open-source markwon library.
- Native API:
AMXMarkdownWidget.h
is summary header file of the open API. The following is the general calling process of streaming rendering components.- Create a TextView instance.
- Generate default styles and set custom styles ( if needed )
- Begin streaming the Markdown content.
- Append data dynamically during rendering.
- Adjust list scrolling in response to content size changes in the TextView.
- Handle completion when rendering is finished.
AMXMarkdownTextView* contentTextView = [[AMXMarkdownTextView alloc] initWithFrame_ant_mark:CGRectMake(0, 0, screenWidht - 20 * 2, 1)];
// get default style config
AMXMarkdownStyleConfig* config = [AMXMarkdownStyleConfig defaultConfig];
// modify code block style for example
config.codeBlockConfig.backgroundColor = [UIColor greenColor];
// set the style with unique Id
[[AMXRenderService shared] setMarkdownStyleWithId:config styleId:@"demo"];
// begin print
[self.contentTextView startStreamingWithContent:@"testing data"];
// append content during printing
[self.contentTextView addStreamContent:@"**append test data**"];
// stop print when you need
[self.contentTextView stop];
@interface StreamPreviewViewController ()<AMXMarkdownTextViewDelegate>
-(void)initUI
{
// set delegate
self.contentTextView.textViewDelegate = self;
}
// size change delegate
-(void)onSizeChange:(CGSize)size
{
// adjust size of AMXMarkdownTextView and container view
[self.contentTextView setFrame:CGRectMake(0, 0, self.contentTextView.frame.size.width, size.height)];
[self.containerView setContentSize:size];
CGPoint bottomOffset = CGPointMake(0, self.containerView.contentSize.height - self.containerView.bounds.size.height);
if (bottomOffset.y > 0) {
// scroll the container view to bottom
[self.containerView setContentOffset:bottomOffset animated:NO];
}
}
- Sample Description
- The
StreamPreviewViewController
class is a sample page for previewing streaming output. - The
AIChatViewController
class demonstrates FluidMarkdown usage in simulated AI conversation scenarios. Note that the conversation data is statically defined and intended solely for rendering demonstration purposes.
- The
- Initialize by calling AFMInitializer.init(context, backgroundTaskHandler, imageHandler, logHandler) once globally. Except for context, all other parameters can be null.
- Create PrinterMarkDownTextView to display markdown content.
- Create MarkdownStyles to set render styles.
- Call PrinterMarkDownTextView.init() to bind MarkdownStyles and ElementClickEventCallback. Must be called, MarkdownStyles cannot be null.
- Set markdown content or call the print start method.
AFMInitializer.init(context, null, null, null);
// Create PrinterMarkDownTextView
PrinterMarkDownTextView markdownTextView = findViewById(R.id.markdown_view);
// Create MarkdownStyles,or you can also create custom styles with new MarkdownStyles()
MarkdownStyles styles = MarkdownStyles.getDefaultStyles();
// set style sample
styles.linkStyle().icon("https://you_image_url");
styles.setTitleStyle(0, TitleStyle.create(1.5f).icon(https://you_image_url));// Set title level 1 style
// bind MarkdownStyles and ElementClickEventCallback.
markdownTextView.init(styles, elementClickEventCallback);
// Set markdown content or you can call the startPrinting(content) to starting printing.
markdownTextView.setMarkdownText(markdown);
- Sample Description
- MainActivity - Markdown normal mode sample.
- PrinterActivity - Streaming print sample.
- ListActivity - Streaming print list sample.
- Clickable elements within tables appear as plain text and are not interactive.
- Nested HTML tags within table cells are not supported.
- Tables on Android may overflow their container and do not support horizontal scrolling.
The FluidMarkdown team welcomes individual or team contributions. For more informations, please refer to the file CONTRIBUTING.
All source code is licensed under the Apache 2.0 license. For details, please refer to LICENSE.
We acknowledge the following open-source projects:
- noties/Markwon
- license: Apache-2.0
- indragiek/CocoaMarkdown
- license: MIT License
- commonmark/commonmark-spec
- license: MIT License
- https://github.com/max-lfeng/iosMath/
- license: MIT License
- https://github.com/mattt/Ono/
- license: MIT License
- All developers who have contributed code to the Ant Markdown component
- Thanks to the following open source projects: