Compare commits
4 commits
c67cccc31f
...
f487d02f1c
| Author | SHA1 | Date | |
|---|---|---|---|
| f487d02f1c | |||
| bec3dca171 | |||
| dcbf8db706 | |||
| 4d6169ff59 |
4 changed files with 594 additions and 206 deletions
|
|
@ -109,7 +109,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
public function __construct()
|
||||
{
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
// Add extra escapable characters before parent constructor
|
||||
// initialize the table.
|
||||
$this->escape_chars .= ':|';
|
||||
|
|
@ -123,22 +123,22 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
"stripAbbreviations" => 25,
|
||||
"appendFootnotes" => 50,
|
||||
);
|
||||
|
||||
|
||||
$this->block_gamut += array(
|
||||
"doFencedCodeBlocks" => 5,
|
||||
"doTables" => 15,
|
||||
"doDefLists" => 45,
|
||||
);
|
||||
|
||||
|
||||
$this->span_gamut += array(
|
||||
"doFootnotes" => 5,
|
||||
"doAbbreviations" => 70,
|
||||
);
|
||||
|
||||
$this->enhanced_ordered_list = true;
|
||||
|
||||
|
||||
parent::__construct();
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
}
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
protected array $tom_cells = array();
|
||||
protected array $tom_cells_type = array();
|
||||
protected array $tom_cells_stack = array();
|
||||
|
||||
|
||||
/**
|
||||
* Give the current footnote number.
|
||||
*/
|
||||
|
|
@ -173,7 +173,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
protected function setup()
|
||||
{
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
parent::setup();
|
||||
|
||||
$this->footnotes = array();
|
||||
|
|
@ -188,14 +188,14 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
$this->tom_cells = array();
|
||||
$this->tom_cells_type = array();
|
||||
$this->tom_cells_stack = array();
|
||||
|
||||
|
||||
foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
|
||||
if ($this->abbr_word_re)
|
||||
$this->abbr_word_re .= '|';
|
||||
$this->abbr_word_re .= preg_quote($abbr_word);
|
||||
$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
|
||||
}
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
}
|
||||
|
||||
|
|
@ -204,7 +204,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
*/
|
||||
protected function teardown() {
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$this->footnotes = array();
|
||||
$this->footnotes_ordered = array();
|
||||
$this->footnotes_ref_count = array();
|
||||
|
|
@ -216,7 +216,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
$this->footnotes_assembled = null;
|
||||
|
||||
parent::teardown();
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
}
|
||||
|
||||
|
|
@ -299,7 +299,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
protected function stripLinkDefinitions($text)
|
||||
{
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$less_than_tab = $this->tab_width - 1;
|
||||
|
||||
// Link defs are in the form: ^[id]: url "optional title"
|
||||
|
|
@ -328,9 +328,9 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
}xm',
|
||||
array($this, '_stripLinkDefinitions_callback'),
|
||||
$text);
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
|
@ -342,15 +342,15 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
protected function _stripLinkDefinitions_callback($matches)
|
||||
{
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$link_id = strtolower($matches[1]);
|
||||
$url = $matches[2] == '' ? $matches[3] : $matches[2];
|
||||
$this->urls[$link_id] = $url;
|
||||
$this->titles[$link_id] =& $matches[4];
|
||||
$this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]);
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return ''; // String that will replace the block
|
||||
}
|
||||
|
||||
|
|
@ -1129,7 +1129,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
array($this, '_doHeaders_callback_atx'), $text);
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
|
@ -1177,7 +1177,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
protected function doTables($text)
|
||||
{
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$less_than_tab = $this->tab_width - 1;
|
||||
// Find tables with leading pipe.
|
||||
//
|
||||
|
|
@ -1265,7 +1265,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
}
|
||||
|
||||
$classname = str_replace('%%', $alignname, $this->table_align_class_tmpl);
|
||||
|
||||
|
||||
return " class=\"$classname\"";
|
||||
}
|
||||
|
||||
|
|
@ -1277,9 +1277,9 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
protected function _doTable_callback($matches)
|
||||
{
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
// array_shift($matches);
|
||||
|
||||
|
||||
$head = $matches[1];
|
||||
$underline = $matches[2];
|
||||
$content = $matches[3];
|
||||
|
|
@ -1347,33 +1347,33 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
|
||||
// Write column headers.
|
||||
$table_attr_str = $this->doExtraAttributes('table', $id_class, null, []);
|
||||
$text = "<table$table_attr_str>\n";
|
||||
$text = "<table$table_attr_str>\n";
|
||||
$text .= "<thead>\n";
|
||||
$text .= "<tr>\n";
|
||||
foreach ($headers as $n => $header)
|
||||
{
|
||||
if (preg_match('/\[([a-zA-Z]+)\]/', $header, $matches))
|
||||
if (preg_match('/\[@([a-zA-Z]+)\]/', $header, $matches))
|
||||
{
|
||||
$label = $matches[1];
|
||||
|
||||
|
||||
if ( !in_array($label, $this->tom_cells_stack)
|
||||
&& array_key_exists($label, $this->tom_cells))
|
||||
{
|
||||
array_push($this->tom_cells_stack, $label);
|
||||
|
||||
$local_content = $this->tom_cells[$label];
|
||||
|
||||
if ($this->tom_cells_type[$label] == "span")
|
||||
{
|
||||
$processed = $this->runSpanGamut($local_content);
|
||||
}
|
||||
else
|
||||
{
|
||||
$processed = $this->runBasicBlockGamut($local_content);
|
||||
}
|
||||
|
||||
array_pop($this->tom_cells_stack);
|
||||
|
||||
array_push($this->tom_cells_stack, $label);
|
||||
|
||||
$local_content = $this->tom_cells[$label];
|
||||
|
||||
if ($this->tom_cells_type[$label] == "span")
|
||||
{
|
||||
$processed = $this->runSpanGamut($local_content);
|
||||
}
|
||||
else
|
||||
{
|
||||
$processed = $this->runBasicBlockGamut($local_content);
|
||||
}
|
||||
|
||||
array_pop($this->tom_cells_stack);
|
||||
|
||||
$text .= " <th$attr[$n]>" . $processed . "</th>\n";
|
||||
}
|
||||
else
|
||||
|
|
@ -1409,14 +1409,14 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
if (preg_match('/ *\[([a-zA-Z]+)\] */', $cell, $matches))
|
||||
{
|
||||
$label = $matches[1];
|
||||
|
||||
|
||||
if ( !in_array($label, $this->tom_cells_stack)
|
||||
&& array_key_exists($label, $this->tom_cells))
|
||||
{
|
||||
array_push($this->tom_cells_stack, $label);
|
||||
|
||||
|
||||
$local_content = $this->tom_cells[$label];
|
||||
|
||||
|
||||
if ($this->tom_cells_type[$label] == "span")
|
||||
{
|
||||
$processed = $this->runSpanGamut($local_content);
|
||||
|
|
@ -1425,9 +1425,9 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
{
|
||||
$processed = $this->runBasicBlockGamut($local_content);
|
||||
}
|
||||
|
||||
|
||||
array_pop($this->tom_cells_stack);
|
||||
|
||||
|
||||
$text .= " <{$column_tags[$n]}$attr[$n]>" . $processed . "</td>\n";
|
||||
}
|
||||
else
|
||||
|
|
@ -1440,14 +1440,14 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
$text .= " <{$column_tags[$n]}$attr[$n]>" . $this->runSpanGamut(trim($cell)) . "</td>\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$text .= "</tr>\n";
|
||||
}
|
||||
$text .= "</tbody>\n";
|
||||
$text .= "</table>";
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return $this->hashBlock($text) . "\n";
|
||||
}
|
||||
|
||||
|
|
@ -1459,7 +1459,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
protected function doDefLists($text)
|
||||
{
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$less_than_tab = $this->tab_width - 1;
|
||||
|
||||
// Re-usable pattern to match any entire dl list:
|
||||
|
|
@ -1497,7 +1497,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
array($this, '_doDefLists_callback'), $text);
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
|
@ -1508,7 +1508,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
*/
|
||||
protected function _doDefLists_callback($matches) {
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
// Re-usable patterns to match list item bullets and number markers:
|
||||
$list = $matches[1];
|
||||
|
||||
|
|
@ -1516,9 +1516,9 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
// paragraph for the last item in a list, if necessary:
|
||||
$result = trim($this->processDefListItems($list));
|
||||
$result = "<dl>\n" . $result . "\n</dl>";
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return $this->hashBlock($result) . "\n\n";
|
||||
}
|
||||
|
||||
|
|
@ -1530,7 +1530,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
*/
|
||||
protected function processDefListItems($list_str) {
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
|
||||
$less_than_tab = $this->tab_width - 1;
|
||||
|
||||
|
|
@ -1569,7 +1569,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
array($this, '_processDefListItems_callback_dd'), $list_str);
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return $list_str;
|
||||
}
|
||||
|
||||
|
|
@ -1580,16 +1580,16 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
*/
|
||||
protected function _processDefListItems_callback_dt($matches) {
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$terms = explode("\n", trim($matches[1]));
|
||||
$text = '';
|
||||
foreach ($terms as $term) {
|
||||
$term = $this->runSpanGamut(trim($term));
|
||||
$text .= "\n<dt>" . $term . "</dt>";
|
||||
}
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return $text . "\n";
|
||||
}
|
||||
|
||||
|
|
@ -1600,7 +1600,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
*/
|
||||
protected function _processDefListItems_callback_dd($matches) {
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$leading_line = $matches[1];
|
||||
$marker_space = $matches[2];
|
||||
$def = $matches[3];
|
||||
|
|
@ -1617,7 +1617,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
}
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return "\n<dd>" . $def . "</dd>\n";
|
||||
}
|
||||
|
||||
|
|
@ -1633,7 +1633,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
*/
|
||||
protected function doFencedCodeBlocks($text) {
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$text = preg_replace_callback('{
|
||||
(?:\n|\A)
|
||||
# 1: Opening marker
|
||||
|
|
@ -1664,7 +1664,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
array($this, '_doFencedCodeBlocks_callback'), $text);
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
|
@ -1777,7 +1777,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
*/
|
||||
protected function stripFootnotes($text) {
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$less_than_tab = $this->tab_width - 1;
|
||||
|
||||
// Link defs are in the form: [^id]: url "optional title"
|
||||
|
|
@ -1798,9 +1798,9 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
}xm',
|
||||
array($this, '_stripFootnotes_callback'),
|
||||
$text);
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
|
@ -1812,79 +1812,79 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
protected function _stripFootnotes_callback($matches)
|
||||
{
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$note_id = $this->fn_id_prefix . $matches[1];
|
||||
$content = $this->footnotes[$note_id] = $this->outdent($matches[2]);
|
||||
|
||||
|
||||
$this->zprint("note_id = $note_id");
|
||||
$this->zprint("content = $content");
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return ''; // String that will replace the block
|
||||
}
|
||||
|
||||
protected function stripTomCells($text) {
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$less_than_tab = $this->tab_width - 1;
|
||||
|
||||
$text = preg_replace_callback('{
|
||||
^[ ]{0,' . $less_than_tab . '}\[(.+?)\][ ]?: [ ]* \n
|
||||
^[ ]{0,' . $less_than_tab . '}\[@(.+?)\][ ]?: [ ]* \n
|
||||
|
||||
(
|
||||
(?>
|
||||
(?!^\[\1\])
|
||||
(?!^\[@\1\])
|
||||
.*\n+
|
||||
)+
|
||||
)
|
||||
|
||||
# Closing marker.
|
||||
\[\1\][ ]* (?= \n )
|
||||
\[@\1\][ ]* (?= \n )
|
||||
}xm',
|
||||
array($this, '_stripTomCells_block_callback'),
|
||||
$text);
|
||||
|
||||
|
||||
$text = preg_replace_callback('{
|
||||
^[ ]{0,' . $less_than_tab . '}\[(.+?)\][ ]?: (.+) \[\1\][ ]* (?= \n )
|
||||
}xm',
|
||||
array($this, '_stripTomCells_span_callback'),
|
||||
$text);
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
protected function _stripTomCells_span_callback($matches)
|
||||
{
|
||||
$this->enter(__FUNCTION__);
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
$this->zprint("matches[1] = {$matches[1]}");
|
||||
$this->zprint("matches[2] = {$matches[2]}");
|
||||
$this->zprint("matches[1] = {$matches[1]}");
|
||||
$this->zprint("matches[2] = {$matches[2]}");
|
||||
|
||||
$this->tom_cells[$matches[1]] = trim($matches[2]);
|
||||
|
||||
$this->tom_cells_type[$matches[1]] = "span";
|
||||
|
||||
$this->tom_cells[$matches[1]] = trim($matches[2]);
|
||||
|
||||
$this->tom_cells_type[$matches[1]] = "span";
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function _stripTomCells_block_callback($matches)
|
||||
{
|
||||
$this->enter(__FUNCTION__);
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
$this->zprint("matches[1] = {$matches[1]}");
|
||||
$this->zprint("matches[2] = {$matches[2]}");
|
||||
$this->zprint("matches[1] = {$matches[1]}");
|
||||
$this->zprint("matches[2] = {$matches[2]}");
|
||||
|
||||
$this->tom_cells[$matches[1]] = $this->outdent($matches[2]);
|
||||
|
||||
$this->tom_cells_type[$matches[1]] = "block";
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
$this->tom_cells[$matches[1]] = $this->outdent($matches[2]);
|
||||
|
||||
$this->tom_cells_type[$matches[1]] = "block";
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
|
@ -1908,13 +1908,13 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
*/
|
||||
protected function appendFootnotes($text) {
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
|
||||
array($this, '_appendFootnotes_callback'), $text);
|
||||
|
||||
if ( ! empty( $this->footnotes_ordered ) ) {
|
||||
$this->_doFootnotes();
|
||||
|
||||
|
||||
if ( ! $this->omit_footnotes ) {
|
||||
$text .= "\n\n";
|
||||
$text .= "<div class=\"footnotes\" role=\"doc-endnotes\">\n";
|
||||
|
|
@ -1923,9 +1923,9 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
$text .= "</div>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
|
@ -1937,7 +1937,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
*/
|
||||
protected function _doFootnotes() {
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$attr = array();
|
||||
if ($this->fn_backlink_class !== "") {
|
||||
$class = $this->fn_backlink_class;
|
||||
|
|
@ -2007,7 +2007,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
$text .= "</ol>\n";
|
||||
|
||||
$this->footnotes_assembled = $text;
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
}
|
||||
|
||||
|
|
@ -2085,7 +2085,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
*/
|
||||
protected function stripAbbreviations($text) {
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$less_than_tab = $this->tab_width - 1;
|
||||
|
||||
// Link defs are in the form: [id]*: url "optional title"
|
||||
|
|
@ -2095,9 +2095,9 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
}xm',
|
||||
array($this, '_stripAbbreviations_callback'),
|
||||
$text);
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
|
@ -2108,7 +2108,7 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
*/
|
||||
protected function _stripAbbreviations_callback($matches) {
|
||||
$this->enter(__FUNCTION__);
|
||||
|
||||
|
||||
$abbr_word = $matches[1];
|
||||
$abbr_desc = $matches[2];
|
||||
if ($this->abbr_word_re) {
|
||||
|
|
@ -2116,9 +2116,9 @@ class MarkdownExtra extends \Michelf\Markdown {
|
|||
}
|
||||
$this->abbr_word_re .= preg_quote($abbr_word);
|
||||
$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
|
||||
|
||||
|
||||
$this->exit(__FUNCTION__);
|
||||
|
||||
|
||||
return ''; // String that will replace the block
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
gedit
|
||||
python3
|
||||
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> |
|
||||
| - | :-: | - |
|
||||
<caption> 1 2 3 | 4 5 6
|
||||
<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>
|
||||
x | y | z </tr> </tbody>
|
||||
[ 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
|
||||
| -
|
||||
| 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.
|
||||
|
||||
|
||||
<table>
|
||||
|a
|
||||
<table markdown="1">
|
||||
|a117
|
||||
|-
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<table markdown="1">
|
||||
|-
|
||||
|b
|
||||
</table>
|
||||
|
|
|
|||
524
test.py
524
test.py
|
|
@ -67,6 +67,7 @@ def do_table_line(state, line):
|
|||
I'm supposed to return the whole HTML.
|
||||
Including the <tr> if needed.
|
||||
"""
|
||||
print("do_table_line");
|
||||
|
||||
print(f'line = "{line}"');
|
||||
|
||||
|
|
@ -74,7 +75,7 @@ def do_table_line(state, line):
|
|||
|
||||
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]*";
|
||||
|
||||
|
|
@ -84,7 +85,7 @@ def do_table_line(state, line):
|
|||
|
||||
caption_sentinel_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;
|
||||
|
||||
|
|
@ -94,15 +95,21 @@ def do_table_line(state, line):
|
|||
# Is it whatever our start tag is?
|
||||
if (m := re.match(start_tag_pattern, line)):
|
||||
# we'll pass this through, and remember that we don't need to do
|
||||
# it ourselves
|
||||
print("found our start tag");
|
||||
# it ourselves also possibly close previous section also change
|
||||
# "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)):];
|
||||
|
||||
print(f'line = "{line}"');
|
||||
|
||||
state.section_tag = m.group(1);
|
||||
state.already_opened_section = 1;
|
||||
|
||||
continue;
|
||||
|
|
@ -119,7 +126,7 @@ def do_table_line(state, line):
|
|||
out += f"<{state.section_tag}>";
|
||||
state.already_opened_section = 1;
|
||||
|
||||
out += m.group(0);
|
||||
out += m.group(0) + "\n";
|
||||
|
||||
line = line[len(m.group(0)):];
|
||||
|
||||
|
|
@ -160,7 +167,7 @@ def do_table_line(state, line):
|
|||
|
||||
print(f'line = "{line}"');
|
||||
|
||||
out += "</caption>";
|
||||
out += "</caption>" + "\n";
|
||||
|
||||
continue;
|
||||
|
||||
|
|
@ -168,7 +175,7 @@ def do_table_line(state, line):
|
|||
if (m := re.match(passthrough_pattern, line)):
|
||||
print(f'found passthrough tag: "{m.group(0)}"');
|
||||
|
||||
out += m.group(0);
|
||||
out += m.group(0) + "\n";
|
||||
|
||||
line = line[len(m.group(0)):];
|
||||
|
||||
|
|
@ -187,11 +194,11 @@ def do_table_line(state, line):
|
|||
column_index = 0;
|
||||
|
||||
if not state.already_opened_section:
|
||||
out += f"<{state.section_tag}>";
|
||||
out += f"<{state.section_tag}>" + "\n";
|
||||
state.already_opened_section = 1;
|
||||
|
||||
if not already_open_tr:
|
||||
out += "<tr>";
|
||||
out += "<tr>" + "\n";
|
||||
|
||||
while line:
|
||||
print("new cell");
|
||||
|
|
@ -206,7 +213,7 @@ def do_table_line(state, line):
|
|||
align = state.column_info[column_index]['align'];
|
||||
|
||||
if align != 'default':
|
||||
attributes['align'] = align;
|
||||
attributes['style'] = f'text-align: {align}';
|
||||
|
||||
print(f'attributes = "{attributes}"');
|
||||
|
||||
|
|
@ -225,7 +232,7 @@ def do_table_line(state, line):
|
|||
line = line[1:];
|
||||
|
||||
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");
|
||||
|
||||
tag = m.group(1);
|
||||
|
|
@ -262,7 +269,7 @@ def do_table_line(state, line):
|
|||
line = line[len(m.group(0)):];
|
||||
|
||||
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!");
|
||||
|
||||
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']
|
||||
|
||||
print(f'tag = "{tag}"');
|
||||
|
||||
print(f'line = "{line}"');
|
||||
else:
|
||||
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'line = "{line}"');
|
||||
|
||||
print("looking for closer");
|
||||
|
||||
content = "";
|
||||
|
|
@ -318,15 +329,10 @@ def do_table_line(state, line):
|
|||
print(f'depth = {depth}');
|
||||
elif (m := re.match("</table>", line)):
|
||||
content += m.group(0);
|
||||
depth -= 1;
|
||||
if depth < 0: raise SyntaxError("negative depth; bad HTML");
|
||||
if depth > 0: depth -= 1;
|
||||
line = line[len(m.group(0)):]
|
||||
print(f'line = "{line}"');
|
||||
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)):
|
||||
content += m.group(0);
|
||||
line = line[len(m.group(0)):]
|
||||
|
|
@ -358,82 +364,358 @@ def do_table_line(state, line):
|
|||
|
||||
column_index += 1;
|
||||
|
||||
# end the row of content
|
||||
out += "\n";
|
||||
|
||||
# close tr on its own line
|
||||
out += "</tr>" + "\n";
|
||||
|
||||
print(f'out = "{out}"');
|
||||
|
||||
return out;
|
||||
|
||||
def do_table(table_open_tag, header_lines, seperator_line, body_lines, optional_caption):
|
||||
|
||||
out = "";
|
||||
|
||||
# handle explicit table tag?
|
||||
if table_open_tag:
|
||||
out += table_open_tag + "\n";
|
||||
else:
|
||||
# otherwise, add a default one:
|
||||
out += "<table>" + "\n";
|
||||
|
||||
state = State(section_tag = "thead", default_cell_tag = "th");
|
||||
|
||||
# Process the header lines:
|
||||
for line in header_lines:
|
||||
html_table_line = do_table_line(state, line);
|
||||
|
||||
out += html_table_line + "\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:
|
||||
html_table_line = do_table_line(state, line);
|
||||
|
||||
out += html_table_line + "\n";
|
||||
|
||||
# Consider the optional caption
|
||||
if optional_caption:
|
||||
out += f"<caption> {optional_caption} </caption>\n";
|
||||
|
||||
out += "</table>\n";
|
||||
|
||||
for o in out.split("\n"):
|
||||
print(o);
|
||||
|
||||
return "\n\n" + out + "\n\n";
|
||||
# def do_table(table_open_tag, header_lines, seperator_line, body_lines, optional_caption):
|
||||
#
|
||||
# # handle explicit table tag?
|
||||
# if table_open_tag:
|
||||
# open_tag = table_open_tag + "\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";
|
||||
#
|
||||
# for o in inner.split("\n"):
|
||||
# print(o);
|
||||
#
|
||||
# return "\n\n" + open_tag + inner + close_tag + "\n\n";
|
||||
|
||||
def handle_table(m):
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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:
|
||||
return do_table(
|
||||
optional_table_open,
|
||||
one_or_more_header_lines.strip().split("\n"),
|
||||
seperator_line,
|
||||
[e.strip().split("\n")
|
||||
for e in one_or_more_body_lines.strip().split("\n\n")],
|
||||
optional_caption,
|
||||
);
|
||||
inner = "";
|
||||
|
||||
state = State(section_tag = "thead", default_cell_tag = "th");
|
||||
|
||||
# Process the required header lines:
|
||||
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);
|
||||
|
||||
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:
|
||||
print(f"caught syntax error: {e}");
|
||||
print("moving on to next table...");
|
||||
|
|
@ -443,7 +725,7 @@ with open("test.md") as stream:
|
|||
text = stream.read();
|
||||
|
||||
# delimiters between cells
|
||||
delimiter = r"(?:[|]|<(?:tr|th)(?:[\s]+[^<>]*)?>)";
|
||||
delimiter = r"(?:[|]|<(?:td|th)(?:[\s]+[^<>]*)?>)";
|
||||
|
||||
# A row is anything with at least one 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.
|
||||
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"""
|
||||
# two blank lines:
|
||||
[\n]{{2}}
|
||||
table = fr"""
|
||||
# two blank lines:
|
||||
[\n]{{2}}
|
||||
|
||||
# optional or required open table tag:
|
||||
(?:(<table(?:[\s]+[^<>]*)?>) \n){{{o},1}}
|
||||
# required open table tag:
|
||||
(?:(<table[\s]+[^<>]*markdown=(?:"1"|'1'|1)[^<>]*>) \n)
|
||||
|
||||
# zero or one or more header rows:
|
||||
((?: {row} \n){{{1-o},}})
|
||||
# zero or more header rows:
|
||||
((?: {row} \n)+)
|
||||
|
||||
# line seperator:
|
||||
({seperator_line}) [\n]
|
||||
# required line seperator:
|
||||
({seperator_line} [\n])
|
||||
|
||||
# zero or one or more body rows, with empty lines of one:
|
||||
((?: {row} [\n]{{1,2}}){{{1-c},}})
|
||||
# zero or more body rows, with empty lines of one:
|
||||
((?: {row} [\n]{{1,2}})*)
|
||||
|
||||
# optional caption:
|
||||
(?: \[ ([a-z0-9 "']+) \] \n)?
|
||||
# optional caption:
|
||||
(?: \[ ([a-z0-9 "']+) \] \n)?
|
||||
|
||||
# optional or required close table tag:
|
||||
(?: </table> [\n]){{{c},1}}
|
||||
# optional close table tag:
|
||||
(?: </table> [\n])?
|
||||
|
||||
# two blank lines:
|
||||
[\n]{{2}}
|
||||
""";
|
||||
# two blank lines (another newline already matched earlier)
|
||||
[\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 += """
|
||||
<style>
|
||||
|
|
|
|||
Loading…
Reference in a new issue