Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support parse markdown table to html table #42

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ target/
*.releaseBackup
release.properties
*.pyc
*.iml

4 changes: 3 additions & 1 deletion src/main/java/com/github/rjeschke/txtmark/BlockType.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,7 @@ enum BlockType
/** An unordered list. */
UNORDERED_LIST,
/** A XML block. */
XML
XML,
/** A TABLE block. */
TABLE
}
33 changes: 31 additions & 2 deletions src/main/java/com/github/rjeschke/txtmark/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
public class Configuration
{
final boolean safeMode;
final boolean parseTable;
final boolean panicMode;
final String encoding;
final Decorator decorator;
Expand Down Expand Up @@ -67,7 +68,7 @@ public class Configuration
Configuration(final boolean safeMode, final String encoding, final Decorator decorator,
final BlockEmitter codeBlockEmitter,
final boolean forceExtendedProfile, final SpanEmitter specialLinkEmitter,
final boolean allowSpacesInFencedDelimiters, final boolean panicMode)
final boolean allowSpacesInFencedDelimiters, final boolean panicMode,final boolean parseTable)
{
this.safeMode = safeMode;
this.encoding = encoding;
Expand All @@ -77,6 +78,20 @@ public class Configuration
this.specialLinkEmitter = specialLinkEmitter;
this.allowSpacesInFencedDelimiters = allowSpacesInFencedDelimiters;
this.panicMode = panicMode;
this.parseTable = parseTable;
}

/**
* Constructor (just for forward compatible )
*/
Configuration(final boolean safeMode, final String encoding, final Decorator decorator,
final BlockEmitter codeBlockEmitter,
final boolean forceExtendedProfile, final SpanEmitter specialLinkEmitter,
final boolean allowSpacesInFencedDelimiters, final boolean panicMode)
{
this(safeMode,encoding,decorator,
codeBlockEmitter,forceExtendedProfile,specialLinkEmitter,
allowSpacesInFencedDelimiters,panicMode,false);
}

/**
Expand All @@ -101,6 +116,7 @@ public static class Builder
private boolean panicMode = false;
private boolean forceExtendedProfile = false;
private boolean allowSpacesInFencedDelimiters = true;
private boolean parseTable = false;
private String encoding = "UTF-8";
private Decorator decorator = new DefaultDecorator();
private BlockEmitter codeBlockEmitter = null;
Expand Down Expand Up @@ -263,6 +279,19 @@ public Builder enablePanicMode()
return this;
}

/**
* This allows you to enable 'parseTable'. When 'parseTable' is enabled,
* it'll try to parse html table from markdown syntax
*
* @return This builder.
* @since 0.12
*/
public Builder enableParseTable()
{
this.parseTable = true;
return this;
}

/**
* Builds a configuration instance.
*
Expand All @@ -273,7 +302,7 @@ public Configuration build()
{
return new Configuration(this.safeMode, this.encoding, this.decorator, this.codeBlockEmitter,
this.forceExtendedProfile, this.specialLinkEmitter, this.allowSpacesInFencedDelimiters,
this.panicMode);
this.panicMode,this.parseTable);
}
}
}
63 changes: 63 additions & 0 deletions src/main/java/com/github/rjeschke/txtmark/Emitter.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ private void emitLines(final StringBuilder out, final Block block)
case XML:
this.emitRawLines(out, block.lines);
break;
case TABLE:
this.emitTableLines(out,block.lines);
break;
default:
this.emitMarkedLines(out, block.lines);
break;
Expand Down Expand Up @@ -1045,4 +1048,64 @@ private void emitCodeLines(final StringBuilder out, final Line lines, final Stri
}
}
}

enum Align{
LEFT,CENTER,RIGHT
}

private void emitTableLines(StringBuilder out, Line line) {
String[] tableHead = line.value.split("\\|");
//TODO support align position
String[] alignHead = (line.next.value).split("\\|");
Align[] aligns = new Align[alignHead.length];

line = line.next.next;//Skip ---|---|---...

out.append("<table>\n");

out.append("<thead><tr>");
for (int i = 0; i < tableHead.length; i++)
{
String text = tableHead[i].trim();
if("".equals(text))
{
if(i == 0 || (i == tableHead.length -1))
{
continue;
}
}
out.append("<th>").append(text).append("</th>");
}
out.append("</tr></thead>");

if(line != null && !line.isEmpty)
{
out.append("\n<tbody>");
while (line != null)
{
if (!line.isEmpty)
{
out.append("\n<tr>");
String[] tds = line.value.split("\\|");

for (int i = 0; i < tds.length; i++)
{
String text = tds[i].trim();
if("".equals(text))
{
if(i == 0 || (i == tableHead.length -1))
{
continue;
}
}
out.append("<td>").append(text).append("</td>");
}
out.append("</tr>");
}
line = line.next;
}
out.append("</tbody>");
}
out.append("\n</table>");
}
}
29 changes: 29 additions & 0 deletions src/main/java/com/github/rjeschke/txtmark/Line.java
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,35 @@ public LineType getLineType(final Configuration configuration)
return LineType.BQUOTE;
}

if(configuration.parseTable)
{
if(this.next != null &&
this.next.value != null && this.next.value.matches("^[| :-]+$")) //Second Line Looks Like:|---|:---:|---|---
{
//double check here
boolean isTable = true;
String[] items = this.next.value.split("\\|");
for (int i = 0; i <items.length; i++) {
String item = items[i].trim();
if("".equals(item)){
if (i == 0 || i == items.length - 1) {
continue;
}
isTable = false;
break;
}
if(!item.matches("^:?-+:?$")){
isTable = false ;
break;
}
}
if(isTable){
return LineType.TABLE;
}
}
}


if (configuration.forceExtendedProfile)
{
if (this.value.length() - this.leading - this.trailing > 2)
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/com/github/rjeschke/txtmark/LineType.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,7 @@ enum LineType
/** Start of a XML block. */
XML,
/** Fenced code block start/end */
FENCED_CODE
FENCED_CODE,
/** Table block */
TABLE
}
16 changes: 16 additions & 0 deletions src/main/java/com/github/rjeschke/txtmark/Processor.java
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,22 @@ private void recurse(final Block root, final boolean listMode)
}
list.expandListParagraphs();
break;
case TABLE:
int baseCols = (line.next.value.trim().split("\\|")).length;
line = line.next.next;//Skip Line(---|---|---|---)
while (line != null)
{
int curCols = line.value.trim().split("\\|").length;
if (line.isEmpty || !(baseCols==curCols))
{
break;
}
line = line.next;
}

block = root.split(line != null ? line.previous : root.lineTail);
block.type = BlockType.TABLE;
break;
default:
line = line.next;
break;
Expand Down
70 changes: 70 additions & 0 deletions src/test/java/com/github/rjeschke/txtmark/MarkTableTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.github.rjeschke.txtmark;

import org.junit.Assert;
import org.junit.Test;

/**
* Created by liuzhenchuan@foxmail.com on 8/5/15.
*/
public class MarkTableTest {

private final String markdownTable =
"| header1 | header2 |\n" +
"| ------------- |:------------:|\n" +
"| col1 | col2 |" ;

private final String markdownTable2 =
" header1 | header2 |\n" +
" ------------- |:------------:|\n" +
" col1 | col2 |" ;

private final String markdownTable3 =
" header1 | header2 |\n" +
" ------------- |:------------:| \n" +
" col1 | col2 |" ;

private final String expectedContent = "<table>\n" +
"<thead><tr><th>header1</th><th>header2</th></tr></thead>\n" +
"<tbody>\n" +
"<tr><td>col1</td><td>col2</td></tr></tbody>\n" +
"</table>";

@Test
public void testConfigure()
{
Configuration.Builder builder = Configuration.builder().setSafeMode(true)
.forceExtentedProfile()
.setAllowSpacesInFencedCodeBlockDelimiters(true)
.setEncoding("UTF-8");

Configuration renderConfig = builder
.build();
String parsedContent = Processor.process(markdownTable, renderConfig);
Assert.assertFalse(parsedContent.contains("<table>"));

renderConfig = builder.enableParseTable()
.build();
parsedContent = Processor.process(markdownTable, renderConfig);
Assert.assertTrue(parsedContent.contains("<table>"));
}

@Test
public void testOutputTable()
{
Configuration renderConfig = Configuration.builder().setSafeMode(true)
.forceExtentedProfile()
.enableParseTable()
.setAllowSpacesInFencedCodeBlockDelimiters(true)
.setEncoding("UTF-8")
.build();
String parsedContent = Processor.process(markdownTable, renderConfig);
Assert.assertEquals(expectedContent,parsedContent);

parsedContent = Processor.process(markdownTable2, renderConfig);
Assert.assertEquals(expectedContent,parsedContent);
//with blank
parsedContent = Processor.process(markdownTable3, renderConfig);
Assert.assertEquals(expectedContent,parsedContent);
}

}