#include <gtest/gtest.h>
#include "macrodown.h"
using namespace macrodown;
TEST(CustomMarkupTest, PrefixMarkup)
{
MacroDown md;
// Define # as prefix markup for 'tag'
md.definePrefixMarkup({"#", "tag", ""});
// We also need to define what the 'tag' macro does in HTML
md.evaluator().define("tag", {"content"}, "<span class=\"tag\">#%content</span>");
std::string input = "This is a #test markup.";
auto root = md.parse(input);
std::string html = md.render(*root);
EXPECT_EQ(html, "<p>This is a <span class=\"tag\">#test</span> markup.</p>\n");
}
TEST(CustomMarkupTest, PrefixMarkupPunctuation)
{
MacroDown md;
md.definePrefixMarkup({"#", "tag", ""});
md.evaluator().define("tag", {"content"}, "[%content]");
// Punctuation should end the prefix markup, except for underscore
std::string input = "#test. #more_test! #final";
std::string html = md.render(*md.parse(input));
EXPECT_EQ(html, "<p>[test]. [more_test]! [final]</p>\n");
}
TEST(CustomMarkupTest, DelimitedMarkup)
{
MacroDown md;
// Define : as delimited markup for 'highlight'
md.defineDelimitedMarkup({":", "highlight", ""});
md.evaluator().define("highlight", {"content"}, "<mark>%content</mark>");
std::string input = "This is :important: text.";
std::string html = md.render(*md.parse(input));
EXPECT_EQ(html, "<p>This is <mark>important</mark> text.</p>\n");
}
TEST(CustomMarkupTest, DelimitedMarkupInvalid)
{
MacroDown md;
md.defineDelimitedMarkup({":", "highlight", ""});
md.evaluator().define("highlight", {"content"}, "<mark>%content</mark>");
// Whitespace or punctuation (except _ and -) makes it invalid
std::string input = "This is :not valid: because of space. And :this.too: because of dot.";
std::string html = md.render(*md.parse(input));
// Should remain as plain text
EXPECT_EQ(html, "<p>This is :not valid: because of space. And :this.too: because of dot.</p>\n");
}
TEST(CustomMarkupTest, DelimitedMarkupUnderscoreDash)
{
MacroDown md;
md.defineDelimitedMarkup({":", "highlight", ""});
md.evaluator().define("highlight", {"content"}, "<mark>%content</mark>");
std::string input = "This is :valid_with-extra: text.";
std::string html = md.render(*md.parse(input));
EXPECT_EQ(html, "<p>This is <mark>valid_with-extra</mark> text.</p>\n");
}
TEST(CustomMarkupTest, UnicodeMarkup)
{
MacroDown md;
// Multi-byte prefix (e.g., symbol)
md.definePrefixMarkup({"§", "section", ""});
md.evaluator().define("section", {"content"}, "Sec. %content");
std::string input = "See §A.1";
std::string html = md.render(*md.parse(input));
EXPECT_EQ(html, "<p>See Sec. A.1</p>\n");
}
TEST(CustomMarkupTest, PrefixMarkupExtendedCharacters)
{
MacroDown md;
md.definePrefixMarkup({"#", "tag", ""});
md.evaluator().define("tag", {"content"}, "[%content]");
// Dash and @ should NOT end the prefix markup per updated PRD
std::string input = "#test-case #user@domain";
std::string html = md.render(*md.parse(input));
EXPECT_EQ(html, "<p>[test-case] [user@domain]</p>\n");
}
TEST(CustomMarkupTest, PrefixMarkupAtPrefix)
{
MacroDown md;
md.definePrefixMarkup({"@", "mention", ""});
md.evaluator().define("mention", {"content"}, "<a href=\" /u/%content\">@%content</a>");
// Dash, @ and . allowed inside.
std::string input = "Hello @user-name! Email: @user@domain.com";
std::string html = md.render(*md.parse(input));
EXPECT_EQ(html, "<p>Hello <a href=\" /u/user-name\">@user-name</a>! Email: <a href=\" /u/user@domain.com\">@user@domain.com</a></p>\n");
}
TEST(CustomMarkupTest, PrefixMarkupTrailingDot)
{
MacroDown md;
md.definePrefixMarkup({"@", "mention", ""});
md.evaluator().define("mention", {"content"}, "(%content)");
std::string input = "End of sentence @mention. Another @mention..";
std::string html = md.render(*md.parse(input));
// @mention. -> mention
// @mention.. -> mention. (first dot kept, second excluded)
EXPECT_EQ(html, "<p>End of sentence (mention). Another (mention.).</p>\n");
}