diff --git a/CHANGELOG.md b/CHANGELOG.md
index dbb6317c..68ba13e7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -272,6 +272,8 @@ Fixes:
Fix reference link definition label matching in a case when the label ends
with a Unicode character with non-trivial case folding mapping.
+ * [#29](https://github.com/mity/md4c/issues/29):
+ Implement Wiky-style ('|2> text |') table colspan extension.
## Version 0.4.6
diff --git a/CMakeLists.txt b/CMakeLists.txt
index aec8293d..bf1303d0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -68,4 +68,23 @@ include(GNUInstallDirs)
add_subdirectory(src)
if (BUILD_MD2HTML_EXECUTABLE)
add_subdirectory(md2html)
-endif ()
+ set(MINIMUM_PYTHON_VERSION "3.6")
+ set(TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}/test")
+ find_package(Python3 COMPONENTS Interpreter)
+ if(Python3_FOUND AND NOT Python3_VERSION VERSION_LESS ${MINIMUM_PYTHON_VERSION})
+ enable_testing()
+ file(GLOB TEST_FILES "${CMAKE_CURRENT_SOURCE_DIR}/test/*.txt")
+ # get_target_property(PROGRAM md2html LOCATION)
+ set(PROGRAM "${CMAKE_CURRENT_BINARY_DIR}/md2html/md2html")
+ foreach(TEST_FILE ${TEST_FILES})
+ get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE)
+ add_test(NAME ${TEST_NAME}
+ COMMAND ${Python3_EXECUTABLE} "${TEST_DIR}/run-testsuite.py" -s ${TEST_FILE} -p ${PROGRAM})
+ endforeach()
+ add_test(NAME Pathological_inputs
+ COMMAND ${Python3_EXECUTABLE} "${TEST_DIR}/pathological-tests.py" -p ${PROGRAM})
+ else()
+ message(WARNING "Python not found or version is less than ${MINIMUM_PYTHON_VERSION}.")
+ endif()
+endif()
+
diff --git a/README.md b/README.md
index 2c8ed267..7427decd 100644
--- a/README.md
+++ b/README.md
@@ -97,6 +97,9 @@ extensions:
* With the flag `MD_FLAG_TABLES`, GitHub-style tables are supported.
+* With the flag `MD_FLAG_TABLES_COLSPAN`, wiky-style ('|2> text |') table
+ colspan are supported.
+
* With the flag `MD_FLAG_TASKLISTS`, GitHub-style task lists are supported.
* With the flag `MD_FLAG_STRIKETHROUGH`, strike-through spans are enabled
diff --git a/md2html/md2html.c b/md2html/md2html.c
index de4ab18e..b525d132 100644
--- a/md2html/md2html.c
+++ b/md2html/md2html.c
@@ -255,6 +255,7 @@ static const CMDLINE_OPTION cmdline_options[] = {
{ 0, "fpermissive-www-autolinks", '.', 0 },
{ 0, "fstrikethrough", 'S', 0 },
{ 0, "ftables", 'T', 0 },
+ { 0, "ftable-colspan", 'J', 0 },
{ 0, "ftasklists", 'X', 0 },
{ 0, "funderline", '_', 0 },
{ 0, "fverbatim-entities", 'E', 0 },
@@ -310,6 +311,7 @@ usage(void)
" Force all soft breaks to act as hard breaks\n"
" --fstrikethrough Enable strike-through spans\n"
" --ftables Enable tables\n"
+ " --ftable-colspan Enable table colspan extension ('|2> text |')\n"
" --ftasklists Enable task lists\n"
" --funderline Enable underline spans\n"
" --fwiki-links Enable wiki links\n"
@@ -382,6 +384,7 @@ cmdline_callback(int opt, char const* value, void* data)
case '@': parser_flags |= MD_FLAG_PERMISSIVEEMAILAUTOLINKS; break;
case 'V': parser_flags |= MD_FLAG_PERMISSIVEAUTOLINKS; break;
case 'T': parser_flags |= MD_FLAG_TABLES; break;
+ case 'J': parser_flags |= MD_FLAG_TABLES_COLSPAN; break;
case 'S': parser_flags |= MD_FLAG_STRIKETHROUGH; break;
case 'L': parser_flags |= MD_FLAG_LATEXMATHSPANS; break;
case 'K': parser_flags |= MD_FLAG_WIKILINKS; break;
diff --git a/src/md4c-html.c b/src/md4c-html.c
index 5229de54..b142cde1 100644
--- a/src/md4c-html.c
+++ b/src/md4c-html.c
@@ -312,15 +312,24 @@ render_open_code_block(MD_HTML* r, const MD_BLOCK_CODE_DETAIL* det)
static void
render_open_td_block(MD_HTML* r, const MD_CHAR* cell_type, const MD_BLOCK_TD_DETAIL* det)
{
+ MD_CHAR tail[2];
+
RENDER_VERBATIM(r, "<");
RENDER_VERBATIM(r, cell_type);
switch(det->align) {
- case MD_ALIGN_LEFT: RENDER_VERBATIM(r, " align=\"left\">"); break;
- case MD_ALIGN_CENTER: RENDER_VERBATIM(r, " align=\"center\">"); break;
- case MD_ALIGN_RIGHT: RENDER_VERBATIM(r, " align=\"right\">"); break;
- default: RENDER_VERBATIM(r, ">"); break;
+ case MD_ALIGN_LEFT: RENDER_VERBATIM(r, " align=\"left\""); break;
+ case MD_ALIGN_CENTER: RENDER_VERBATIM(r, " align=\"center\""); break;
+ case MD_ALIGN_RIGHT: RENDER_VERBATIM(r, " align=\"right\""); break;
+ case MD_ALIGN_DEFAULT: break;
+ }
+ if (det->colspan > 1) {
+ RENDER_VERBATIM(r, " colspan=\"");
+ tail[0] = '0' + det->colspan;
+ tail[1] = '\"';
+ render_verbatim(r, tail, 2);
}
+ RENDER_VERBATIM(r, ">");
}
static void
diff --git a/src/md4c.c b/src/md4c.c
index e3f5cf9d..9074aa3e 100644
--- a/src/md4c.c
+++ b/src/md4c.c
@@ -4529,10 +4529,9 @@ md_analyze_table_alignment(MD_CTX* ctx, OFF beg, OFF end, MD_ALIGN* align, int n
static int md_process_normal_block_contents(MD_CTX* ctx, const MD_LINE* lines, MD_SIZE n_lines);
static int
-md_process_table_cell(MD_CTX* ctx, MD_BLOCKTYPE cell_type, MD_ALIGN align, OFF beg, OFF end)
+md_process_table_cell(MD_CTX* ctx, MD_BLOCKTYPE cell_type, MD_BLOCK_TD_DETAIL *det, OFF beg, OFF end)
{
MD_LINE line;
- MD_BLOCK_TD_DETAIL det;
int ret = 0;
while(beg < end && ISWHITESPACE(beg))
@@ -4540,13 +4539,12 @@ md_process_table_cell(MD_CTX* ctx, MD_BLOCKTYPE cell_type, MD_ALIGN align, OFF b
while(end > beg && ISWHITESPACE(end-1))
end--;
- det.align = align;
line.beg = beg;
line.end = end;
- MD_ENTER_BLOCK(cell_type, &det);
+ MD_ENTER_BLOCK(cell_type, det);
MD_CHECK(md_process_normal_block_contents(ctx, &line, 1));
- MD_LEAVE_BLOCK(cell_type, &det);
+ MD_LEAVE_BLOCK(cell_type, det);
abort:
return ret;
@@ -4557,6 +4555,10 @@ md_process_table_row(MD_CTX* ctx, MD_BLOCKTYPE cell_type, OFF beg, OFF end,
const MD_ALIGN* align, int col_count)
{
MD_LINE line;
+ MD_LINE cell;
+ MD_BLOCK_TD_DETAIL det;
+
+ unsigned is_spans;
OFF* pipe_offs = NULL;
int i, j, k, n;
int ret = 0;
@@ -4583,19 +4585,36 @@ md_process_table_row(MD_CTX* ctx, MD_BLOCKTYPE cell_type, OFF beg, OFF end,
MD_MARK* mark = &ctx->marks[i];
pipe_offs[j++] = mark->end;
}
- pipe_offs[j++] = end+1;
+ pipe_offs[j] = end+1;
+ is_spans = ctx->parser.flags & MD_FLAG_TABLES_COLSPAN;
/* Process cells. */
MD_ENTER_BLOCK(MD_BLOCK_TR, NULL);
k = 0;
- for(i = 0; i < j-1 && k < col_count; i++) {
- if(pipe_offs[i] < pipe_offs[i+1]-1)
- MD_CHECK(md_process_table_cell(ctx, cell_type, align[k++], pipe_offs[i], pipe_offs[i+1]-1));
+ for(i = 0; i < j && k < col_count; i++) {
+ cell.beg = pipe_offs[i];
+ cell.end = pipe_offs[i+1]-1;
+
+ if(cell.beg < cell.end) {
+ det.colspan = 0;
+ if (is_spans && cell.end - cell.beg >= 2 &&
+ ISDIGIT(cell.beg) && CH(cell.beg+1) == '>') {
+ det.colspan = CH(cell.beg) - '0';
+ cell.beg += 2;
+ }
+ det.align = align[k++];
+ MD_CHECK(md_process_table_cell(ctx, cell_type, &det, cell.beg, cell.end));
+ if (is_spans && det.colspan > 1)
+ k += det.colspan - 1;
+ }
}
/* Make sure we call enough table cells even if the current table contains
* too few of them. */
- while(k < col_count)
- MD_CHECK(md_process_table_cell(ctx, cell_type, align[k++], 0, 0));
+ det.colspan = 0;
+ while(k < col_count) {
+ det.align = align[k++];
+ MD_CHECK(md_process_table_cell(ctx, cell_type, &det, 0, 0));
+ }
MD_LEAVE_BLOCK(MD_BLOCK_TR, NULL);
abort:
diff --git a/src/md4c.h b/src/md4c.h
index 8d6be1cb..8ca7e782 100644
--- a/src/md4c.h
+++ b/src/md4c.h
@@ -278,6 +278,7 @@ typedef struct MD_BLOCK_TABLE_DETAIL {
/* Detailed info for MD_BLOCK_TH and MD_BLOCK_TD. */
typedef struct MD_BLOCK_TD_DETAIL {
MD_ALIGN align;
+ int colspan;
} MD_BLOCK_TD_DETAIL;
/* Detailed info for MD_SPAN_A. */
@@ -318,6 +319,7 @@ typedef struct MD_SPAN_WIKILINK {
#define MD_FLAG_WIKILINKS 0x2000 /* Enable wiki links extension. */
#define MD_FLAG_UNDERLINE 0x4000 /* Enable underline extension (and disables '_' for normal emphasis). */
#define MD_FLAG_HARD_SOFT_BREAKS 0x8000 /* Force all soft breaks to act as hard breaks. */
+#define MD_FLAG_TABLES_COLSPAN 0x10000 /* Enable table colspan extension '|2> 2-colspan cell |'. */
#define MD_FLAG_PERMISSIVEAUTOLINKS (MD_FLAG_PERMISSIVEEMAILAUTOLINKS | MD_FLAG_PERMISSIVEURLAUTOLINKS | MD_FLAG_PERMISSIVEWWWAUTOLINKS)
#define MD_FLAG_NOHTML (MD_FLAG_NOHTMLBLOCKS | MD_FLAG_NOHTMLSPANS)
diff --git a/test/spec-tables-colspan.txt b/test/spec-tables-colspan.txt
new file mode 100644
index 00000000..47a03e91
--- /dev/null
+++ b/test/spec-tables-colspan.txt
@@ -0,0 +1,74 @@
+
+# Table colspan extension
+
+With the flag `MD_FLAG_TABLES_COLSPAN`, MD4C enables extension for recognition
+of table colspan's.
+
+Basic table example of a table with colspan:
+
+```````````````````````````````` example
+| Column 1 | Column 2 |
+|----------|----------|
+| foo | bar |
+|2> baz |
+| quux | quuz |
+.
+
+
+| Column 1 | Column 2 |
+
+
+| foo | bar |
+| baz |
+| quux | quuz |
+
+
+.
+--ftables --ftable-colspan
+````````````````````````````````
+
+Only one digit are allowed:
+
+```````````````````````````````` example
+| Column 1 | Column 2 |
+|----------|----------|
+| foo | bar |
+|22> baz |
+| quux | quuz |
+.
+
+
+| Column 1 | Column 2 |
+
+
+| foo | bar |
+| 22> baz | |
+| quux | quuz |
+
+
+.
+--ftables --ftable-colspan
+````````````````````````````````
+
+The arrow character must follow without spaces:
+
+```````````````````````````````` example
+| Column 1 | Column 2 |
+|----------|----------|
+| foo | bar |
+| 2 > baz |
+| quux | quuz |
+.
+
+
+| Column 1 | Column 2 |
+
+
+| foo | bar |
+| 2 > baz | |
+| quux | quuz |
+
+
+.
+--ftables --ftable-colspan
+````````````````````````````````