Changeset View
Changeset View
Standalone View
Standalone View
src/infrastructure/markup/blockrule/PhutilRemarkupBlockRule.php
- This file was added.
<?php | |||||
abstract class PhutilRemarkupBlockRule extends Phobject { | |||||
private $engine; | |||||
private $rules = array(); | |||||
/** | |||||
* Determine the order in which blocks execute. Blocks with smaller priority | |||||
* numbers execute sooner than blocks with larger priority numbers. The | |||||
* default priority for blocks is `500`. | |||||
* | |||||
* Priorities are used to disambiguate syntax which can match multiple | |||||
* patterns. For example, ` - Lorem ipsum...` may be a code block or a | |||||
* list. | |||||
* | |||||
* @return int Priority at which this block should execute. | |||||
*/ | |||||
public function getPriority() { | |||||
return 500; | |||||
} | |||||
final public function getPriorityVector() { | |||||
return id(new PhutilSortVector()) | |||||
->addInt($this->getPriority()) | |||||
->addString(get_class($this)); | |||||
} | |||||
abstract public function markupText($text, $children); | |||||
/** | |||||
* This will get an array of unparsed lines and return the number of lines | |||||
* from the first array value that it can parse. | |||||
* | |||||
* @param array $lines | |||||
* @param int $cursor | |||||
* | |||||
* @return int | |||||
*/ | |||||
abstract public function getMatchingLineCount(array $lines, $cursor); | |||||
protected function didMarkupText() { | |||||
return; | |||||
} | |||||
final public function setEngine(PhutilRemarkupEngine $engine) { | |||||
$this->engine = $engine; | |||||
$this->updateRules(); | |||||
return $this; | |||||
} | |||||
final protected function getEngine() { | |||||
return $this->engine; | |||||
} | |||||
public function setMarkupRules(array $rules) { | |||||
assert_instances_of($rules, 'PhutilRemarkupRule'); | |||||
$this->rules = $rules; | |||||
$this->updateRules(); | |||||
return $this; | |||||
} | |||||
private function updateRules() { | |||||
$engine = $this->getEngine(); | |||||
if ($engine) { | |||||
$this->rules = msort($this->rules, 'getPriority'); | |||||
foreach ($this->rules as $rule) { | |||||
$rule->setEngine($engine); | |||||
} | |||||
} | |||||
return $this; | |||||
} | |||||
final public function getMarkupRules() { | |||||
return $this->rules; | |||||
} | |||||
final public function postprocess() { | |||||
$this->didMarkupText(); | |||||
} | |||||
final protected function applyRules($text) { | |||||
foreach ($this->getMarkupRules() as $rule) { | |||||
$text = $rule->apply($text); | |||||
} | |||||
return $text; | |||||
} | |||||
public function supportsChildBlocks() { | |||||
return false; | |||||
} | |||||
public function extractChildText($text) { | |||||
throw new PhutilMethodNotImplementedException(); | |||||
} | |||||
protected function renderRemarkupTable(array $out_rows) { | |||||
assert_instances_of($out_rows, 'array'); | |||||
if ($this->getEngine()->isTextMode()) { | |||||
$lengths = array(); | |||||
foreach ($out_rows as $r => $row) { | |||||
foreach ($row['content'] as $c => $cell) { | |||||
$text = $this->getEngine()->restoreText($cell['content']); | |||||
$lengths[$c][$r] = phutil_utf8_strlen($text); | |||||
} | |||||
} | |||||
$max_lengths = array_map('max', $lengths); | |||||
$out = array(); | |||||
foreach ($out_rows as $r => $row) { | |||||
$headings = false; | |||||
foreach ($row['content'] as $c => $cell) { | |||||
$length = $max_lengths[$c] - $lengths[$c][$r]; | |||||
$out[] = '| '.$cell['content'].str_repeat(' ', $length).' '; | |||||
if ($cell['type'] == 'th') { | |||||
$headings = true; | |||||
} | |||||
} | |||||
$out[] = "|\n"; | |||||
if ($headings) { | |||||
foreach ($row['content'] as $c => $cell) { | |||||
$char = ($cell['type'] == 'th' ? '-' : ' '); | |||||
$out[] = '| '.str_repeat($char, $max_lengths[$c]).' '; | |||||
} | |||||
$out[] = "|\n"; | |||||
} | |||||
} | |||||
return rtrim(implode('', $out), "\n"); | |||||
} | |||||
if ($this->getEngine()->isHTMLMailMode()) { | |||||
$table_attributes = array( | |||||
'style' => 'border-collapse: separate; | |||||
border-spacing: 1px; | |||||
background: #d3d3d3; | |||||
margin: 12px 0;', | |||||
); | |||||
$cell_attributes = array( | |||||
'style' => 'background: #ffffff; | |||||
padding: 3px 6px;', | |||||
); | |||||
} else { | |||||
$table_attributes = array( | |||||
'class' => 'remarkup-table', | |||||
); | |||||
$cell_attributes = array(); | |||||
} | |||||
$out = array(); | |||||
$out[] = "\n"; | |||||
foreach ($out_rows as $row) { | |||||
$cells = array(); | |||||
foreach ($row['content'] as $cell) { | |||||
$cells[] = phutil_tag( | |||||
$cell['type'], | |||||
$cell_attributes, | |||||
$cell['content']); | |||||
} | |||||
$out[] = phutil_tag($row['type'], array(), $cells); | |||||
$out[] = "\n"; | |||||
} | |||||
$table = phutil_tag('table', $table_attributes, $out); | |||||
return phutil_tag_div('remarkup-table-wrap', $table); | |||||
} | |||||
} |