isMarkdownable['h1']['id'] = 'optional';
$this->isMarkdownable['h1']['class'] = 'optional';
$this->isMarkdownable['h2']['id'] = 'optional';
$this->isMarkdownable['h2']['class'] = 'optional';
$this->isMarkdownable['h3']['id'] = 'optional';
$this->isMarkdownable['h3']['class'] = 'optional';
$this->isMarkdownable['h4']['id'] = 'optional';
$this->isMarkdownable['h4']['class'] = 'optional';
$this->isMarkdownable['h5']['id'] = 'optional';
$this->isMarkdownable['h5']['class'] = 'optional';
$this->isMarkdownable['h6']['id'] = 'optional';
$this->isMarkdownable['h6']['class'] = 'optional';
// tables
$this->isMarkdownable['table'] = array();
$this->isMarkdownable['th'] = array(
'align' => 'optional',
);
$this->isMarkdownable['td'] = array(
'align' => 'optional',
);
$this->isMarkdownable['tr'] = array();
array_push($this->ignore, 'thead');
array_push($this->ignore, 'tbody');
array_push($this->ignore, 'tfoot');
// definition lists
$this->isMarkdownable['dl'] = array();
$this->isMarkdownable['dd'] = array();
$this->isMarkdownable['dt'] = array();
// link class
$this->isMarkdownable['a']['id'] = 'optional';
$this->isMarkdownable['a']['class'] = 'optional';
// footnotes
$this->isMarkdownable['fnref'] = array(
'target' => 'required',
);
$this->isMarkdownable['footnotes'] = array();
$this->isMarkdownable['fn'] = array(
'name' => 'required',
);
$this->parser->blockElements['fnref'] = false;
$this->parser->blockElements['fn'] = true;
$this->parser->blockElements['footnotes'] = true;
// abbr
$this->isMarkdownable['abbr'] = array(
'title' => 'required',
);
// build RegEx lookahead to decide wether table can pe parsed or not
$inlineTags = array_keys($this->parser->blockElements, false);
$colContents = '(?:[^<]|<(?:' . implode('|', $inlineTags) . '|[^a-z]))*';
$this->tableLookaheadHeader = '{
^\s*(?:)?\s* # open optional thead
\s*(?: # start required row with headers
# close row with headers
\s*(?:)? # close optional thead
}sxi';
$this->tdSubstitute = '\s*' . $colContents . '\s* # contents
\s*';
$this->tableLookaheadBody = '{
\s*(?: # header with optional align
\s*' . $colContents . '\s* # contents
\s* # close header
)+
#si', $matches[0], $cols); $regEx = ''; $i = 1; $aligns = array(); foreach ($cols[2] as $align) { $align = strtolower($align); array_push($aligns, $align); if (empty($align)) { $align = 'left'; // default value } $td = '\s+align=("|\')' . $align . '\\' . $i; $i++; if ($align == 'left') { // look for empty align or left $td = '(?:' . $td . ')?'; } $td = ' | '; $regEx .= $td . $this->tdSubstitute; } $regEx = sprintf($this->tableLookaheadBody, $regEx); if (preg_match($regEx, $this->parser->html, $matches, null, strlen($matches[0]))) { // this is a markdownable table tag! $this->table = array( 'rows' => array(), 'col_widths' => array(), 'aligns' => $aligns, ); $this->row = 0; } else { // non markdownable table $this->handleTagToText(); } } else { // non markdownable table $this->handleTagToText(); } } else { $this->table = array( 'rows' => array(), 'col_widths' => array(), 'aligns' => array(), ); $this->row = 0; } } else { // finally build the table in Markdown Extra syntax $separator = array(); if (!isset($this->table['aligns'])) { $this->table['aligns'] = array(); } // seperator with correct align identifiers foreach ($this->table['aligns'] as $col => $align) { if (!$this->keepHTML && !isset($this->table['col_widths'][$col])) { break; } $left = ' '; $right = ' '; switch ($align) { case 'left': $left = ':'; break; case 'center': $right = ':'; $left = ':'; case 'right': $right = ':'; break; } array_push($separator, $left . str_repeat('-', $this->table['col_widths'][$col]) . $right); } $separator = '|' . implode('|', $separator) . '|'; $rows = array(); // add padding array_walk_recursive($this->table['rows'], array(&$this, 'alignTdContent')); $header = array_shift($this->table['rows']); array_push($rows, '| ' . implode(' | ', $header) . ' |'); array_push($rows, $separator); foreach ($this->table['rows'] as $row) { array_push($rows, '| ' . implode(' | ', $row) . ' |'); } $this->out(implode("\n" . $this->indent, $rows)); $this->table = array(); $this->setLineBreaks(2); } } /** * properly pad content so it is aligned as whished * should be used with array_walk_recursive on $this->table['rows'] * * @param string &$content * @param int $col * @return void */ protected function alignTdContent(&$content, $col) { if (!isset($this->table['aligns'][$col])) { $this->table['aligns'][$col] = 'left'; } switch ($this->table['aligns'][$col]) { default: case 'left': $content .= str_repeat(' ', $this->table['col_widths'][$col] - $this->strlen($content)); break; case 'right': $content = str_repeat(' ', $this->table['col_widths'][$col] - $this->strlen($content)) . $content; break; case 'center': $paddingNeeded = $this->table['col_widths'][$col] - $this->strlen($content); $left = floor($paddingNeeded / 2); $right = $paddingNeeded - $left; $content = str_repeat(' ', $left) . $content . str_repeat(' ', $right); break; } } /** * handle |
---|---|
tags * * @param void * @return void */ protected function handleTag_td() { if ($this->parser->isStartTag) { $this->col++; if (!isset($this->table['col_widths'][$this->col])) { $this->table['col_widths'][$this->col] = 0; } $this->buffer(); } else { $buffer = trim($this->unbuffer()); if (!isset($this->table['col_widths'][$this->col])) { $this->table['col_widths'][$this->col] = 0; } $this->table['col_widths'][$this->col] = max($this->table['col_widths'][$this->col], $this->strlen($buffer)); $this->table['rows'][$this->row][$this->col] = $buffer; } } /** * handle | tags
*
* @param void
* @return void
*/
protected function handleTag_th()
{
if (!$this->keepHTML && !isset($this->table['rows'][1]) && !isset($this->table['aligns'][$this->col + 1])) {
if (isset($this->parser->tagAttributes['align'])) {
$this->table['aligns'][$this->col + 1] = $this->parser->tagAttributes['align'];
} else {
$this->table['aligns'][$this->col + 1] = '';
}
}
$this->handleTag_td();
}
/**
* handle
|