Markdown Media file

The Fossil Media Markdown library provides a lightweight way to parse Markdown text into a structured tree and serialize it back to Markdown. The C API exposes a node-based representation of Markdown elements (headings, bold, italic, lists, code, links, etc.), while the C++ wrapper adds RAII safety, exceptions, and modern string handling. This makes it suitable for both embedded C projects and higher-level C++ applications that need Markdown processing.

HEADER REFERENCE #

#ifndef FOSSIL_MEDIA_MD_H
#define FOSSIL_MEDIA_MD_H

#include <stddef.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C"
{
#endif

/**
 * @brief Markdown element types
 */
typedef enum {
    FOSSIL_MEDIA_MD_TEXT,       /**< Plain text */
    FOSSIL_MEDIA_MD_HEADING,    /**< # Heading */
    FOSSIL_MEDIA_MD_BOLD,       /**< **bold** */
    FOSSIL_MEDIA_MD_ITALIC,     /**< *italic* */
    FOSSIL_MEDIA_MD_CODE,       /**< Inline `code` */
    FOSSIL_MEDIA_MD_CODE_BLOCK, /**< ```code block``` */
    FOSSIL_MEDIA_MD_LIST_ITEM,  /**< - List item */
    FOSSIL_MEDIA_MD_LINK,       /**< [text](url) */
    FOSSIL_MEDIA_MD_PARAGRAPH,  /**< Paragraph block */
} fossil_media_md_type_t;

/**
 * @brief Parsed Markdown node
 */
typedef struct fossil_media_md_node_t {
    fossil_media_md_type_t type;   /**< Node type */
    char *content;                 /**< Text content or inline data */
    char *extra;                   /**< Extra data (e.g., link URL) */

    struct fossil_media_md_node_t **children; /**< Child nodes (for lists, blocks) */
    size_t child_count;
    int level;

    struct fossil_media_md_node_t *parent;    /**< Parent node */
} fossil_media_md_node_t;

/**
 * @brief Parse Markdown text into a tree of nodes
 */
fossil_media_md_node_t *fossil_media_md_parse(const char *input);

/**
 * @brief Serialize a Markdown node tree back into Markdown text
 */
char *fossil_media_md_serialize(const fossil_media_md_node_t *root);

/**
 * @brief Free a Markdown node tree
 */
void fossil_media_md_free(fossil_media_md_node_t *node);

#ifdef __cplusplus
}
#include <string>
#include <stdexcept>
#include <utility>
#include <cstdlib>

namespace fossil {

    namespace media {

        /**
         * @brief C++ wrapper class for Markdown parsing and serialization.
         */
        class Markdown {
        public:
            /**
             * @brief Parse Markdown text into a tree of nodes.
             * @param input The Markdown text to parse.
             * @return Pointer to the root node of the parsed tree.
             * @throws std::runtime_error on parse failure.
             */
            static fossil_media_md_node_t* parse(const std::string& input) {
                fossil_media_md_node_t* root = fossil_media_md_parse(input.c_str());
                if (!root)
                    throw std::runtime_error("Failed to parse Markdown");
                return root;
            }

            /**
             * @brief Serialize a Markdown node tree back into Markdown text.
             * @param root Pointer to the root node of the tree.
             * @return Serialized Markdown text.
             * @throws std::runtime_error on serialization failure.
             */
            static std::string serialize(const fossil_media_md_node_t* root) {
                char* result = fossil_media_md_serialize(root);
                if (!result)
                    throw std::runtime_error("Failed to serialize Markdown");
                std::string output(result);
                std::free(result);
                return output;
            }

            /**
             * @brief Free a Markdown node tree.
             * @param node Pointer to the root node to free.
             */
            static void free(fossil_media_md_node_t* node) {
                fossil_media_md_free(node);
            }
        };

    } // namespace media

} // namespace fossil

#endif

#endif /* FOSSIL_MEDIA_MD_H */

SAMPLE CODE C #

#include "fossil/media/markdown.h"
#include <stdio.h>

int main(void) {
    const char *text = "# Title\n\nThis is *italic* and **bold**.";
    fossil_media_md_node_t *root = fossil_media_md_parse(text);

    if (!root) {
        fprintf(stderr, "Failed to parse markdown\n");
        return 1;
    }

    char *out = fossil_media_md_serialize(root);
    if (out) {
        printf("Serialized:\n%s\n", out);
        free(out);
    }

    fossil_media_md_free(root);
    return 0;
}

SAMPLE CODE C++ #

#include "fossil/media/markdown.h"
#include <iostream>

int main() {
    try {
        std::string text = "- Item 1\n- Item 2\n\n[Link](https://example.com)";
        auto root = fossil::media::Markdown::parse(text);

        std::string out = fossil::media::Markdown::serialize(root);
        std::cout << "Serialized:\n" << out << std::endl;

        fossil::media::Markdown::free(root);
    } catch (const std::runtime_error &e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }
    return 0;
}

What are your feelings

Updated on August 21, 2025