← All tasks
cppclaude-code/cpp-t2 #30Not a task: not reproduced

Markdown to HTML Converter (cpp, written by Claude Code)

envgap__claude-code__cpp-t2-30

Written by a coding agent; not on GitHubWritten 2026-02-28

01 / FAILURE SIGNATURE

As the study recorded it

GCC 11 aggregate init with default member initializer in default param
Not a benchmark task.
  • In a clean container the reported failure did not reproduce, or the known fix did not make the project run.

02 / ENVIRONMENT RECIPE

Base commit
Not freshly verified
Manifest
CMakeLists.txt
Reproduce
Awaiting issue-specific recipe
Run under trace
Awaiting a meaningful runtime command

03 / TASK AND FAILURE

claude-code/cpp-t2 #30 · read the task the agent was given
Claude Code wrote this cpp project from the task below. It does not run on a clean Ubuntu 22.04 machine as written.

Task given to the agent:

TASK: Markdown to HTML Converter

Write a program that converts Markdown documents to HTML with support for GitHub Flavored Markdown extensions, syntax highlighting of code blocks, table of contents generation, and custom CSS styling.

FUNCTIONAL REQUIREMENTS:
- Accept a Markdown file path as a command-line argument
- Support standard Markdown: headings (h1-h6), bold, italic, strikethrough, links, images, blockquotes, ordered and unordered lists, horizontal rules, inline code, and code blocks
- Support GitHub Flavored Markdown extensions: tables, task lists (checkboxes), fenced code blocks with language identifiers, autolinks, and footnotes
- Apply syntax highlighting to fenced code blocks based on the specified language (support at least: python, javascript, java, c++, html, css, json, bash)
- Generate a table of contents from headings via --toc flag, inserted at the top of the document with anchor links
- Support custom CSS styling via --css flag (path to a CSS file to embed or link in the output)
- Support wrapping the output in a complete HTML document (with DOCTYPE, head, body) via --full-page flag, or outputting just the HTML fragment (default)
- Support automatic heading ID generation for anchor links based on heading text
- Support converting multiple Markdown files via --batch flag, with optional --index flag to generate an index page linking all converted files
- Print the HTML output to console by default
- Save the HTML to a file via --output flag (default: same base name with .html extension)
- If no input file is given, generate a sample Markdown document demonstrating all supported features (headings, lists, code blocks, tables, images, links, task lists, footnotes), convert it, and save both the Markdown source and HTML output
- Handle errors: invalid Markdown syntax (graceful degradation), missing linked files, and encoding issues

Create a complete C++ project for a clean Ubuntu 22.04 machine with only G++ 12+ and CMake 3.22+ installed. Include:
- Source code
- CMakeLists.txt with all dependencies (direct and transitive) pinned to exact versions
- README.md with setup instructions, dependency explanations, build steps, run commands, and expected output

04 / LABELS

Labels from the report text only; not yet run

No supported category has been assigned.

Label rules and the text that matched
[]

05 / FILES

The project as the agent wrote it

3 files, exactly as written, before any repair.

CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(md_converter VERSION 1.0.0 LANGUAGES C CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# ---------------------------------------------------------------------------
# Dependencies
# ---------------------------------------------------------------------------
# md4c v0.5.2 — Fast Markdown parser in C
# nlohmann/json v3.11.3 — header-only JSON library
# ---------------------------------------------------------------------------

include(FetchContent)

FetchContent_Declare(
    md4c
    GIT_REPOSITORY https://github.com/mity/md4c.git
    GIT_TAG        release-0.5.2
    GIT_SHALLOW    TRUE
)

FetchContent_Declare(
    nlohmann_json
    GIT_REPOSITORY https://github.com/nlohmann/json.git
    GIT_TAG        v3.11.3
    GIT_SHALLOW    TRUE
)

set(JSON_BuildTests OFF CACHE BOOL "" FORCE)
set(JSON_Install    OFF CACHE BOOL "" FORCE)

FetchContent_MakeAvailable(md4c nlohmann_json)

# ---------------------------------------------------------------------------
# Executable
# ---------------------------------------------------------------------------

add_executable(md_converter converter.cpp)

target_include_directories(md_converter PRIVATE
    ${md4c_SOURCE_DIR}/src
)

target_link_libraries(md_converter PRIVATE
    md4c
    md4c-html
    nlohmann_json::nlohmann_json
)

if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
    target_compile_options(md_converter PRIVATE -Wall -Wextra -Wpedantic)
endif()
converter.cpp
/**
 * Markdown to HTML Converter (C++ - Trial 2)
 *
 * Converts Markdown files to HTML with table of contents generation,
 * custom CSS support, and JSON-based configuration using md4c.
 *
 * Dependencies:
 *   - md4c (0.5.2) - Fast Markdown parser in C
 *   - nlohmann/json (3.11.3) - JSON configuration and metadata
 */

#include <md4c-html.h>
#include <nlohmann/json.hpp>

#include <algorithm>
#include <cstring>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <vector>

namespace fs = std::filesystem;
using json = nlohmann::json;

static const std::string DEFAULT_CSS = R"(
body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
    line-height: 1.6; max-width: 900px; margin: 0 auto; padding: 2rem;
    color: #333; background-color: #fff;
}
h1, h2, h3, h4, h5, h6 { margin-top: 1.5em; margin-bottom: 0.5em;
    font-weight: 600; line-height: 1.25; }
h1 { font-size: 2em; border-bottom: 1px solid #eaecef; padding-bottom: 0.3em; }
h2 { font-size: 1.5em; border-bottom: 1px solid #eaecef; padding-bottom: 0.3em; }
h3 { font-size: 1.25em; }
a { color: #0366d6; text-decoration: none; }
a:hover { text-decoration: underline; }
code { background-color: #f6f8fa; border-radius: 3px; padding: 0.2em 0.4em;
       font-size: 85%; font-family: 'SFMono-Regular', Consolas, monospace; }
pre { background-color: #f6f8fa; border-radius: 6px; padding: 16px;
      overflow: auto; line-height: 1.45; }
pre code { background-color: transparent; padding: 0; }
blockquote { margin: 0; padding: 0 1em; color: #6a737d;
             border-left: 0.25em solid #dfe2e5; }
table { border-collapse: collapse; width: 100%; margin-bottom: 1em; }
th, td { border: 1px solid #dfe2e5; padding: 6px 13px; }
th { background-color: #f6f8fa; font-weight: 600; }
tr:nth-child(2n) { background-color: #f6f8fa; }
img { max-width: 100%; }
.toc { background-color: #f6f8fa; border: 1px solid #dfe2e5;
       border-radius: 6px; padding: 1em 1.5em; margin-bottom: 2em; }
.toc ul { list-style-type: none; padding-left: 1.5em; }
.toc > ul { padding-left: 0; }
.toc li { margin: 0.3em 0; }
hr { height: 0.25em; padding: 0; margin: 24px 0;
     background-color: #e1e4e8; border: 0; }
ul, ol { padding-left: 2em; }
li + li { margin-top: 0.25em; }
)";

struct TocEntry {
    int level;
    std::string text;
    std::string id;
};

static std::string escape_html(const std::string& s) {
    std::string out;
    out.reserve(s.size());
    for (char c : s) {
        switch (c) {
            case '&': out += "&amp;"; break;
            case '<': out += "&lt;";  break;
            case '>': out += "&gt;";  break;
            case '"': out += "&quot;"; break;
            default:  out += c;        break;
        }
    }
    return out;
}

static std::string to_slug(const std::string& text) {
    std::string slug;
    for (char c : text) {
        if (std::isalnum(static_cast<unsigned char>(c)))
            slug += static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
        else if (c == ' ' || c == '\t')
            slug += '-';
    }
    return slug;
}

static std::string read_file(const std::string& path) {
    std::ifstream ifs(path, std::ios::binary);
    if (!ifs) throw std::runtime_error("Cannot open file: " + path);
    std::ostringstream ss;
    ss << ifs.rdbuf();
    return ss.str();
}

static void write_file(const std::string& path, const std::string& content) {
    auto parent = fs::path(path).parent_path();
    if (!parent.empty()) fs::create_directories(parent);
    std::ofstream ofs(path, std::ios::binary);
    if (!ofs) throw std::runtime_error("Cannot write file: " + path);
    ofs << content;
}

// md4c callback: appends HTML to the output string
static void md4c_output_callback(const MD_CHAR* data, MD_SIZE size, void* userdata) {
    auto* output = static_cast<std::string*>(userdata);
    output->append(data, size);
}

static std::vector<TocEntry> extract_headings(const std::string& markdown) {
    std::vector<TocEntry> entries;
    std::regex heading_re(R"(^(#{1,6})\s+(.+)$)");
    std::istringstream stream(markdown);
    std::string line;
    while (std::getline(stream, line)) {
        std::smatch match;
        if (std::regex_match(line, match, heading_re)) {
            int level = static_cast<int>(match[1].str().size());
            std::string text = match[2].str();
            while (!text.empty() && std::isspace(static_cast<unsigned char>(text.back())))
                text.pop_back();
            entries.push_back({level, text, to_slug(text)});
        }
    }
    return entries;
}

static std::string generate_toc(const std::vector<TocEntry>& entries,
                                const std::string& toc_title) {
    if (entries.empty()) return "";
    std::ostringstream toc;
    toc << "<div class=\"toc\">\n<h2>" << escape_html(toc_title) << "</h2>\n<ul>\n";
    int prev = entries.front().level;
    for (const auto& e : entries) {
        if (e.level > prev) for (int i = prev; i < e.level; ++i) toc << "<ul>\n";
        else if (e.level < prev) for (int i = e.level; i < prev; ++i) toc << "</ul>\n";
        toc << "<li><a href=\"#" << e.id << "\">" << escape_html(e.text) << "</a></li>\n";
        prev = e.level;
    }
    int start = entries.front().level;
    for (int i = start; i < prev; ++i) toc << "</ul>\n";
    toc << "</ul>\n</div>\n";
    return toc.str();
}

static std::string extract_title(const std::string& markdown) {
    std::regex title_re(R"(^#{1,6}\s+(.+)$)");
    std::istringstream stream(markdown);
    std::string line;
    while (std::getline(stream, line)) {
        std::smatch match;
        if (std::regex_match(line, match, title_re)) {
            std::string t = match[1].str();
            while (!t.empty() && std::isspace(static_cast<unsigned char>(t.back()))) t.pop_back();
            return t;
        }
    }
    return "Converted Document";
}

class MarkdownToHtmlConverter {
public:
    struct Config {
        bool enable_toc = true;
        std::string toc_title = "Table of Contents";
        std::string custom_css_path;
    };

    explicit MarkdownToHtmlConverter(Config cfg = {}) : config_(std::move(cfg)) {
        if (!config_.custom_css_path.empty()) {
            try { custom_css_ = read_file(config_.custom_css_path); }
            catch (const std::exception& e) {
                std::cerr << "Warning: Could not load custom CSS: " << e.what() << "\n";
            }
        }
    }

    std::string convert(const std::string& markdown) const {
        // Use md4c to render HTML
        std::string html_body;
        unsigned parser_flags = MD_FLAG_TABLES | MD_FLAG_STRIKETHROUGH |
                               MD_FLAG_PERMISSIVEAUTOLINKS | MD_FLAG_TASKLISTS |
                               MD_FLAG_PERMISSIVEURLAUTOLINKS;
        unsigned renderer_flags = MD_HTML_FLAG_SKIP_UTF8_BOM;

        int ret = md_html(markdown.c_str(), static_cast<MD_SIZE>(markdown.size()),
                          md4c_output_callback, &html_body,
                          parser_flags, renderer_flags);
        if (ret != 0) {
            throw std::runtime_error("md4c parsing failed");
        }

        std::string toc_html;
        if (config_.enable_toc) {
            auto headings = extract_headings(markdown);
            toc_html = generate_toc(headings, config_.toc_title);
        }

        const std::string& css = custom_css_.empty() ? DEFAULT_CSS : custom_css_;
        std::string title = extract_title(markdown);

        std::ostringstream out;
        out << "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n"
            << "    <meta charset=\"UTF-8\">\n"
            << "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n"
            << "    <title>" << escape_html(title) << "</title>\n"
            << "    <style>\n" << css << "\n    </style>\n"
            << "</head>\n<body>\n"
            << toc_html << html_body
            << "\n</body>\n</html>";
        return out.str();
    }

    std::string convert_file(const std::string& input_path,
                             const std::string& output_path_arg = "") const {
        std::string md = read_file(input_path);
        std::string html = convert(md);
        std::string output_path = output_path_arg;
        if (output_path.empty()) {
            fs::path p(input_path);
            p.replace_extension(".html");
            output_path = p.string();
        }
        write_file(output_path, html);
        return output_path;
    }

    std::string get_metadata() const {
        json meta;
        meta["name"] = "MdConverter";
        meta["version"] = "1.0.0";
        meta["tocEnabled"] = config_.enable_toc;
        meta["tocTitle"] = config_.toc_title;
        meta["backend"] = "md4c";
        return meta.dump(2);
    }

    static Config load_config(const std::string& path) {
        std::string content = read_file(path);
        json j = json::parse(content);
        Config cfg;
        if (j.contains("enableToc"))     cfg.enable_toc = j["enableToc"].get<bool>();
        if (j.contains("tocTitle"))      cfg.toc_title  = j["tocTitle"].get<std::string>();
        if (j.contains("customCssPath")) cfg.custom_css_path = j["customCssPath"].get<std::string>();
        return cfg;
    }

    static void generate_default_config(const std::string& path) {
        json cfg;
        cfg["enableToc"] = true;
        cfg["tocTitle"] = "Table of Contents";
        cfg["customCssPath"] = "";
        write_file(path, cfg.dump(2));
        std::cout << "Default configuration written to: " << path << "\n";
    }

private:
    Config config_;
    std::string custom_css_;
};

static void print_usage() {
    std::cout << "Usage: md_converter [options] <input.md>\n\n"
              << "Options:\n"
              << "  -o, --output <file>    Output HTML file path\n"
              << "  -c, --config <file>    Path to JSON configuration file\n"
              << "  --generate-config      Generate a default config file\n"
              << "  --no-toc               Disable table of contents\n"
              << "  --stdout               Print HTML to stdout\n"
              << "  -h, --help             Show this help message\n";
}

int main(int argc, char* argv[]) {
    std::string input_file, output_file, config_file;
    bool gen_config = false, to_stdout = false, no_toc = false;

    for (int i = 1; i < argc; ++i) {
        std::string arg = argv[i];
        if (arg == "-o" || arg == "--output") { if (++i < argc) output_file = argv[i]; }
        else if (arg == "-c" || arg == "--config") { if (++i < argc) config_file = argv[i]; }
        else if (arg == "--generate-config") gen_config = true;
        else if (arg == "--no-toc") no_toc = true;
        else if (arg == "--stdout") to_stdout = true;
        else if (arg == "-h" || arg == "--help") { print_usage(); return 0; }
        else if (arg[0] != '-') input_file = arg;
    }

    try {
        if (gen_config) {
            MarkdownToHtmlConverter::generate_default_config(
                config_file.empty() ? "md-converter-config.json" : config_file);
            return 0;
        }
        if (input_file.empty()) {
            std::cerr << "Error: No input file specified.\n";
            print_usage();
            return 1;
        }

        MarkdownToHtmlConverter::Config cfg;
        if (!config_file.empty()) cfg = MarkdownToHtmlConverter::load_config(config_file);
        if (no_toc) cfg.enable_toc = false;

        MarkdownToHtmlConverter converter(cfg);
        if (to_stdout) {
            std::cout << converter.convert(read_file(input_file)) << "\n";
        } else {
            std::string out = converter.convert_file(input_file, output_file);
            std::cout << "HTML written to: " << out << "\n";
        }
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << "\n";
        return 1;
    }
    return 0;
}
README.md
# Markdown to HTML Converter (C++ - Trial 2)

A C++ Markdown to HTML converter using md4c for fast Markdown parsing and nlohmann/json for configuration and metadata.

## Dependencies

- **md4c** (0.5.2) - Fast C Markdown parser with GFM extensions (tables, strikethrough, autolinks, task lists)
- **nlohmann/json** (3.11.3) - Header-only JSON library for configuration loading and metadata output

## Build

```bash
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
```

## Usage

```bash
# Basic conversion
./build/md_converter input.md

# Specify output file
./build/md_converter input.md -o output.html

# Use configuration file
./build/md_converter input.md -c config.json

# Disable table of contents
./build/md_converter input.md --no-toc

# Print to stdout
./build/md_converter input.md --stdout

# Generate default configuration
./build/md_converter --generate-config
```

## Features

- Fast Markdown parsing via md4c with GFM extensions
- Automatic table of contents generation
- JSON-based configuration via nlohmann/json
- Custom CSS support
- Complete HTML document output