Skip to content

Commit fe8e2f6

Browse files
committed
add html converter div table conversion
1 parent e740b61 commit fe8e2f6

File tree

6 files changed

+155
-0
lines changed

6 files changed

+155
-0
lines changed

VERSION-TODO.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- [Release 0.60.0](#release-0600)
88
- [API Refactoring](#api-refactoring)
99
- [Next 0.60.xx](#next-060xx)
10+
- [Next 0.59.126](#next-059126)
1011
- [0.59.124](#059124)
1112
- [0.59.122](#059122)
1213
- [0.59.120](#059120)
@@ -211,6 +212,11 @@ Please give feedback on the upcoming changes if you have concerns about breaking
211212
`|` for each line that was wrapped. Otherwise, it is impossible to tell where each line
212213
ends and another begins.
213214

215+
## Next 0.59.126
216+
217+
* Add: `FlexmarkHtmlConverter` `div` to table options to allow converting `div` based table code
218+
to markdown tables.
219+
214220
## 0.59.124
215221

216222
* Add: `migrate flexmark-java 0_50_x to 0_60_0.xml` IntelliJ Migration

flexmark-html2md-converter/src/main/java/com/vladsch/flexmark/html2md/converter/FlexmarkHtmlConverter.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,16 @@ public class FlexmarkHtmlConverter {
110110
final public static DataKey<Boolean> DIV_AS_PARAGRAPH = new DataKey<>("DIV_AS_PARAGRAPH", false);
111111
final public static DataKey<Boolean> BR_AS_PARA_BREAKS = new DataKey<>("BR_AS_PARA_BREAKS", true);
112112
final public static DataKey<Boolean> BR_AS_EXTRA_BLANK_LINES = new DataKey<>("BR_AS_EXTRA_BLANK_LINES", true);
113+
final public static DataKey<Boolean> DIV_TABLE_PROCESSING = new DataKey<>("DIV_TABLE_PROCESSING", false);
114+
final public static DataKey<String[]> DIV_TABLE_HDR_CLASSES = new DataKey<>("DIV_TABLE_HDR_CLASSES", new String[] {
115+
"wt-data-grid__row_header",
116+
});
117+
final public static DataKey<String[]> DIV_TABLE_ROW_CLASSES = new DataKey<>("DIV_TABLE_ROW_CLASSES", new String[] {
118+
"wt-data-grid__row",
119+
});
120+
final public static DataKey<String[]> DIV_TABLE_CELL_CLASSES = new DataKey<>("DIV_TABLE_CELL_CLASSES", new String[] {
121+
"wt-data-grid__cell",
122+
});
113123

114124
final public static DataKey<Boolean> ADD_TRAILING_EOL = new DataKey<>("ADD_TRAILING_EOL", true);
115125

flexmark-html2md-converter/src/main/java/com/vladsch/flexmark/html2md/converter/HtmlConverterOptions.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public class HtmlConverterOptions implements MutableDataSetter {
4040
public boolean skipAttributes;
4141
public boolean skipFencedCode;
4242
public boolean skipCharEscape;
43+
public boolean divTableProcessing;
4344
public ExtensionConversion extInlineStrong;
4445
public ExtensionConversion extInlineEmphasis;
4546
public ExtensionConversion extInlineCode;
@@ -69,6 +70,9 @@ public class HtmlConverterOptions implements MutableDataSetter {
6970
public int maxTrailingBlankLines;
7071
public String[] unwrappedTags;
7172
public String[] wrappedTags;
73+
public String[] divTableRowClasses;
74+
public String[] divTableCellClasses;
75+
public String[] divTableHdrClasses;
7276

7377
public HtmlConverterOptions() {
7478
this((DataHolder) null);
@@ -102,6 +106,7 @@ public HtmlConverterOptions(HtmlConverterOptions other) {
102106
skipAttributes = other.skipAttributes;
103107
skipFencedCode = other.skipFencedCode;
104108
skipCharEscape = other.skipCharEscape;
109+
divTableProcessing = other.divTableProcessing;
105110
extInlineStrong = other.extInlineStrong;
106111
extInlineEmphasis = other.extInlineEmphasis;
107112
extInlineCode = other.extInlineCode;
@@ -131,6 +136,9 @@ public HtmlConverterOptions(HtmlConverterOptions other) {
131136
maxTrailingBlankLines = other.maxTrailingBlankLines;
132137
unwrappedTags = other.unwrappedTags;
133138
wrappedTags = other.wrappedTags;
139+
divTableRowClasses = other.divTableRowClasses;
140+
divTableCellClasses = other.divTableCellClasses;
141+
divTableHdrClasses = other.divTableHdrClasses;
134142
}
135143

136144
public HtmlConverterOptions(DataHolder options) {
@@ -161,6 +169,7 @@ public HtmlConverterOptions(DataHolder options) {
161169
skipAttributes = FlexmarkHtmlConverter.SKIP_ATTRIBUTES.get(options);
162170
skipFencedCode = FlexmarkHtmlConverter.SKIP_FENCED_CODE.get(options);
163171
skipCharEscape = FlexmarkHtmlConverter.SKIP_CHAR_ESCAPE.get(options);
172+
divTableProcessing = FlexmarkHtmlConverter.DIV_TABLE_PROCESSING.get(options);
164173
extInlineStrong = FlexmarkHtmlConverter.EXT_INLINE_STRONG.get(options);
165174
extInlineEmphasis = FlexmarkHtmlConverter.EXT_INLINE_EMPHASIS.get(options);
166175
extInlineCode = FlexmarkHtmlConverter.EXT_INLINE_CODE.get(options);
@@ -190,6 +199,9 @@ public HtmlConverterOptions(DataHolder options) {
190199
maxTrailingBlankLines = FlexmarkHtmlConverter.MAX_TRAILING_BLANK_LINES.get(options);
191200
unwrappedTags = FlexmarkHtmlConverter.UNWRAPPED_TAGS.get(options);
192201
wrappedTags = FlexmarkHtmlConverter.WRAPPED_TAGS.get(options);
202+
divTableRowClasses = FlexmarkHtmlConverter.DIV_TABLE_ROW_CLASSES.get(options);
203+
divTableCellClasses = FlexmarkHtmlConverter.DIV_TABLE_CELL_CLASSES.get(options);
204+
divTableHdrClasses = FlexmarkHtmlConverter.DIV_TABLE_HDR_CLASSES.get(options);
193205
}
194206

195207
@NotNull
@@ -222,6 +234,7 @@ public MutableDataHolder setIn(@NotNull MutableDataHolder dataHolder) {
222234
dataHolder.set(FlexmarkHtmlConverter.SKIP_ATTRIBUTES, skipAttributes);
223235
dataHolder.set(FlexmarkHtmlConverter.SKIP_FENCED_CODE, skipFencedCode);
224236
dataHolder.set(FlexmarkHtmlConverter.SKIP_CHAR_ESCAPE, skipCharEscape);
237+
dataHolder.set(FlexmarkHtmlConverter.DIV_TABLE_PROCESSING, divTableProcessing);
225238
dataHolder.set(FlexmarkHtmlConverter.EXT_INLINE_STRONG, extInlineStrong);
226239
dataHolder.set(FlexmarkHtmlConverter.EXT_INLINE_EMPHASIS, extInlineEmphasis);
227240
dataHolder.set(FlexmarkHtmlConverter.EXT_INLINE_CODE, extInlineCode);
@@ -249,6 +262,9 @@ public MutableDataHolder setIn(@NotNull MutableDataHolder dataHolder) {
249262
dataHolder.set(FlexmarkHtmlConverter.MAX_TRAILING_BLANK_LINES, maxTrailingBlankLines);
250263
dataHolder.set(FlexmarkHtmlConverter.UNWRAPPED_TAGS, unwrappedTags);
251264
dataHolder.set(FlexmarkHtmlConverter.WRAPPED_TAGS, wrappedTags);
265+
dataHolder.set(FlexmarkHtmlConverter.DIV_TABLE_ROW_CLASSES, divTableRowClasses);
266+
dataHolder.set(FlexmarkHtmlConverter.DIV_TABLE_CELL_CLASSES, divTableCellClasses);
267+
dataHolder.set(FlexmarkHtmlConverter.DIV_TABLE_HDR_CLASSES, divTableHdrClasses);
252268
return dataHolder;
253269
}
254270
}

flexmark-html2md-converter/src/main/java/com/vladsch/flexmark/html2md/converter/internal/HtmlConverterCoreNodeRenderer.java

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.vladsch.flexmark.util.sequence.BasedSequence;
1919
import com.vladsch.flexmark.util.sequence.LineAppendable;
2020
import com.vladsch.flexmark.util.sequence.RepeatedSequence;
21+
import org.jetbrains.annotations.NotNull;
2122
import org.jsoup.nodes.*;
2223
import org.jsoup.select.Elements;
2324

@@ -416,8 +417,86 @@ private void processDel(Element element, HtmlNodeConverterContext context, HtmlM
416417
});
417418
}
418419

420+
private void handleDivTable(Element element, HtmlNodeConverterContext context, HtmlMarkdownWriter out) {
421+
MarkdownTable oldTable = myTable;
422+
423+
myTable = new MarkdownTable("", myHtmlConverterOptions.tableOptions);
424+
myTableSuppressColumns = false;
425+
426+
Node node = element;
427+
do {
428+
if (!node.nodeName().toLowerCase().equals(FlexmarkHtmlConverter.DIV_NODE)) {
429+
if (node instanceof Element) break;
430+
continue;
431+
}
432+
433+
Set<String> classNames = ((Element) node).classNames();
434+
if (!classNames.contains("wt-data-grid__row")) break;
435+
436+
handleDivTableRow((Element) node, context, out);
437+
} while ((node = context.next()) != null);
438+
439+
myTable.finalizeTable();
440+
int sepColumns = myTable.getMaxColumns();
441+
442+
if (sepColumns > 0) {
443+
out.blankLine();
444+
myTable.appendTable(out);
445+
out.tailBlankLine();
446+
}
447+
448+
myTable = oldTable;
449+
}
450+
451+
private void handleDivTableRow(Element element, HtmlNodeConverterContext context, HtmlMarkdownWriter out) {
452+
context.pushState(element);
453+
454+
myTable.setHeader(hasIntersection(element.classNames(), myHtmlConverterOptions.divTableHdrClasses));
455+
456+
Node node;
457+
while ((node = context.next()) != null) {
458+
if (!node.nodeName().toLowerCase().equals(FlexmarkHtmlConverter.DIV_NODE)) {
459+
if (node instanceof Element) break;
460+
continue;
461+
}
462+
if (!hasIntersection(((Element) node).classNames(), myHtmlConverterOptions.divTableCellClasses)) break;
463+
464+
handleDivTableCell((Element) node, context, out);
465+
}
466+
467+
myTable.nextRow();
468+
context.popState(out);
469+
}
470+
471+
private void handleDivTableCell(Element element, HtmlNodeConverterContext context, HtmlMarkdownWriter out) {
472+
String cellText = context.processTextNodes(element).trim().replaceAll("\\s*\n\\s*", " ");
473+
int colSpan = 1;
474+
int rowSpan = 1;
475+
CellAlignment alignment = CellAlignment.NONE;
476+
477+
// skip cells defined by row spans in previous rows
478+
if (!myTableSuppressColumns) {
479+
myTable.addCell(new TableCell(null, BasedSequence.NULL, cellText.replace("\n", " "), BasedSequence.NULL, rowSpan, colSpan, alignment));
480+
}
481+
}
482+
483+
private boolean hasIntersection(@NotNull Set<String> stringSet1, String[] stringSet2) {
484+
for (String item : stringSet2) {
485+
if (stringSet1.contains(item)) return true;
486+
}
487+
return false;
488+
}
489+
419490
private void processDiv(Element element, HtmlNodeConverterContext context, HtmlMarkdownWriter out) {
420491
// unwrap and process content
492+
if (myHtmlConverterOptions.divTableProcessing) {
493+
// NOTE: handle class names for header, row and cell
494+
if (hasIntersection(element.classNames(), myHtmlConverterOptions.divTableRowClasses)) {
495+
handleDivTable(element, context, out);
496+
return;
497+
}
498+
}
499+
421500
if (!isFirstChild(element)) {
422501
if (!myHtmlConverterOptions.divAsParagraph) {
423502
int pendingEOL = out.getPendingEOL();

flexmark-html2md-converter/src/test/java/com/vladsch/flexmark/html2md/converter/HtmlConverterTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public abstract class HtmlConverterTest extends ComboSpecTestCase {
6060
optionsMap.put("html-ext-inline-ins", new MutableDataSet().set(FlexmarkHtmlConverter.EXT_INLINE_INS, ExtensionConversion.HTML));
6161
optionsMap.put("html-ext-inline-sub", new MutableDataSet().set(FlexmarkHtmlConverter.EXT_INLINE_SUB, ExtensionConversion.HTML));
6262
optionsMap.put("html-ext-inline-sup", new MutableDataSet().set(FlexmarkHtmlConverter.EXT_INLINE_SUP, ExtensionConversion.HTML));
63+
optionsMap.put("div-tables", new MutableDataSet().set(FlexmarkHtmlConverter.DIV_TABLE_PROCESSING, true));
6364
optionsMap.put("no-github-id", new MutableDataSet().set(FlexmarkHtmlConverter.OUTPUT_ID_ATTRIBUTE_REGEX, ""));
6465

6566
optionsMap.put("links-none", new MutableDataSet().set(FlexmarkHtmlConverter.EXT_INLINE_LINK, LinkConversion.NONE));

0 commit comments

Comments
 (0)