Path: blob/master/src/infrastructure/markup/blockrule/PhutilRemarkupTableBlockRule.php
12241 views
<?php12final class PhutilRemarkupTableBlockRule extends PhutilRemarkupBlockRule {34public function getMatchingLineCount(array $lines, $cursor) {5$num_lines = 0;67if (preg_match('/^\s*<table>/i', $lines[$cursor])) {8$num_lines++;9$cursor++;1011while (isset($lines[$cursor])) {12$num_lines++;13if (preg_match('@</table>\s*$@i', $lines[$cursor])) {14break;15}16$cursor++;17}18}1920return $num_lines;21}2223public function markupText($text, $children) {24$root = id(new PhutilHTMLParser())25->parseDocument($text);2627$nodes = $root->selectChildrenWithTags(array('table'));2829$out = array();30$seen_table = false;31foreach ($nodes as $node) {32if ($node->isContentNode()) {33$content = $node->getContent();3435if (!strlen(trim($content))) {36// Ignore whitespace.37continue;38}3940// If we find other content, fail the rule. This can happen if the41// input is two consecutive table tags on one line with some text42// in between them, which we currently forbid.43return $text;44} else {45// If we have multiple table tags, just return the raw text.46if ($seen_table) {47return $text;48}49$seen_table = true;5051$out[] = $this->newTable($node);52}53}5455if ($this->getEngine()->isTextMode()) {56return implode('', $out);57} else {58return phutil_implode_html('', $out);59}60}6162private function newTable(PhutilDOMNode $table) {63$nodes = $table->selectChildrenWithTags(64array(65'colgroup',66'tr',67));6869$colgroup = null;70$rows = array();7172foreach ($nodes as $node) {73if ($node->isContentNode()) {74$content = $node->getContent();7576// If this is whitespace, ignore it.77if (!strlen(trim($content))) {78continue;79}8081// If we have nonempty content between the rows, this isn't a valid82// table. We can't really do anything reasonable with this, so just83// fail out and render the raw text.84return $table->newRawString();85}8687if ($node->getTagName() === 'colgroup') {88// This table has multiple "<colgroup />" tags. Just bail out.89if ($colgroup !== null) {90return $table->newRawString();91}9293// This table has a "<colgroup />" after a "<tr />". We could parse94// this, but just reject it out of an abundance of caution.95if ($rows) {96return $table->newRawString();97}9899$colgroup = $node;100continue;101}102103$rows[] = $node;104}105106$row_specs = array();107108foreach ($rows as $row) {109$cells = $row->selectChildrenWithTags(array('td', 'th'));110111$cell_specs = array();112foreach ($cells as $cell) {113if ($cell->isContentNode()) {114$content = $node->getContent();115116if ($content === null || !strlen(trim($content))) {117continue;118}119120return $table->newRawString();121}122123// Respect newlines in table cells as literal linebreaks.124125$content = $cell->newRawContentString();126$content = trim($content, "\r\n");127128$lines = phutil_split_lines($content, $retain_endings = false);129foreach ($lines as $key => $line) {130$lines[$key] = $this->applyRules($line);131}132133$content = phutil_implode_html(134phutil_tag('br'),135$lines);136137$cell_specs[] = array(138'type' => $cell->getTagName(),139'content' => $content,140);141}142143$row_specs[] = array(144'type' => 'tr',145'content' => $cell_specs,146);147}148149return $this->renderRemarkupTable($row_specs);150}151152}153154155