Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
21 changes: 20 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()

3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions md2html/md2html.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down
17 changes: 13 additions & 4 deletions src/md4c-html.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
41 changes: 30 additions & 11 deletions src/md4c.c
Original file line number Diff line number Diff line change
Expand Up @@ -4529,24 +4529,22 @@ 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))
beg++;
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;
Expand All @@ -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;
Expand All @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions src/md4c.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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)
Expand Down
74 changes: 74 additions & 0 deletions test/spec-tables-colspan.txt
Original file line number Diff line number Diff line change
@@ -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 |
.
<table>
<thead>
<tr><th>Column 1</th><th>Column 2</th></tr>
</thead>
<tbody>
<tr><td>foo</td><td>bar</td></tr>
<tr><td colspan="2">baz</td></tr>
<tr><td>quux</td><td>quuz</td></tr>
</tbody>
</table>
.
--ftables --ftable-colspan
````````````````````````````````

Only one digit are allowed:

```````````````````````````````` example
| Column 1 | Column 2 |
|----------|----------|
| foo | bar |
|22> baz |
| quux | quuz |
.
<table>
<thead>
<tr><th>Column 1</th><th>Column 2</th></tr>
</thead>
<tbody>
<tr><td>foo</td><td>bar</td></tr>
<tr><td>22&gt; baz</td><td></td></tr>
<tr><td>quux</td><td>quuz</td></tr>
</tbody>
</table>
.
--ftables --ftable-colspan
````````````````````````````````

The arrow character must follow without spaces:

```````````````````````````````` example
| Column 1 | Column 2 |
|----------|----------|
| foo | bar |
| 2 > baz |
| quux | quuz |
.
<table>
<thead>
<tr><th>Column 1</th><th>Column 2</th></tr>
</thead>
<tbody>
<tr><td>foo</td><td>bar</td></tr>
<tr><td>2 &gt; baz</td><td></td></tr>
<tr><td>quux</td><td>quuz</td></tr>
</tbody>
</table>
.
--ftables --ftable-colspan
````````````````````````````````