Compare commits
4 commits
c67cccc31f
...
f487d02f1c
| Author | SHA1 | Date | |
|---|---|---|---|
| f487d02f1c | |||
| bec3dca171 | |||
| dcbf8db706 | |||
| 4d6169ff59 |
4 changed files with 594 additions and 206 deletions
|
|
@ -1352,7 +1352,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
||||||
$text .= "<tr>\n";
|
$text .= "<tr>\n";
|
||||||
foreach ($headers as $n => $header)
|
foreach ($headers as $n => $header)
|
||||||
{
|
{
|
||||||
if (preg_match('/\[([a-zA-Z]+)\]/', $header, $matches))
|
if (preg_match('/\[@([a-zA-Z]+)\]/', $header, $matches))
|
||||||
{
|
{
|
||||||
$label = $matches[1];
|
$label = $matches[1];
|
||||||
|
|
||||||
|
|
@ -1830,17 +1830,17 @@ class MarkdownExtra extends \Michelf\Markdown {
|
||||||
$less_than_tab = $this->tab_width - 1;
|
$less_than_tab = $this->tab_width - 1;
|
||||||
|
|
||||||
$text = preg_replace_callback('{
|
$text = preg_replace_callback('{
|
||||||
^[ ]{0,' . $less_than_tab . '}\[(.+?)\][ ]?: [ ]* \n
|
^[ ]{0,' . $less_than_tab . '}\[@(.+?)\][ ]?: [ ]* \n
|
||||||
|
|
||||||
(
|
(
|
||||||
(?>
|
(?>
|
||||||
(?!^\[\1\])
|
(?!^\[@\1\])
|
||||||
.*\n+
|
.*\n+
|
||||||
)+
|
)+
|
||||||
)
|
)
|
||||||
|
|
||||||
# Closing marker.
|
# Closing marker.
|
||||||
\[\1\][ ]* (?= \n )
|
\[@\1\][ ]* (?= \n )
|
||||||
}xm',
|
}xm',
|
||||||
array($this, '_stripTomCells_block_callback'),
|
array($this, '_stripTomCells_block_callback'),
|
||||||
$text);
|
$text);
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
gedit
|
gedit
|
||||||
python3
|
python3
|
||||||
meld
|
meld
|
||||||
|
zip
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
||||||
67
test.md
67
test.md
|
|
@ -6,15 +6,24 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor, nunc non fr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
line 9 | 2
|
||||||
|
- | -
|
||||||
|
3 | 4
|
||||||
|
|
||||||
|
|
||||||
|
xyz
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table q=w>
|
|
||||||
|
|
||||||
|
|
||||||
|
<table q=w markdown="1">
|
||||||
| a | b | <p> c </p> <p> d </p> |
|
| a | b | <p> c </p> <p> d </p> |
|
||||||
| - | :-: | - |
|
| - | :-: | - |
|
||||||
<caption> 1 2 3 | 4 5 6
|
<caption> 1 2 3 | 4 5 6
|
||||||
<caption> q w e r t y <tr a="b"> | d | e | f |
|
<caption> q w e r t y <tr a="b"> | d | e | f |
|
||||||
| g <th a="b" align="left"> h </th> i |
|
| g <th a="b" style="text-align: left"> h </th> i |
|
||||||
<tr> x | y | z </tr>
|
<tr> x | y | z </tr>
|
||||||
x | y | z </tr> </tbody>
|
x | y | z </tr> </tbody>
|
||||||
[ def ]
|
[ def ]
|
||||||
|
|
@ -30,7 +39,53 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor, nunc non fr
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<caption> <ol> <li> 1 <li> 2 <li> 3 </ol> | foo
|
|
||||||
|
<table markdown=1>
|
||||||
|
tiptoe | 2
|
||||||
|
|
||||||
|
3 | 4
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<table markdown=1>
|
||||||
|
tiptoe | 2
|
||||||
|
3 | 4
|
||||||
|
5 | 6
|
||||||
|
[duh]
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<table markdown=1>
|
||||||
|
<tfoot>
|
||||||
|
1 | 2
|
||||||
|
<tbody>
|
||||||
|
3 | 4
|
||||||
|
<thead>
|
||||||
|
5 | 6
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<table markdown=1>
|
||||||
|
1 | 2
|
||||||
|
|
||||||
|
3 | 4
|
||||||
|
|
||||||
|
5 | 6
|
||||||
|
[duh]
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<caption> <ol> <li> 1 <li> 2 <li> 3 </ol> | foo88
|
||||||
<caption>foo<thead> bar | baz
|
<caption>foo<thead> bar | baz
|
||||||
| -
|
| -
|
||||||
| bar
|
| bar
|
||||||
|
|
@ -58,15 +113,15 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor, nunc non fr
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor, nunc non fringilla pulvinar, augue arcu tempor lacus, vel gravida justo sapien vel nibh. Curabitur eget dignissim lorem. Vivamus sit amet urna nec lorem aliquet viverra. Aliquam erat volutpat. Maecenas sed ante vitae erat feugiat faucibus. Integer porttitor nibh eu risus suscipit, ut efficitur mauris sollicitudin. Suspendisse potenti. Integer feugiat mi sed ligula sagittis, id sagittis justo ullamcorper.
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor, nunc non fringilla pulvinar, augue arcu tempor lacus, vel gravida justo sapien vel nibh. Curabitur eget dignissim lorem. Vivamus sit amet urna nec lorem aliquet viverra. Aliquam erat volutpat. Maecenas sed ante vitae erat feugiat faucibus. Integer porttitor nibh eu risus suscipit, ut efficitur mauris sollicitudin. Suspendisse potenti. Integer feugiat mi sed ligula sagittis, id sagittis justo ullamcorper.
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table markdown="1">
|
||||||
|a
|
|a117
|
||||||
|-
|
|-
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table markdown="1">
|
||||||
|-
|
|-
|
||||||
|b
|
|b
|
||||||
</table>
|
</table>
|
||||||
|
|
|
||||||
512
test.py
512
test.py
|
|
@ -67,6 +67,7 @@ def do_table_line(state, line):
|
||||||
I'm supposed to return the whole HTML.
|
I'm supposed to return the whole HTML.
|
||||||
Including the <tr> if needed.
|
Including the <tr> if needed.
|
||||||
"""
|
"""
|
||||||
|
print("do_table_line");
|
||||||
|
|
||||||
print(f'line = "{line}"');
|
print(f'line = "{line}"');
|
||||||
|
|
||||||
|
|
@ -74,7 +75,7 @@ def do_table_line(state, line):
|
||||||
|
|
||||||
passthrough_pattern = fr"(?:<{tags}(?:[\s]+[^>]*)?>|</{tags}>)";
|
passthrough_pattern = fr"(?:<{tags}(?:[\s]+[^>]*)?>|</{tags}>)";
|
||||||
|
|
||||||
start_tag_pattern = fr"<{state.section_tag}(?:[\s]+[^>]*)?>"
|
start_tag_pattern = fr"<(thead|tbody|tfoot)(?:[\s]+[^>]*)?>"
|
||||||
|
|
||||||
open_tr_pattern = r"<tr(?:[\s]+[^<>]*)?>[\s]*";
|
open_tr_pattern = r"<tr(?:[\s]+[^<>]*)?>[\s]*";
|
||||||
|
|
||||||
|
|
@ -84,7 +85,7 @@ def do_table_line(state, line):
|
||||||
|
|
||||||
caption_sentinel_pattern = "(?:" + \
|
caption_sentinel_pattern = "(?:" + \
|
||||||
'|'.join((cell_delimiter, passthrough_pattern, start_tag_pattern,
|
'|'.join((cell_delimiter, passthrough_pattern, start_tag_pattern,
|
||||||
open_tr_pattern, open_caption_pattern)) + ")"
|
open_tr_pattern, open_caption_pattern, r'</?table.*')) + ")"
|
||||||
|
|
||||||
already_open_tr = 0;
|
already_open_tr = 0;
|
||||||
|
|
||||||
|
|
@ -94,15 +95,21 @@ def do_table_line(state, line):
|
||||||
# Is it whatever our start tag is?
|
# Is it whatever our start tag is?
|
||||||
if (m := re.match(start_tag_pattern, line)):
|
if (m := re.match(start_tag_pattern, line)):
|
||||||
# we'll pass this through, and remember that we don't need to do
|
# we'll pass this through, and remember that we don't need to do
|
||||||
# it ourselves
|
# it ourselves also possibly close previous section also change
|
||||||
print("found our start tag");
|
# "section_tag" to be thead
|
||||||
|
print(f"found our start tag: '{m.group(0)}'");
|
||||||
|
|
||||||
out += m.group(0);
|
# if we're already open, close whatever that was
|
||||||
|
if state.already_opened_section:
|
||||||
|
out += f'</{state.section_tag}>' + "\n";
|
||||||
|
|
||||||
|
out += m.group(0) + "\n";
|
||||||
|
|
||||||
line = line[len(m.group(0)):];
|
line = line[len(m.group(0)):];
|
||||||
|
|
||||||
print(f'line = "{line}"');
|
print(f'line = "{line}"');
|
||||||
|
|
||||||
|
state.section_tag = m.group(1);
|
||||||
state.already_opened_section = 1;
|
state.already_opened_section = 1;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -119,7 +126,7 @@ def do_table_line(state, line):
|
||||||
out += f"<{state.section_tag}>";
|
out += f"<{state.section_tag}>";
|
||||||
state.already_opened_section = 1;
|
state.already_opened_section = 1;
|
||||||
|
|
||||||
out += m.group(0);
|
out += m.group(0) + "\n";
|
||||||
|
|
||||||
line = line[len(m.group(0)):];
|
line = line[len(m.group(0)):];
|
||||||
|
|
||||||
|
|
@ -160,7 +167,7 @@ def do_table_line(state, line):
|
||||||
|
|
||||||
print(f'line = "{line}"');
|
print(f'line = "{line}"');
|
||||||
|
|
||||||
out += "</caption>";
|
out += "</caption>" + "\n";
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -168,7 +175,7 @@ def do_table_line(state, line):
|
||||||
if (m := re.match(passthrough_pattern, line)):
|
if (m := re.match(passthrough_pattern, line)):
|
||||||
print(f'found passthrough tag: "{m.group(0)}"');
|
print(f'found passthrough tag: "{m.group(0)}"');
|
||||||
|
|
||||||
out += m.group(0);
|
out += m.group(0) + "\n";
|
||||||
|
|
||||||
line = line[len(m.group(0)):];
|
line = line[len(m.group(0)):];
|
||||||
|
|
||||||
|
|
@ -187,11 +194,11 @@ def do_table_line(state, line):
|
||||||
column_index = 0;
|
column_index = 0;
|
||||||
|
|
||||||
if not state.already_opened_section:
|
if not state.already_opened_section:
|
||||||
out += f"<{state.section_tag}>";
|
out += f"<{state.section_tag}>" + "\n";
|
||||||
state.already_opened_section = 1;
|
state.already_opened_section = 1;
|
||||||
|
|
||||||
if not already_open_tr:
|
if not already_open_tr:
|
||||||
out += "<tr>";
|
out += "<tr>" + "\n";
|
||||||
|
|
||||||
while line:
|
while line:
|
||||||
print("new cell");
|
print("new cell");
|
||||||
|
|
@ -206,7 +213,7 @@ def do_table_line(state, line):
|
||||||
align = state.column_info[column_index]['align'];
|
align = state.column_info[column_index]['align'];
|
||||||
|
|
||||||
if align != 'default':
|
if align != 'default':
|
||||||
attributes['align'] = align;
|
attributes['style'] = f'text-align: {align}';
|
||||||
|
|
||||||
print(f'attributes = "{attributes}"');
|
print(f'attributes = "{attributes}"');
|
||||||
|
|
||||||
|
|
@ -225,7 +232,7 @@ def do_table_line(state, line):
|
||||||
line = line[1:];
|
line = line[1:];
|
||||||
|
|
||||||
print(f'line = "{line}"');
|
print(f'line = "{line}"');
|
||||||
elif (m := re.match(r"<([a-z]+)(?:[\s]+([^<>]*))?>", line)):
|
elif (m := re.match(r"<(th|td)(?:[\s]+([^<>]*))?>", line)):
|
||||||
print("found opening HTML tag");
|
print("found opening HTML tag");
|
||||||
|
|
||||||
tag = m.group(1);
|
tag = m.group(1);
|
||||||
|
|
@ -262,7 +269,7 @@ def do_table_line(state, line):
|
||||||
line = line[len(m.group(0)):];
|
line = line[len(m.group(0)):];
|
||||||
|
|
||||||
print(f'line = "{line}"');
|
print(f'line = "{line}"');
|
||||||
elif (m := re.match(r"<([a-z]+)", line)):
|
elif (m := re.match(r"<(th|td)", line)):
|
||||||
print("found HTML open, but it's incomplete? huh?! throwing!");
|
print("found HTML open, but it's incomplete? huh?! throwing!");
|
||||||
|
|
||||||
raise SyntaxError("could not find '>' for HTML open tag");
|
raise SyntaxError("could not find '>' for HTML open tag");
|
||||||
|
|
@ -272,6 +279,8 @@ def do_table_line(state, line):
|
||||||
tag = state.column_info[column_index]['default-tag']
|
tag = state.column_info[column_index]['default-tag']
|
||||||
|
|
||||||
print(f'tag = "{tag}"');
|
print(f'tag = "{tag}"');
|
||||||
|
|
||||||
|
print(f'line = "{line}"');
|
||||||
else:
|
else:
|
||||||
print(f"found nothing, defaulting default_tag ({state.default_cell_tag})");
|
print(f"found nothing, defaulting default_tag ({state.default_cell_tag})");
|
||||||
|
|
||||||
|
|
@ -279,6 +288,8 @@ def do_table_line(state, line):
|
||||||
|
|
||||||
print(f'tag = "{tag}"');
|
print(f'tag = "{tag}"');
|
||||||
|
|
||||||
|
print(f'line = "{line}"');
|
||||||
|
|
||||||
print("looking for closer");
|
print("looking for closer");
|
||||||
|
|
||||||
content = "";
|
content = "";
|
||||||
|
|
@ -318,15 +329,10 @@ def do_table_line(state, line):
|
||||||
print(f'depth = {depth}');
|
print(f'depth = {depth}');
|
||||||
elif (m := re.match("</table>", line)):
|
elif (m := re.match("</table>", line)):
|
||||||
content += m.group(0);
|
content += m.group(0);
|
||||||
depth -= 1;
|
if depth > 0: depth -= 1;
|
||||||
if depth < 0: raise SyntaxError("negative depth; bad HTML");
|
|
||||||
line = line[len(m.group(0)):]
|
line = line[len(m.group(0)):]
|
||||||
print(f'line = "{line}"');
|
print(f'line = "{line}"');
|
||||||
print(f'depth = {depth}');
|
print(f'depth = {depth}');
|
||||||
# elif (m := re.match(fr"</{tags}>", line)):
|
|
||||||
# # ignore the closers for table parts, no passthrough
|
|
||||||
# line = line[len(m.group(0)):]
|
|
||||||
# print(f'line = "{line}"');
|
|
||||||
elif (m := re.match("<[a-z]+(?:\\s+[^<>]*)?>", line)):
|
elif (m := re.match("<[a-z]+(?:\\s+[^<>]*)?>", line)):
|
||||||
content += m.group(0);
|
content += m.group(0);
|
||||||
line = line[len(m.group(0)):]
|
line = line[len(m.group(0)):]
|
||||||
|
|
@ -358,82 +364,358 @@ def do_table_line(state, line):
|
||||||
|
|
||||||
column_index += 1;
|
column_index += 1;
|
||||||
|
|
||||||
|
# end the row of content
|
||||||
|
out += "\n";
|
||||||
|
|
||||||
|
# close tr on its own line
|
||||||
|
out += "</tr>" + "\n";
|
||||||
|
|
||||||
print(f'out = "{out}"');
|
print(f'out = "{out}"');
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
def do_table(table_open_tag, header_lines, seperator_line, body_lines, optional_caption):
|
# def do_table(table_open_tag, header_lines, seperator_line, body_lines, optional_caption):
|
||||||
|
#
|
||||||
out = "";
|
# # handle explicit table tag?
|
||||||
|
# if table_open_tag:
|
||||||
# handle explicit table tag?
|
# open_tag = table_open_tag + "\n";
|
||||||
if table_open_tag:
|
# else:
|
||||||
out += table_open_tag + "\n";
|
# # otherwise, add a default one:
|
||||||
else:
|
# open_tag = "<table>" + "\n";
|
||||||
# otherwise, add a default one:
|
#
|
||||||
out += "<table>" + "\n";
|
# inner = "";
|
||||||
|
#
|
||||||
state = State(section_tag = "thead", default_cell_tag = "th");
|
# state = State(section_tag = "thead", default_cell_tag = "th");
|
||||||
|
#
|
||||||
# Process the header lines:
|
# # Process the header lines:
|
||||||
for line in header_lines:
|
# for line in header_lines:
|
||||||
html_table_line = do_table_line(state, line);
|
# inner = do_table_line(state, line);
|
||||||
|
#
|
||||||
out += html_table_line + "\n";
|
# if state.already_opened_section:
|
||||||
|
# inner += f"</{state.section_tag}>" "\n";
|
||||||
# Handle line seperator:
|
#
|
||||||
column_info = parse_colinfo(seperator_line);
|
# # Handle line seperator:
|
||||||
|
# column_info = parse_colinfo(seperator_line);
|
||||||
# Process the body lines:
|
#
|
||||||
for lines in body_lines:
|
# # Process the body lines:
|
||||||
state = State(section_tag = "tbody", \
|
# for lines in body_lines:
|
||||||
default_cell_tag = "td", \
|
# state = State(section_tag = "tbody", \
|
||||||
column_info = column_info);
|
# default_cell_tag = "td", \
|
||||||
|
# column_info = column_info);
|
||||||
for line in lines:
|
#
|
||||||
html_table_line = do_table_line(state, line);
|
# for line in lines:
|
||||||
|
# inner += do_table_line(state, line);
|
||||||
out += html_table_line + "\n";
|
#
|
||||||
|
# if state.already_opened_section:
|
||||||
# Consider the optional caption
|
# inner += f"</{state.section_tag}>" "\n";
|
||||||
if optional_caption:
|
#
|
||||||
out += f"<caption> {optional_caption} </caption>\n";
|
# # Consider the optional caption.
|
||||||
|
# # If it happens, it goes before everything else
|
||||||
out += "</table>\n";
|
# if optional_caption:
|
||||||
|
# inner = f"<caption> {optional_caption} </caption>\n" + inner;
|
||||||
for o in out.split("\n"):
|
#
|
||||||
print(o);
|
# close_tag = "</table>\n";
|
||||||
|
#
|
||||||
return "\n\n" + out + "\n\n";
|
# for o in inner.split("\n"):
|
||||||
|
# print(o);
|
||||||
|
#
|
||||||
|
# return "\n\n" + open_tag + inner + close_tag + "\n\n";
|
||||||
|
|
||||||
def handle_table(m):
|
def handle_table(m):
|
||||||
print("handle_table");
|
print("handle_table");
|
||||||
|
|
||||||
|
assert(not "TODO");
|
||||||
|
# matched = m.group(0);
|
||||||
|
|
||||||
|
# optional_table_open = m.group(1);
|
||||||
|
|
||||||
|
# one_or_more_header_lines = m.group(2);
|
||||||
|
|
||||||
|
# header_lines = one_or_more_header_lines.strip().split("\n")
|
||||||
|
|
||||||
|
# seperator_line = m.group(3);
|
||||||
|
|
||||||
|
# one_or_more_body_lines = m.group(4);
|
||||||
|
|
||||||
|
# body_lines = [e.strip().split("\n") for e in one_or_more_body_lines.strip().split("\n\n")]
|
||||||
|
|
||||||
|
# optional_caption = m.group(5);
|
||||||
|
|
||||||
|
# assert(seperator_line is not None)
|
||||||
|
|
||||||
|
# try:
|
||||||
|
# # handle explicit table tag?
|
||||||
|
# if optional_table_open:
|
||||||
|
# open_tag = optional_table_open + "\n";
|
||||||
|
# else:
|
||||||
|
# # otherwise, add a default one:
|
||||||
|
# open_tag = "<table>" + "\n";
|
||||||
|
|
||||||
|
# inner = "";
|
||||||
|
|
||||||
|
# state = State(section_tag = "thead", default_cell_tag = "th");
|
||||||
|
|
||||||
|
# # Process the header lines:
|
||||||
|
# for line in header_lines:
|
||||||
|
# inner = do_table_line(state, line);
|
||||||
|
|
||||||
|
# if state.already_opened_section:
|
||||||
|
# inner += f"</{state.section_tag}>" "\n";
|
||||||
|
|
||||||
|
# # Handle line seperator:
|
||||||
|
# column_info = parse_colinfo(seperator_line);
|
||||||
|
|
||||||
|
# # Process the body lines:
|
||||||
|
# for lines in body_lines:
|
||||||
|
# state = State(section_tag = "tbody", \
|
||||||
|
# default_cell_tag = "td", \
|
||||||
|
# column_info = column_info);
|
||||||
|
|
||||||
|
# for line in lines:
|
||||||
|
# inner += do_table_line(state, line);
|
||||||
|
|
||||||
|
# if state.already_opened_section:
|
||||||
|
# inner += f"</{state.section_tag}>" "\n";
|
||||||
|
|
||||||
|
# # Consider the optional caption.
|
||||||
|
# # If it happens, it goes before everything else
|
||||||
|
# if optional_caption:
|
||||||
|
# inner = f"<caption> {optional_caption} </caption>\n" + inner;
|
||||||
|
|
||||||
|
# close_tag = "</table>\n";
|
||||||
|
|
||||||
|
# return "\n\n" + open_tag + inner + close_tag + "\n\n";
|
||||||
|
# except SyntaxError as e:
|
||||||
|
# print(f"caught syntax error: {e}");
|
||||||
|
# print("moving on to next table...");
|
||||||
|
# return m.group(0);
|
||||||
|
|
||||||
|
def handle_table_no_sep(m):
|
||||||
|
print("handle_table_no_sep");
|
||||||
|
|
||||||
|
assert(not "TODO");
|
||||||
|
|
||||||
|
# matched = m.group(0);
|
||||||
|
|
||||||
|
# print(f'matched = """{matched}"""');
|
||||||
|
|
||||||
|
# table_open_tag = m.group(1) + "\n";
|
||||||
|
|
||||||
|
# one_or_more_body_lines = m.group(2);
|
||||||
|
|
||||||
|
# body_lines = [e.strip().split("\n") for e in one_or_more_body_lines.strip().split("\n\n")]
|
||||||
|
|
||||||
|
# optional_caption = m.group(3);
|
||||||
|
|
||||||
|
# try:
|
||||||
|
# inner = "";
|
||||||
|
|
||||||
|
# # Process the body lines:
|
||||||
|
# for lines in body_lines:
|
||||||
|
# state = State(section_tag = "tbody", \
|
||||||
|
# default_cell_tag = "td", \
|
||||||
|
# column_info = []);
|
||||||
|
|
||||||
|
# for line in lines:
|
||||||
|
# inner += do_table_line(state, line);
|
||||||
|
|
||||||
|
# if state.already_opened_section:
|
||||||
|
# inner += f"</{state.section_tag}>" "\n";
|
||||||
|
|
||||||
|
# # Consider the optional caption.
|
||||||
|
# # If it happens, it goes before everything else
|
||||||
|
# if optional_caption:
|
||||||
|
# inner = f"<caption> {optional_caption} </caption>\n" + inner;
|
||||||
|
|
||||||
|
# table_close_tag = "</table>\n";
|
||||||
|
|
||||||
|
# return "\n\n" + table_open_tag + inner + table_close_tag + "\n\n";
|
||||||
|
|
||||||
|
# except SyntaxError as e:
|
||||||
|
# print(f"caught syntax error: {e}");
|
||||||
|
# print("moving on to next table...");
|
||||||
|
# return m.group(0);
|
||||||
|
|
||||||
|
def handle_table_case_1(m):
|
||||||
|
print("handle_table_case_1");
|
||||||
|
|
||||||
matched = m.group(0);
|
matched = m.group(0);
|
||||||
|
|
||||||
print(f'matched = """{matched}"""');
|
print(f'matched = """{matched}"""');
|
||||||
|
|
||||||
optional_table_open = m.group(1);
|
# required open table tag:
|
||||||
|
table_open_tag = m.group(1);
|
||||||
|
|
||||||
one_or_more_header_lines = m.group(2);
|
# remove the 'markdown="1"' syntax
|
||||||
|
table_open_tag = re.sub(r"markdown=(?:\"1\"|'1'|1)", "", table_open_tag);
|
||||||
|
|
||||||
|
# zero or more header rows:
|
||||||
|
header_rows = m.group(2);
|
||||||
|
|
||||||
|
# required seperator line:
|
||||||
seperator_line = m.group(3);
|
seperator_line = m.group(3);
|
||||||
|
|
||||||
one_or_more_body_lines = m.group(4);
|
# zero or more body rows, with empty lines of one:
|
||||||
|
body_rows = m.group(4);
|
||||||
|
|
||||||
|
# optional caption:
|
||||||
optional_caption = m.group(5);
|
optional_caption = m.group(5);
|
||||||
|
|
||||||
assert(seperator_line is not None)
|
try:
|
||||||
|
inner = "";
|
||||||
|
|
||||||
|
# Process the (optional) header lines:
|
||||||
|
if header_rows is not None:
|
||||||
|
state = State(section_tag = "thead", default_cell_tag = "th");
|
||||||
|
|
||||||
|
for line in header_rows.strip().split('\n'):
|
||||||
|
inner += do_table_line(state, line);
|
||||||
|
|
||||||
|
if state.already_opened_section:
|
||||||
|
inner += f"</{state.section_tag}>" "\n";
|
||||||
|
|
||||||
|
# Handle line seperator:
|
||||||
|
column_info = parse_colinfo(seperator_line);
|
||||||
|
|
||||||
|
if body_rows is not None and body_rows.strip():
|
||||||
|
for body in body_rows.strip().split('\n\n'):
|
||||||
|
state = State(section_tag = "tbody", \
|
||||||
|
default_cell_tag = "td", \
|
||||||
|
column_info = column_info);
|
||||||
|
|
||||||
|
for line in body.strip().split('\n'):
|
||||||
|
inner += do_table_line(state, line);
|
||||||
|
|
||||||
|
if state.already_opened_section:
|
||||||
|
inner += f"</{state.section_tag}>" "\n";
|
||||||
|
|
||||||
|
# Consider the optional caption.
|
||||||
|
# If it happens, it goes before everything else
|
||||||
|
if optional_caption:
|
||||||
|
inner = f"<caption> {optional_caption} </caption>\n" + inner;
|
||||||
|
|
||||||
|
table_open_tag = table_open_tag + "\n";
|
||||||
|
table_close_tag = "</table>\n";
|
||||||
|
|
||||||
|
return "\n\n" + table_open_tag + inner + table_close_tag + "\n";
|
||||||
|
except SyntaxError as e:
|
||||||
|
print(f"caught syntax error: {e}");
|
||||||
|
print("moving on to next table...");
|
||||||
|
return m.group(0);
|
||||||
|
|
||||||
|
def handle_table_case_2(m):
|
||||||
|
print("handle_table_case_2");
|
||||||
|
|
||||||
|
matched = m.group(0);
|
||||||
|
|
||||||
|
print(f'matched = """{matched}"""');
|
||||||
|
|
||||||
|
# no open table tag:
|
||||||
|
|
||||||
|
# one or more header rows:
|
||||||
|
header_rows = m.group(1);
|
||||||
|
|
||||||
|
# line seperator:
|
||||||
|
seperator_line = m.group(2);
|
||||||
|
|
||||||
|
print(f'seperator_line = "{seperator_line.strip()}"');
|
||||||
|
|
||||||
|
# one or more body rows, with empty lines of one:
|
||||||
|
body_rows = m.group(3);
|
||||||
|
|
||||||
|
print(f'body_rows = "{body_rows}"');
|
||||||
|
|
||||||
|
# optional caption:
|
||||||
|
optional_caption = m.group(4);
|
||||||
|
|
||||||
|
# no close table tag:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return do_table(
|
inner = "";
|
||||||
optional_table_open,
|
|
||||||
one_or_more_header_lines.strip().split("\n"),
|
state = State(section_tag = "thead", default_cell_tag = "th");
|
||||||
seperator_line,
|
|
||||||
[e.strip().split("\n")
|
# Process the required header lines:
|
||||||
for e in one_or_more_body_lines.strip().split("\n\n")],
|
for line in header_rows.strip().split('\n'):
|
||||||
optional_caption,
|
inner += do_table_line(state, line);
|
||||||
);
|
|
||||||
|
if state.already_opened_section:
|
||||||
|
inner += f"</{state.section_tag}>" "\n";
|
||||||
|
|
||||||
|
# Handle line seperator:
|
||||||
|
column_info = parse_colinfo(seperator_line);
|
||||||
|
|
||||||
|
for body in body_rows.strip().split('\n\n'):
|
||||||
|
state = State(section_tag = "tbody", \
|
||||||
|
default_cell_tag = "td", \
|
||||||
|
column_info = column_info);
|
||||||
|
|
||||||
|
for line in body.strip().split('\n'):
|
||||||
|
inner += do_table_line(state, line);
|
||||||
|
|
||||||
|
if state.already_opened_section:
|
||||||
|
inner += f"</{state.section_tag}>" "\n";
|
||||||
|
|
||||||
|
# Consider the optional caption.
|
||||||
|
# If it happens, it goes before everything else
|
||||||
|
if optional_caption:
|
||||||
|
inner = f"<caption> {optional_caption} </caption>\n" + inner;
|
||||||
|
|
||||||
|
table_open_tag = "<table>\n";
|
||||||
|
table_close_tag = "</table>\n";
|
||||||
|
|
||||||
|
return "\n\n" + table_open_tag + inner + table_close_tag + "\n";
|
||||||
|
except SyntaxError as e:
|
||||||
|
print(f"caught syntax error: {e}");
|
||||||
|
print("moving on to next table...");
|
||||||
|
return m.group(0);
|
||||||
|
|
||||||
|
def handle_table_case_3(m):
|
||||||
|
print("handle_table_case_3");
|
||||||
|
|
||||||
|
matched = m.group(0);
|
||||||
|
|
||||||
|
print(f'matched = """{matched}"""');
|
||||||
|
|
||||||
|
# required open table tag:
|
||||||
|
table_open_tag = m.group(1);
|
||||||
|
|
||||||
|
# remove the 'markdown="1"' syntax
|
||||||
|
table_open_tag = re.sub(r"markdown=(?:\"1\"|'1'|1)", "", table_open_tag);
|
||||||
|
|
||||||
|
# one or more body rows, with empty lines of one:
|
||||||
|
body_rows = m.group(2);
|
||||||
|
|
||||||
|
# no line seperator
|
||||||
|
|
||||||
|
# optional caption:
|
||||||
|
optional_caption = m.group(3);
|
||||||
|
|
||||||
|
# optional close table tag.
|
||||||
|
|
||||||
|
try:
|
||||||
|
inner = "";
|
||||||
|
|
||||||
|
for body in body_rows.strip().split('\n\n'):
|
||||||
|
state = State(section_tag = "tbody", \
|
||||||
|
default_cell_tag = "td", \
|
||||||
|
column_info = []);
|
||||||
|
|
||||||
|
for line in body.strip().split('\n'):
|
||||||
|
inner += do_table_line(state, line);
|
||||||
|
|
||||||
|
if state.already_opened_section:
|
||||||
|
inner += f"</{state.section_tag}>" "\n";
|
||||||
|
|
||||||
|
# Consider the optional caption.
|
||||||
|
# If it happens, it goes before everything else
|
||||||
|
if optional_caption:
|
||||||
|
inner = f"<caption> {optional_caption} </caption>\n" + inner;
|
||||||
|
|
||||||
|
table_open_tag = table_open_tag + "\n";
|
||||||
|
table_close_tag = "</table>\n";
|
||||||
|
|
||||||
|
return "\n\n" + table_open_tag + inner + table_close_tag + "\n";
|
||||||
except SyntaxError as e:
|
except SyntaxError as e:
|
||||||
print(f"caught syntax error: {e}");
|
print(f"caught syntax error: {e}");
|
||||||
print("moving on to next table...");
|
print("moving on to next table...");
|
||||||
|
|
@ -443,7 +725,7 @@ with open("test.md") as stream:
|
||||||
text = stream.read();
|
text = stream.read();
|
||||||
|
|
||||||
# delimiters between cells
|
# delimiters between cells
|
||||||
delimiter = r"(?:[|]|<(?:tr|th)(?:[\s]+[^<>]*)?>)";
|
delimiter = r"(?:[|]|<(?:td|th)(?:[\s]+[^<>]*)?>)";
|
||||||
|
|
||||||
# A row is anything with at least one delimiter
|
# A row is anything with at least one delimiter
|
||||||
row = fr"(?: .* {delimiter} .*)";
|
row = fr"(?: .* {delimiter} .*)";
|
||||||
|
|
@ -466,35 +748,85 @@ row = fr"(?:{row} | {table_part}+)";
|
||||||
# Between the header rows and the body rows there is a line seperator.
|
# Between the header rows and the body rows there is a line seperator.
|
||||||
seperator_line = r"\s* [|]? \s* [-=:]+ \s* (?: \s* [|] \s* [-=:]* \s* )* \s*"
|
seperator_line = r"\s* [|]? \s* [-=:]+ \s* (?: \s* [|] \s* [-=:]* \s* )* \s*"
|
||||||
|
|
||||||
# Regex for whole table:
|
|
||||||
for o, c in product((1, 0), repeat=2):
|
|
||||||
table = fr"""
|
table = fr"""
|
||||||
# two blank lines:
|
# two blank lines:
|
||||||
[\n]{{2}}
|
[\n]{{2}}
|
||||||
|
|
||||||
# optional or required open table tag:
|
# required open table tag:
|
||||||
(?:(<table(?:[\s]+[^<>]*)?>) \n){{{o},1}}
|
(?:(<table[\s]+[^<>]*markdown=(?:"1"|'1'|1)[^<>]*>) \n)
|
||||||
|
|
||||||
# zero or one or more header rows:
|
# zero or more header rows:
|
||||||
((?: {row} \n){{{1-o},}})
|
((?: {row} \n)+)
|
||||||
|
|
||||||
# line seperator:
|
# required line seperator:
|
||||||
({seperator_line}) [\n]
|
({seperator_line} [\n])
|
||||||
|
|
||||||
# zero or one or more body rows, with empty lines of one:
|
# zero or more body rows, with empty lines of one:
|
||||||
((?: {row} [\n]{{1,2}}){{{1-c},}})
|
((?: {row} [\n]{{1,2}})*)
|
||||||
|
|
||||||
# optional caption:
|
# optional caption:
|
||||||
(?: \[ ([a-z0-9 "']+) \] \n)?
|
(?: \[ ([a-z0-9 "']+) \] \n)?
|
||||||
|
|
||||||
# optional or required close table tag:
|
# optional close table tag:
|
||||||
(?: </table> [\n]){{{c},1}}
|
(?: </table> [\n])?
|
||||||
|
|
||||||
# two blank lines:
|
# two blank lines (another newline already matched earlier)
|
||||||
[\n]{{2}}
|
[\n]{{1}}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
text = re.sub(table, handle_table, text, flags=re.VERBOSE)
|
text = re.sub(table, handle_table_case_1, text, flags=re.VERBOSE)
|
||||||
|
|
||||||
|
table = fr"""
|
||||||
|
# two blank lines:
|
||||||
|
[\n]{{2}}
|
||||||
|
|
||||||
|
# no open table tag:
|
||||||
|
# (?:(<table[\s]+[^<>]*markdown=(?:"1"|'1'|1)[^<>]*>) \n)?
|
||||||
|
|
||||||
|
# one or more header rows:
|
||||||
|
((?: {row} \n)+)
|
||||||
|
|
||||||
|
# line seperator:
|
||||||
|
({seperator_line} [\n])
|
||||||
|
|
||||||
|
# one or more body rows, with empty lines of one:
|
||||||
|
((?: {row} [\n]{{1,2}})+)
|
||||||
|
|
||||||
|
# optional caption:
|
||||||
|
(?: \[ ([a-z0-9 "']+) \] \n)?
|
||||||
|
|
||||||
|
# no close table tag:
|
||||||
|
# (?: </table> [\n])?
|
||||||
|
|
||||||
|
# two blank lines (another newline already matched earlier)
|
||||||
|
[\n]{{1}}
|
||||||
|
""";
|
||||||
|
|
||||||
|
text = re.sub(table, handle_table_case_2, text, flags=re.VERBOSE)
|
||||||
|
|
||||||
|
table = fr"""
|
||||||
|
# two blank lines:
|
||||||
|
[\n]{{2}}
|
||||||
|
|
||||||
|
# required open table tag:
|
||||||
|
(?:(<table[\s]+[^<>]*markdown=(?:"1"|'1'|1)[^<>]*>) \n)
|
||||||
|
|
||||||
|
# one or more body rows, with empty lines of one:
|
||||||
|
((?: {row} [\n]{{1,2}})+)
|
||||||
|
|
||||||
|
# no line seperator
|
||||||
|
|
||||||
|
# optional caption:
|
||||||
|
(?: \[ ([a-z0-9 "']+) \] \n)?
|
||||||
|
|
||||||
|
# optional close table tag:
|
||||||
|
(?: </table> [\n])?
|
||||||
|
|
||||||
|
# two blank lines (another newline already matched earlier)
|
||||||
|
[\n]{{1}}
|
||||||
|
""";
|
||||||
|
|
||||||
|
text = re.sub(table, handle_table_case_3, text, flags=re.VERBOSE)
|
||||||
|
|
||||||
text += """
|
text += """
|
||||||
<style>
|
<style>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue