FluidMarkdown

repository·main·Indexed 20 days ago

https://github.com/antgroup/fluidmarkdown

A cross-platform library for iOS, Android, and HarmonyOS designed for the progressive, streaming rendering of Markdown content, specifically optimized for Large Language Model (LLM) outputs. It includes a C++ LaTeX rendering engine capable of converting formulas to SVG via a headless CLI or integrated API, requiring platform-specific implementations of Graphics2D, Font, and TextLayout interfaces.

Tokens
15.3K
Snippets
46
Records
69
Agent score
69%

What's inside fluidmarkdown

  1. Overview of formula-ffi

    main

    formula-ffi

    formula-ffi is a library designed to display mathematical formulas written in LaTeX. It provides interfaces for parsing LaTeX strings and converting them into various visual formats.

    Key Features:

    • LaTeX Parsing: Provides interfaces to parse mathematical formula strings.
    • Bitmap Generation: Generates bitmap representations of formulas.
    • Image Resource Generation: Provides interfaces to generate image resources from formulas.
  2. Overview of libboundscheck

    main
    libboundscheck is a library that implements common memory and string operation functions following the C11 Annex K (Bounds-checking interfaces) standard. It provides safer alternatives to standard C functions by performing bounds checking to prevent buffer overflows. The library includes implementations for functions like memcpy_s, strcpy_s, and others.
  3. FluidMarkdown Features and Supported Syntax

    main

    FluidMarkdown enables streaming rendering of Markdown for AI-driven applications.

    Supported Markdown Syntax:

    • Titles, paragraphs, and quotes.
    • Ordered and unordered lists.
    • Tables, code blocks, and inline code.
    • Mathematical formulas.
    • Footnotes, links, and images.
    • Dividing lines.

    Supported HTML Tags:

    • Standard tags: <s>, <sup>, <sub>, <mark>, <a>, <span>, <cite>, <del>, <font>, <img>, <u>, etc.
    • Extended tags (via AMHTMLTransformer): <iconlink>, <icon>.

    Key Capabilities:

    • Streaming rendering and one-time full rendering modes.
    • Customizable rendering styles.
    • Adjustable streaming speed.
    • Event support for clickable elements and visibility callbacks.
  4. Implement the required graphical interfaces

    main

    To use this library on a specific platform, you must implement the interfaces defined in src/graphic/graphic.h. The core interfaces are:

    • tex::Font: Represents a typeface. You must implement the interface and provide two static factory methods: Font::create(const string& file, float size) and Font::_create(const string& name, int style, float size).
    • tex::TextLayout: Used to layout characters from unregistered alphabets (e.g., CJK Unified Ideographs). This allows the library to calculate layout bounds for non-BMP or non-predefined Unicode blocks.
    • tex::Graphics2D: The most critical interface. It defines the 2D graphics context for all TeX drawing operations, including affine transformations and basic shapes. You wrap your platform's specific graphics API (like Cairo, GDI+, or Android Canvas) into this interface.

    Existing implementations are available for:

    • Linux: graphic_cairo (using cairomm and gtkmm).
    • Windows: graphic_win32 (using gdiplus).
    • Android: Implementations available via AndroidLaTeXMath.
    • Memory Check: empty implementations in src/samples/mem_check_main.cpp.
  5. Use FluidMarkdown on iOS

    main

    To implement streaming Markdown rendering on iOS, use the AMXMarkdownTextView class. The process involves creating a TextView instance, configuring styles via AMXMarkdownStyleConfig, and managing the stream lifecycle using startStreamingWithContent:, addStreamContent:, and stop.

    To handle dynamic content size changes (e.g., for auto-scrolling), implement the AMXMarkdownTextViewDelegate and use the onSizeChange: callback to adjust the view's frame and container content size.

    ```objectivec
    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:@
  6. Compile and build formula-ffi for HarmonyOS

    main

    To build formula-ffi for the HarmonyOS environment, follow these steps:

    1. Download the code

    git clone --recursive https://gitcode.com/Cangjie-TPC/formula-ffi.git

    2. Environment Setup

    • MSYS2 & MinGW64:
      • Install MSYS2.
      • Download mingw64 binaries and extract them into the MSYS2 root directory.
      • Copy msys2\mingw64\bin\mingw32-make.exe to msys2\mingw64\bin\make.exe.
    • CMake: Download CMake and copy its contents into the msys2/usr/ directory.
    • DevEco Studio: Install DevEco Studio. You must update the paths in build-ohos.sh to point to your HarmonyOS SDK (located under sdk -> HarmonyOS-NEXT-DB3/openharmony or similar).
    • Cangjie Cross-Compilation: Update the ${DEVECO_CANGJIE_HOME} variable in cjpm.toml. This is typically located in your user directory under .cangjie-sdk after installing the Cangjie plugin in DevEco Studio.

    3. Build

    Open a MinGW64 terminal, navigate to the project root, and execute:

    ./build-ohos.sh

    Note: This project is strictly limited to the HarmonyOS (ohos) environment.

    #!/bin/bash
    # Example execution command
    ./build-ohos.sh
  7. Install FluidMarkdown for iOS

    main

    To use FluidMarkdown in an iOS project, clone the repository, navigate to the iOS directory, and open the FluidMarkdown.xcworkspace file in Xcode.

    git clone git@github.com:antgroup/FluidMarkdown.git
    cd <your-project-path>/FluidMarkdown/iOS
    open FluidMarkdown.xcworkspace
  8. Use libboundscheck in your C project

    main

    To integrate libboundscheck into your project, follow these two steps:

    1. Deploy the library: Copy the generated libboundscheck.so to your system's library directory (e.g., /usr/local/lib/).
    2. Link the library: Add the -lboundscheck flag to your compiler command when building your application.
    gcc -g -o test test.c -lboundscheck
  9. Initialize and use the LaTeX library in C++

    main

    To use the library in your application, follow these lifecycle steps:

    1. Initialize: Call LaTeX::init() at the start of your application. This loads required resources. You can specify a custom resource directory using LaTeX::init("path/to/resources").
    2. Configure (Optional):
      • Set pixels per point: TeXFormula::PIXELS_PER_POINT = value; (default is 1).
      • Set DPI target: TeXFormula::setDPITarget(dpi); (e.g., 74).
    3. Display: Use the library to render formulas.
    4. Release: Call LaTeX::release() before application exit to free resources.
    #include "latex.h"
    
    using namespace tex;
    
    // 1. Initialize resources (can be done in a background thread)
    LaTeX::init();
    
    // 2. Optional configuration
    TeXFormula::PIXELS_PER_POINT = 2;
    TeXFormula::setDPITarget(74);
    
    // ... render formulas ...
    
    // 3. Release resources before exit
    LaTeX::release();
  10. Use FluidMarkdown on HarmonyOS

    main

    FluidMarkdown for HarmonyOS is a component compliant with the @ComponentV2 specification. It supports three main modes:

    1. Normal Rendering

    Import Markdown and bind content via the content parameter. Use the mode parameter set to EMarkdownMode.Normal.

    2. Streaming Output (Typing Mode)

    Set mode to EMarkdownMode.Typing. You must provide a MarkdownController instance to the controller parameter. Important: Control methods like update() should only be called within the onMarkdownTypingReady event callback to ensure reliability. In this mode, the content parameter is ignored.

    3. Theme Customization

    Pass a BaseEngine instance to the engine parameter. You can modify theme properties (like fontColor) through the engine's theme service during the component lifecycle (e.g., in aboutToAppear).

    // Normal Mode Example
    import { Markdown, EMarkdownMode } from 'fluid-markdown';
    
    Markdown({
      content: this.content,
      mode: EMarkdownMode.Normal,
      onMarkdownAreaChange: () => {},
      onMarkdownNodeClick: data => {},
    })
    
    // Streaming Mode Example
    import { Markdown, EMarkdownMode, MarkdownController, ETypingMode } from 'fluid-markdown';
    
    private markdownController: MarkdownController = new MarkdownController();
    
    Markdown({
      controller: this.markdownController,
      mode: EMarkdownMode.Typing,
      onMarkdownTypingReady: () => {
        this.markdownController.typing.update('Hello FluidMarkdown', ETypingMode.Begin);
      },
    })
  11. Install FluidMarkdown for HarmonyOS

    main

    To use FluidMarkdown in a HarmonyOS project, clone the repository and open the project located in the HarmonyOS directory using DevEco-Studio.

    git clone git@github.com:antgroup/FluidMarkdown.git
    cd your/project/FluidMarkdown/HarmonyOS
    # Open the project via DevEco-Studio
  12. Display mathematical formulas using LaTeX

    main

    You can render LaTeX code into a paintable TeXRender object using two different modes: General mode (simple) or Builder mode (highly configurable).

    General Mode

    Use LaTeX::parse for a quick way to convert LaTeX code into a TeXRender object. Note that the library uses wide strings (wstring) to represent UTF characters. You may need to convert UTF-8 strings using a utility like utf82wide.

    Builder Mode

    Use TeXRenderBuilder for fine-grained control over the rendering environment.

    Important Requirements:

    • You must call .setStyle() and .setSize() before calling .build(), otherwise an ex_invalid_state exception will be thrown.
    • If you do not set a logical width using .setWidth(), the resulting TeXRender might overflow the graphics context.

    Drawing the Result

    Once you have a TeXRender object, use its .draw(x, y) method within a graphics context (e.g., Graphics2D_cairo) to render it. Remember to delete the TeXRender object when it is no longer needed to prevent memory leaks.

    // General Mode
    wstring code = L"\int_{now}^{+\infty} \text{Keep trying}";
    auto r = LaTeX::parse(code, 720, 20, 10, BLACK);
    
    // Builder Mode
    TeXFormula formula;
    TeXRenderBuilder builder;
    formula.setLaTeX(L"\int_{now}^{+\infty} \text{Keep trying}");
    
    auto r = builder
        .setStyle(STYLE_DISPLAY)
        .setSize(20)
        .setWidth(UNIT_PIXEL, 720, ALIGN_LEFT)
        .setIsMaxWidth(false)
        .setLineSpace(UNIT_PIXEL, 10)
        .setForground(tex::BLACK)
        .build(formula);
    
    // Drawing (Example using Cairo)
    Graphics2D_cairo g2;
    r->draw(10, 10);
    delete r;