WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

antgroup/FluidMarkdown

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FluidMarkdown

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.

Overview

This library is designed for native Android, iOS and HarmonyOS 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.

Features

  • 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>in AMHTMLTransformer class.

Install

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.

Directory structure

iOS

  • AntMarkdown —— a standard markdown parser and rendering module based on commonMark.
  • FluidMarkdown —— Component for streaming output.

Android

  • fluid-markdown —— Component for streaming output.
  • markwon-xxx —— Syntax parsing and style rendering implementation based on the open-source markwon library.

HarmonyOS

  • markdown —— the folder contains all the source code for the markdown component, such as syntax parsing, layout rendering, theme configuration, runtime services, etc.
  • playground —— a demo to show markdown component feature list.
your/project/markdown/src/main/ets
├── engine					//	[folder] engine manages all services and plugins at runtime.
├── index.ets       //  [file]   default exports.
├── markdown.ets		//	[file]   markdown component compliant with the @ComponentV2 specification.
├── render					//	[folder] rendering-related logic based on the StyledString mechanism.
├── service					//	[folder] runtime service modules, such as syntax parsing, code highlighting, etc.
├── theme						//	[folder] style and theme-related logic based on the StyledString mechanism.
└── util						//	[folder] built-in utility api.

Usage

iOS

  • Native API: AMXMarkdownWidget.h is summary header file of the open API. The following is the general calling process of streaming rendering components.
    1. Create a TextView instance.
    2. Generate default styles and set custom styles ( if needed )
    3. Begin streaming the Markdown content.
    4. Append data dynamically during rendering.
    5. Adjust list scrolling in response to content size changes in the TextView.
    6. 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
    1. The StreamPreviewViewController class is a sample page for previewing streaming output.
    2. 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.

StreamingPreviewAIChat

Android

  1. Initialize by calling AFMInitializer.init(context, backgroundTaskHandler, imageHandler, logHandler) once globally. Except for context, all other parameters can be null.
  2. Create PrinterMarkDownTextView to display markdown content.
  3. Create MarkdownStyles to set render styles.
  4. Call PrinterMarkDownTextView.init() to bind MarkdownStyles and ElementClickEventCallback. Must be called, MarkdownStyles cannot be null.
  5. 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.

printlist

HarmonyOS

Combine Markdown

  • Import and combine the Markdown component in your page build() method.
  • Bind markdown-formatted content text via the @Param content parameter.
  • Handle various callback events inside the Markdown component to enhance the business interaction flow, such as @Event onMarkdownAreaChange, @Event onMarkdownNodeClick, etc.
import { Markdown, EMarkdownMode } from 'fluid-markdown';

@ComponentV2
export struct MyComponent {
  @Param content: string;
  private scroller: Scroller = new Scroller();

  build() {
      Scroll(this.scroller) {
        Markdown({
          content: this.content,
          mode: EMarkdownMode.Normal,
          onMarkdownAreaChange: () => {},
          onMarkdownNodeClick: data => {},
        })
          .margin(12)
      }
      .width('100%')
      .height('100%')
      .scrollable(ScrollDirection.Vertical)
      .margin(12)
  }
}

Streaming Output

  • Enable streaming output mode by setting the @Param mode parameter to EMarkdownMode.Typing.
  • Create a MarkdownController instance and bind it to the @Param controller parameter to manage the streaming output process, such as update(), pause(), resume(), etc.
  • Note: Control methods of MarkdownController, such as update(), can only be reliably executed within the @Event onMarkdownTypingReady callback event.
  • Note: The @Param content parameter will be ignored in streaming output mode.
import { 
  Markdown, EMarkdownMode, MarkdownController, ETypingMode,
} from 'fluid-markdown';

@ComponentV2
export struct MyComponent {
  private scroller: Scroller = new Scroller();
  private markdownController: MarkdownController = new MarkdownController();

  build() {
      Scroll(this.scroller) {
        Markdown({
          controller: this.markdownController,
          mode: EMarkdownMode.Typing,
          onMarkdownTypingReady: () => {
            this.markdownController.typing.update('Hello FluidMarkdown', ETypingMode.Begin);
          },
        })
          .margin(12)
      }
      .width('100%')
      .height('100%')
      .scrollable(ScrollDirection.Vertical)
      .margin(12)
  }
}

Theme Config

  • Create a new Engine instance and bind it to the @Param engine parameter.
  • Set ITheme properties for theme styling through the theme service within the Engine.
import { Markdown, EMarkdownMode, BaseEngine } from 'fluid-markdown';

@ComponentV2
export struct MyComponent {
  @Param content: string;
  private scroller: Scroller = new Scroller();
  private engine: BaseEngine = new BaseEngine();

  aboutToAppear() {
    this.engine.theme!.theme!.document!.font!.fontColor = Color.Red;
  }
  
  build() {
      Scroll(this.scroller) {
        Markdown({
          engine: this.engine,
          content: this.content,
          mode: EMarkdownMode.Normal,
          onMarkdownAreaChange: () => {},
          onMarkdownNodeClick: data => {},
        })
          .margin(12)
      }
      .width('100%')
      .height('100%')
      .scrollable(ScrollDirection.Vertical)
      .margin(12)
  }
}

Playground

Build and run the Playground app to try out FluidMarkdown—have fun! fluid-markdown-ohos-playground

Known Issues

  • 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.
  • LaTex capability on the HarmonyOS platform is under development and not yet available.
  • The minimum required HarmonyOS API version is 15 or higher.

Contribute

The FluidMarkdown team welcomes individual or team contributions. For more informations, please refer to the file CONTRIBUTING.

Licensing

All source code is licensed under the Apache 2.0 license. For details, please refer to LICENSE.

We acknowledge the following open-source projects:

Acknowledgements and References