@@ -90,9 +90,12 @@ public String getMarkdownContent(String path) throws IOException {
9090 private String convertHtmlToAscii (String html , String dir ) {
9191 // First pass: Convert headers with dynamic borders
9292 html = convertDynamicHeaders (html );
93-
93+
9494 html = formatNestedLists (html );
9595
96+ // Convert tables before the general regex pass
97+ html = convertTablesToAscii (html );
98+
9699 // Convert HTML elements to ASCII formatting
97100 String text = html
98101 // Headers already converted above
@@ -126,17 +129,7 @@ private String convertHtmlToAscii(String html, String dir) {
126129
127130 // Bold and italic
128131 .replaceAll ("<strong[^>]*>([^<]*)</strong>" , "**$1**" )
129- .replaceAll ("<em[^>]*>([^<]*)</em>" , "*$1*" )
130-
131- // Tables (simplified ASCII representation)
132- .replaceAll ("<table[^>]*>" , "\n ┌" )
133- .replaceAll ("</table>" , "┘\n " )
134- .replaceAll ("<tr[^>]*>" , "" )
135- .replaceAll ("</tr>" , "\n ├" )
136- .replaceAll ("<th[^>]*>" , "─ " )
137- .replaceAll ("</th>" , " ─" )
138- .replaceAll ("<td[^>]*>" , "│ " )
139- .replaceAll ("</td>" , " │" );
132+ .replaceAll ("<em[^>]*>([^<]*)</em>" , "*$1*" );
140133
141134 // Handle images with ASCII art
142135 Pattern imgPattern = Pattern .compile ("<img[^>]*src=\" ([^\" ]*)\" [^>]*>" );
@@ -251,6 +244,90 @@ int nextIndex() {
251244 }
252245 }
253246
247+ private String convertTablesToAscii (String html ) {
248+ Pattern tablePattern = Pattern .compile ("<table[^>]*>(.*?)</table>" , Pattern .DOTALL | Pattern .CASE_INSENSITIVE );
249+ Matcher tableMatcher = tablePattern .matcher (html );
250+ StringBuffer sb = new StringBuffer ();
251+ while (tableMatcher .find ()) {
252+ String asciiTable = renderTableAsAscii (tableMatcher .group (1 ));
253+ tableMatcher .appendReplacement (sb , Matcher .quoteReplacement (asciiTable ));
254+ }
255+ tableMatcher .appendTail (sb );
256+ return sb .toString ();
257+ }
258+
259+ private String renderTableAsAscii (String tableHtml ) {
260+ List <List <String >> rows = new ArrayList <>();
261+
262+ Pattern rowPattern = Pattern .compile ("<tr[^>]*>(.*?)</tr>" , Pattern .DOTALL | Pattern .CASE_INSENSITIVE );
263+ Matcher rowMatcher = rowPattern .matcher (tableHtml );
264+ while (rowMatcher .find ()) {
265+ List <String > cells = new ArrayList <>();
266+ Pattern cellPattern = Pattern .compile ("<t[hd][^>]*>(.*?)</t[hd]>" , Pattern .DOTALL | Pattern .CASE_INSENSITIVE );
267+ Matcher cellMatcher = cellPattern .matcher (rowMatcher .group (1 ));
268+ while (cellMatcher .find ()) {
269+ String cell = cellMatcher .group (1 )
270+ .replaceAll ("<[^>]+>" , "" )
271+ .replaceAll ("&" , "&" ).replaceAll ("<" , "<" )
272+ .replaceAll (">" , ">" ).replaceAll (""" , "\" " )
273+ .replaceAll ("'" , "'" ).replaceAll (" " , " " )
274+ .trim ();
275+ cells .add (cell );
276+ }
277+ if (!cells .isEmpty ()) rows .add (cells );
278+ }
279+
280+ if (rows .isEmpty ()) return "" ;
281+
282+ int numCols = rows .stream ().mapToInt (List ::size ).max ().orElse (0 );
283+ int [] colWidths = new int [numCols ];
284+ for (List <String > row : rows ) {
285+ for (int i = 0 ; i < row .size (); i ++) {
286+ colWidths [i ] = Math .max (colWidths [i ], row .get (i ).length ());
287+ }
288+ }
289+
290+ StringBuilder ascii = new StringBuilder ("\n " );
291+
292+ // Top border
293+ ascii .append ("┌" );
294+ for (int i = 0 ; i < numCols ; i ++) {
295+ ascii .append ("─" .repeat (colWidths [i ] + 2 ));
296+ ascii .append (i < numCols - 1 ? "┬" : "┐" );
297+ }
298+ ascii .append ("\n " );
299+
300+ for (int r = 0 ; r < rows .size (); r ++) {
301+ List <String > row = rows .get (r );
302+ ascii .append ("│" );
303+ for (int i = 0 ; i < numCols ; i ++) {
304+ String cell = i < row .size () ? row .get (i ) : "" ;
305+ ascii .append (" " ).append (cell ).append (" " .repeat (colWidths [i ] - cell .length () + 1 )).append ("│" );
306+ }
307+ ascii .append ("\n " );
308+
309+ if (r == 0 && rows .size () > 1 ) {
310+ // Header separator
311+ ascii .append ("├" );
312+ for (int i = 0 ; i < numCols ; i ++) {
313+ ascii .append ("─" .repeat (colWidths [i ] + 2 ));
314+ ascii .append (i < numCols - 1 ? "┼" : "┤" );
315+ }
316+ ascii .append ("\n " );
317+ } else if (r == rows .size () - 1 ) {
318+ // Bottom border
319+ ascii .append ("└" );
320+ for (int i = 0 ; i < numCols ; i ++) {
321+ ascii .append ("─" .repeat (colWidths [i ] + 2 ));
322+ ascii .append (i < numCols - 1 ? "┴" : "┘" );
323+ }
324+ ascii .append ("\n " );
325+ }
326+ }
327+
328+ return ascii .toString ();
329+ }
330+
254331 private String convertDynamicHeaders (String html ) {
255332 // Convert H1 headers with dynamic borders
256333 Pattern h1Pattern = Pattern .compile ("<h1[^>]*>(.*?)</h1>" , Pattern .DOTALL );
0 commit comments