igormironchik / md4qt

Markdown parser for Qt6 or ICU
16 stars 1 forks source link
ast commonmark cpp17 gfm icu markdown md parser qt6 stl

License: MIT

md4qt is a header-only C++ library for parsing Markdown.

md4qt supports CommonMark 0.31.2 Spec, and some GitHub extensions, such as tables, footnotes, tasks lists, strikethroughs, LaTeX Math injections, GitHub's autolinks.

md4qt can be built with Qt6 or with ICU.

This library parses Markdown into tree structure.

Example

#define MD4QT_QT_SUPPORT
#include <md4qt/parser.hpp>

int main()
{
    MD::Parser< MD::QStringTrait > p;

    auto doc = p.parse( QStringLiteral( "your_markdown.md" ) );

    for( auto it = doc->items().cbegin(), last = doc->items().cend(); it != last; ++it )
    {
        switch( (*it)->type() )
        {
            case MD::ItemType::Anchor :
            {
                auto a = static_cast< MD::Anchor< MD::QStringTrait >* > ( it->get() );
                qDebug() << a->label();
            }
                break;

            default :
                break;
        }
    }

    return 0;
}

Benchmark

Approximate benchmark with md4c and cmark-gfm says, that Qt6 version of md4qt is slower ~8-12 times. But you will get complete C++ tree structure of the Markdown document with all major extensions. Conclusion why it's slower you can read here.

cmark-gfm md4c markdown-it (Rust) md4qt with Qt6
~284 microseconds ~427 microseconds ~6700 microseconds ~3394 microseconds

[!NOTE]

This measurement done with test file in markdown-it (Rust)

markdown-it (Rust) measurement done with markdown_it::plugins::extra

Keep in mind that markdown-it (Rust) doesn't support all GFM extensions, so it's not honest to compare. md4qt supports GitHub's autolinks extension, that markdown-it (Rust) doesn't, and this requires ~500 microseconds, for example...

Playground

You can play in action with md4qt in Markdown Tools. There you can find Markdown editor/viewer/converter to PDF.

Q/A

Why another AST Markdown parser?

What should I know about links in the document?

What is the second argument of MD::Parser::parse()?

What is an MD::Anchor?

Does the library throw exceptions?

Why MD::Parser and MD::Document are templates?

So, how can I use md4qt with Qt6 and ICU?

ICU is slower then Qt6? Really?

Why is parsing wrong on Windows with std::ifstream?

How can I convert MD::Document into HTML?

How can I obtain positions of blocks/elements in Markdown file?

How can I easily traverse through the MD::Document?

Why don't you have an implementation for pure STL with std::string?

Where are empty list items and blockquotes?

Is it possible to write custom text plugin for this parser?

What is a ID of a plugin?

What is a TextPluginFunc< Trait >?

What is processInLinks flag for?

What for is a userData argument?

Could you show an example of a plugin?

I didn't understand how raw text data correlates with a paragraph.

How can I get a string of StyleDelim?

Is it possible to find Markdown item by its position?

How can I walk through the document and find all items of given type?

How can I add and process a custom (user-defined) item in MD::Document?