test "heading_1" { const input = "# hello this is a heading\n"; const parsed = [_]Token{ Token{ .type = .heading, .data = "#", }, Token{ .type = .text, .data = "hello this is a heading\n", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "heading_2" { const input = "## hello this is a heading\n"; const parsed = [_]Token{ Token{ .type = .heading, .data = "##", }, Token{ .type = .text, .data = "hello this is a heading\n", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "heading_3" { const input = "### hello this is a heading\n"; const parsed = [_]Token{ Token{ .type = .heading, .data = "###", }, Token{ .type = .text, .data = "hello this is a heading\n", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "heading_4" { const input = "#### hello this is a heading\n"; const parsed = [_]Token{ Token{ .type = .heading, .data = "####", }, Token{ .type = .text, .data = "hello this is a heading\n", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "heading_5" { const input = "##### hello this is a heading\n"; const parsed = [_]Token{ Token{ .type = .heading, .data = "#####", }, Token{ .type = .text, .data = "hello this is a heading\n", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "heading_6" { const input = "###### hello this is a heading\n"; const parsed = [_]Token{ Token{ .type = .heading, .data = "######", }, Token{ .type = .text, .data = "hello this is a heading\n", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "header_no_text" { const input = "######\n"; const parsed = [_]Token{ Token{ .type = .heading, .data = "######", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text" { const input = "plain test\n"; const parsed = [_]Token{ Token{ .type = .text, .data = "plain test", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_code" { const input = "`plain test`\n"; const parsed = [_]Token{ Token{ .type = .inline_style, .data = "`", }, Token{ .type = .text, .data = "plain test", }, Token{ .type = .inline_style, .data = "`", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_bold" { const input = "!plain test!\n"; const parsed = [_]Token{ Token{ .type = .inline_style, .data = "!", }, Token{ .type = .text, .data = "plain test", }, Token{ .type = .inline_style, .data = "!", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_italic" { const input = "*plain test*\n"; const parsed = [_]Token{ Token{ .type = .inline_style, .data = "*", }, Token{ .type = .text, .data = "plain test", }, Token{ .type = .inline_style, .data = "*", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_underline" { const input = "_plain test_\n"; const parsed = [_]Token{ Token{ .type = .inline_style, .data = "_", }, Token{ .type = .text, .data = "plain test", }, Token{ .type = .inline_style, .data = "_", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_strikethrough" { const input = "~plain test~\n"; const parsed = [_]Token{ Token{ .type = .inline_style, .data = "~", }, Token{ .type = .text, .data = "plain test", }, Token{ .type = .inline_style, .data = "~", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_highlighted" { const input = "|plain test|\n"; const parsed = [_]Token{ Token{ .type = .inline_style, .data = "|", }, Token{ .type = .text, .data = "plain test", }, Token{ .type = .inline_style, .data = "|", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_&" { const input = "&plain test&\n"; const parsed = [_]Token{ Token{ .type = .inline_style, .data = "&", }, Token{ .type = .text, .data = "plain test", }, Token{ .type = .inline_style, .data = "&", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_%" { const input = "%plain test%\n"; const parsed = [_]Token{ Token{ .type = .inline_style, .data = "%", }, Token{ .type = .text, .data = "plain test", }, Token{ .type = .inline_style, .data = "%", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_$" { const input = "$plain test$\n"; const parsed = [_]Token{ Token{ .type = .inline_style, .data = "$", }, Token{ .type = .text, .data = "plain test", }, Token{ .type = .inline_style, .data = "$", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_#" { const input = "#plain test#\n"; const parsed = [_]Token{ Token{ .type = .inline_style, .data = "#", }, Token{ .type = .text, .data = "plain test", }, Token{ .type = .inline_style, .data = "#", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_-" { const input = "-plain test-\n"; const parsed = [_]Token{ Token{ .type = .inline_style, .data = "-", }, Token{ .type = .text, .data = "plain test", }, Token{ .type = .inline_style, .data = "-", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_+" { const input = "+plain test+\n"; const parsed = [_]Token{ Token{ .type = .inline_style, .data = "+", }, Token{ .type = .text, .data = "plain test", }, Token{ .type = .inline_style, .data = "+", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_=" { const input = "=plain test=\n"; const parsed = [_]Token{ Token{ .type = .inline_style, .data = "=", }, Token{ .type = .text, .data = "plain test", }, Token{ .type = .inline_style, .data = "=", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_super_script" { const input = "sometext^2\n"; const parsed = [_]Token{ Token{ .type = .text, .data = "sometext", }, Token{ .type = .sup, .data = "^", }, Token{ .type = .text, .data = "2", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_style_sub_script" { const input = "sometext_2\n"; const parsed = [_]Token{ Token{ .type = .text, .data = "sometext", }, Token{ .type = .sub, .data = "_", }, Token{ .type = .text, .data = "2", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "list_ordered_number" { const input = "1. ordered list\n2. ordered list\n3. ordered list\n"; const parsed = [_]Token{ Token{ .type = .ordered_list, .data = "1.", }, Token{ .type = .text, .data = "ordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .ordered_list, .data = "2.", }, Token{ .type = .text, .data = "ordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .ordered_list, .data = "3.", }, Token{ .type = .text, .data = "ordered list", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "list_ordered_i" { const input = "i. ordered list\nii. ordered list\niii. ordered list\n"; const parsed = [_]Token{ Token{ .type = .ordered_list, .data = "i.", }, Token{ .type = .text, .data = "ordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .ordered_list, .data = "ii.", }, Token{ .type = .text, .data = "ordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .ordered_list, .data = "iii.", }, Token{ .type = .text, .data = "ordered list", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "list_ordered_letter" { const input = "a. ordered list\nb. ordered list\nc. ordered list\n"; const parsed = [_]Token{ Token{ .type = .ordered_list, .data = "a.", }, Token{ .type = .text, .data = "ordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .ordered_list, .data = "b.", }, Token{ .type = .text, .data = "ordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .ordered_list, .data = "c.", }, Token{ .type = .text, .data = "ordered list", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "list_unordered_dashed" { const input = "- unordered list\n- unordered list\n- unordered list\n"; const parsed = [_]Token{ Token{ .type = .unordered_list, .data = "-", }, Token{ .type = .text, .data = "unordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .unordered_list, .data = "-", }, Token{ .type = .text, .data = "unordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .unordered_list, .data = "-", }, Token{ .type = .text, .data = "unordered list", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "list_unordered_eq" { const input = "= unordered list\n= unordered list\n= unordered list\n"; const parsed = [_]Token{ Token{ .type = .unordered_list, .data = "=", }, Token{ .type = .text, .data = "unordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .unordered_list, .data = "=", }, Token{ .type = .text, .data = "unordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .unordered_list, .data = "=", }, Token{ .type = .text, .data = "unordered list", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "list_unordered_plus" { const input = "+ unordered list\n+ unordered list\n+ unordered list\n"; const parsed = [_]Token{ Token{ .type = .unordered_list, .data = "+", }, Token{ .type = .text, .data = "unordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .unordered_list, .data = "+", }, Token{ .type = .text, .data = "unordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .unordered_list, .data = "+", }, Token{ .type = .text, .data = "unordered list", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "list_unordered_dot" { const input = "* unordered list\n* unordered list\n* unordered list\n"; const parsed = [_]Token{ Token{ .type = .unordered_list, .data = "*", }, Token{ .type = .text, .data = "unordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .unordered_list, .data = "*", }, Token{ .type = .text, .data = "unordered list", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .unordered_list, .data = "*", }, Token{ .type = .text, .data = "unordered list", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "embed_image" { const input = "![figure text](relitive path to image)\n"; const parsed = [_]Token{ Token{ .type = .embed, .data = "!", }, Token{ .type = .bracket_open, .data = "[", }, Token{ .type = .text, .data = "figure text", }, Token{ .type = .bracket_close, .data = "]", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .raw_text, .data = "relitive path to image", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "embed_table" { const input = "#[table text](relitive path to tabulated data)\n"; const parsed = [_]Token{ Token{ .type = .embed, .data = "#", }, Token{ .type = .bracket_open, .data = "[", }, Token{ .type = .text, .data = "table text", }, Token{ .type = .bracket_close, .data = "]", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .raw_text, .data = "relitive path to tabulated data", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "embed_file" { const input = "$[file text](path to file#starting_line:ending_line)\n"; const parsed = [_]Token{ Token{ .type = .embed, .data = "$", }, Token{ .type = .bracket_open, .data = "[", }, Token{ .type = .text, .data = "file text", }, Token{ .type = .bracket_close, .data = "]", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .raw_text, .data = "path to file#starting_line:ending_line", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "embed_*" { const input = "*[file text](file_path)\n"; const parsed = [_]Token{ Token{ .type = .embed, .data = "*", }, Token{ .type = .bracket_open, .data = "[", }, Token{ .type = .text, .data = "file text", }, Token{ .type = .bracket_close, .data = "]", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .raw_text, .data = "file_path", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "embed__" { const input = "_[file text](file_path)\n"; const parsed = [_]Token{ Token{ .type = .embed, .data = "_", }, Token{ .type = .bracket_open, .data = "[", }, Token{ .type = .text, .data = "file text", }, Token{ .type = .bracket_close, .data = "]", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .raw_text, .data = "file_path", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "embed_~" { const input = "~[file text](file_path)\n"; const parsed = [_]Token{ Token{ .type = .embed, .data = "~", }, Token{ .type = .bracket_open, .data = "[", }, Token{ .type = .text, .data = "file text", }, Token{ .type = .bracket_close, .data = "]", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .raw_text, .data = "file_path", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "embed_|" { const input = "|[file text](file_path)\n"; const parsed = [_]Token{ Token{ .type = .embed, .data = "|", }, Token{ .type = .bracket_open, .data = "[", }, Token{ .type = .text, .data = "file text", }, Token{ .type = .bracket_close, .data = "]", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .raw_text, .data = "file_path", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "embed_&" { const input = "&[file text](file_path)\n"; const parsed = [_]Token{ Token{ .type = .embed, .data = "&", }, Token{ .type = .bracket_open, .data = "[", }, Token{ .type = .text, .data = "file text", }, Token{ .type = .bracket_close, .data = "]", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .raw_text, .data = "file_path", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "embed_%" { const input = "%[file text](file_path)\n"; const parsed = [_]Token{ Token{ .type = .embed, .data = "%", }, Token{ .type = .bracket_open, .data = "[", }, Token{ .type = .text, .data = "file text", }, Token{ .type = .bracket_close, .data = "]", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .raw_text, .data = "file_path", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "embed_-" { const input = "-[file text](file_path)\n"; const parsed = [_]Token{ Token{ .type = .embed, .data = "-", }, Token{ .type = .bracket_open, .data = "[", }, Token{ .type = .text, .data = "file text", }, Token{ .type = .bracket_close, .data = "]", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .raw_text, .data = "file_path", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "embed_+" { const input = "+[file text](file_path)\n"; const parsed = [_]Token{ Token{ .type = .embed, .data = "+", }, Token{ .type = .bracket_open, .data = "[", }, Token{ .type = .text, .data = "file text", }, Token{ .type = .bracket_close, .data = "]", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .raw_text, .data = "file_path", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "embed_=" { const input = "=[file text](file_path)\n"; const parsed = [_]Token{ Token{ .type = .embed, .data = "=", }, Token{ .type = .bracket_open, .data = "[", }, Token{ .type = .text, .data = "file text", }, Token{ .type = .bracket_close, .data = "]", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .raw_text, .data = "file_path", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "embed_link" { const input = "/[file text](link to something)\n"; const parsed = [_]Token{ Token{ .type = .link, .data = "/", }, Token{ .type = .bracket_open, .data = "[", }, Token{ .type = .text, .data = "file text", }, Token{ .type = .bracket_close, .data = "]", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .raw_text, .data = "link to something", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "table" { const input = "| col | col | col |\n| --- | --- | --- |\n| row | row | row |\n| row | row | row |\n| row | row | row |\n| row | row | row |\n"; const parsed = [_]Token{ Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " col ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " col ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " col ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .table_row_sep, .data = " --- ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .table_row_sep, .data = " --- ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .table_row_sep, .data = " --- ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " row ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " row ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " row ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " row ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " row ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " row ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " row ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " row ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " row ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " row ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " row ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .text, .data = " row ", }, Token{ .type = .table_sep, .data = "|", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "qoute_arrow" { const input = "> quote\n> quote\n> quote\n"; const parsed = [_]Token{ Token{ .type = .quote, .data = ">", }, Token{ .type = .text, .data = "qoute", }, Token{ .type = .quote, .data = ">", }, Token{ .type = .text, .data = "qoute", }, Token{ .type = .quote, .data = ">", }, Token{ .type = .text, .data = "qoute", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "qoute_bar" { const input = "| quote\n| quote\n| quote\n"; const parsed = [_]Token{ Token{ .type = .quote, .data = "|", }, Token{ .type = .text, .data = "qoute", }, Token{ .type = .quote, .data = "|", }, Token{ .type = .text, .data = "qoute", }, Token{ .type = .quote, .data = "|", }, Token{ .type = .text, .data = "qoute", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "text_block" { const input = "```\nsome text or code\n```\n"; const parsed = [_]Token{ Token{ .type = .code_block, .data = "```", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .raw_text, .data = "some text or code", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .code_block, .data = "```", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "code_block" { const input = "```lang_name\nsome text or code\n```\n"; const parsed = [_]Token{ Token{ .type = .code_block, .data = "```", }, Token{ .type = .raw_text, .data = "lang_name", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .raw_text, .data = "some text or code", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .code_block, .data = "```", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "passthrough_block" { const input = "```passthrough\nsome text or code\n```\n"; const parsed = [_]Token{ Token{ .type = .code_block, .data = "```", }, Token{ .type = .raw_text, .data = "passthrough", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .raw_text, .data = "some text or code", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .code_block, .data = "```", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "comment" { const input = "// this is a comment\n"; const parsed = [_]Token{ Token{ .type = .comment, .data = "// ", }, Token{ .type = .raw_text, .data = "this is a comment", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "tick_box_empty" { const input = "- [ ] something to check off\n"; const parsed = [_]Token{ Token{ .type = .tickbox, .data = "- [ ]", }, Token{ .type = .text, .data = "something to check off", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "tick_box_checked" { const input = "- [x] something checked off\n"; const parsed = [_]Token{ Token{ .type = .tickbox, .data = "- [x]", }, Token{ .type = .text, .data = "something checked off", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "tick_box_ticked" { const input = "- [/] something ticked off\n"; const parsed = [_]Token{ Token{ .type = .tickbox, .data = "- [/]", }, Token{ .type = .text, .data = "something ticked off", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "tick_box_dashed" { const input = "- [~] something dashed off\n"; const parsed = [_]Token{ Token{ .type = .tickbox, .data = "- [~]", }, Token{ .type = .text, .data = "something dashed off", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "horrazontal_rule_straight_line" { const input = "---\n"; const parsed = [_]Token{ Token{ .type = .rule, .data = "---", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "horrazontal_rule_double_straight_line" { const input = "===\n"; const parsed = [_]Token{ Token{ .type = .rule, .data = "===", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "horrazontal_rule_big_dotted_straight_line" { const input = "***\n"; const parsed = [_]Token{ Token{ .type = .rule, .data = "***", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "horrazontal_rule_small_dotted_line" { const input = "...\n"; const parsed = [_]Token{ Token{ .type = .rule, .data = "...", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "horrazontal_rule_squiggly_line" { const input = "&&&\n"; const parsed = [_]Token{ Token{ .type = .rule, .data = "&&&", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "horrazontal_rule_jagged_line" { const input = "^^^\n"; const parsed = [_]Token{ Token{ .type = .rule, .data = "^^^", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "footnote" { const input = "sometext [^1]\n\n[^1]: footnote\n"; const parsed = [_]Token{ Token{ .type = .text, .data = "sometext ", }, Token{ .type = .footnote, .data = "[^1]", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .newline, .data = "\n", }, Token{ .type = .footnote_def, .data = "[^1]:", }, Token{ .type = .text, .data = "footnote", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "macro" { const input = "@macro(arg, arg2)\n"; const parsed = [_]Token{ Token{ .type = .macro, .data = "macro", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .macro_arg, .data = "arg", }, Token{ .type = .arg_sep, .data = ",", }, Token{ .type = .macro_arg, .data = "arg2", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "replace" { const input = "@replace\n"; const parsed = [_]Token{ Token{ .type = .replace, .data = "replace", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); } test "inbulit" { const input = "@.macro(arg, arg2)\n"; const parsed = [_]Token{ Token{ .type = .inbulit, .data = "macro", }, Token{ .type = .bracket_open, .data = "(", }, Token{ .type = .macro_arg, .data = "arg", }, Token{ .type = .arg_sep, .data = ",", }, Token{ .type = .macro_arg, .data = "arg2", }, Token{ .type = .bracket_close, .data = ")", }, Token{ .type = .newline, .data = "\n", }, }; var parsing = try tokenize(input, std.testing.allocator); try expect(parsing.items.len >= parsed.len); for (parsed, parsing.items[0..parsed.len]) |expected_token, actual_token| { try expect(expected_token.type == actual_token.type); try expect(std.mem.eql(u8, expected_token.data, actual_token.data)); } parsing.deinit(std.testing.allocator); }