Completed
Push — master ( 422520...8a11c4 )
by Carsten
01:36
created

TableTrait::composeTable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
crap 1
1
<?php
2
/**
3
 * @copyright Copyright (c) 2014 Carsten Brandt
4
 * @license https://github.com/cebe/markdown/blob/master/LICENSE
5
 * @link https://github.com/cebe/markdown#readme
6
 */
7
8
namespace cebe\markdown\block;
9
10
/**
11
 * Adds the table blocks
12
 */
13
trait TableTrait
14
{
15
	private $_tableCellTag = 'td';
16
	private $_tableCellCount = 0;
17
	private $_tableCellAlign = [];
18
19
	/**
20
	 * identify a line as the beginning of a table block.
21
	 */
22 131
	protected function identifyTable($line, $lines, $current)
23
	{
24 131
		return strpos($line, '|') !== false && isset($lines[$current + 1])
25 131
			&& preg_match('~^\\s*\\|?(\\s*:?-[\\-\\s]*:?\\s*\\|?)*\\s*$~', $lines[$current + 1])
26 131
			&& strpos($lines[$current + 1], '|') !== false
27 131
			&& isset($lines[$current + 2]) && trim($lines[$current + 1]) !== '';
28
	}
29
30
	/**
31
	 * Consume lines for a table
32
	 */
33 2
	protected function consumeTable($lines, $current)
34
	{
35
		// consume until newline
36
37
		$block = [
38 2
			'table',
39
			'cols' => [],
40
			'rows' => [],
41
		];
42 2
		for ($i = $current, $count = count($lines); $i < $count; $i++) {
43 2
			$line = trim($lines[$i]);
44
45
			// extract alignment from second line
46 2
			if ($i == $current+1) {
47 2
				$cols = explode('|', trim($line, ' |'));
48 2
				foreach($cols as $col) {
49 2
					$col = trim($col);
50 2
					if (empty($col)) {
51
						$block['cols'][] = '';
52
						continue;
53
					}
54 2
					$l = ($col[0] === ':');
55 2
					$r = (substr($col, -1, 1) === ':');
56 2
					if ($l && $r) {
57 2
						$block['cols'][] = 'center';
58 2
					} elseif ($l) {
59 2
						$block['cols'][] = 'left';
60 2
					} elseif ($r) {
61 2
						$block['cols'][] = 'right';
62
					} else {
63 2
						$block['cols'][] = '';
64
					}
65
				}
66
67 2
				continue;
68
			}
69 2
			if ($line === '' || substr($lines[$i], 0, 4) === '    ') {
70 2
				break;
71
			}
72 2
			if ($line[0] === '|') {
73 2
				$line = substr($line, 1);
74
			}
75 2
			if (substr($line, -1, 1) === '|' && (substr($line, -2, 2) !== '\\|' || substr($line, -3, 3) === '\\\\|')) {
76 2
				$line = substr($line, 0, -1);
77
			}
78 2
			$block['rows'][] = $line;
79
		}
80
81 2
		return [$block, --$i];
82
	}
83
84
	/**
85
	 * render a table block
86
	 */
87 2
	protected function renderTable($block)
88
	{
89 2
		$head = '';
90 2
		$body = '';
91 2
		$this->_tableCellAlign = $block['cols'];
92 2
		$first = true;
93 2
		foreach($block['rows'] as $row) {
94 2
			$this->_tableCellTag = $first ? 'th' : 'td';
95 2
			$align = empty($this->_tableCellAlign[$this->_tableCellCount]) ? '' : ' align="' . $this->_tableCellAlign[$this->_tableCellCount] . '"';
96 2
			$this->_tableCellCount++;
97 2
			$tds = "<$this->_tableCellTag$align>" . trim($this->renderAbsy($this->parseInline($row))) . "</$this->_tableCellTag>"; // TODO move this to the consume step
98 2
			if ($first) {
99 2
				$head .= "<tr>$tds</tr>\n";
100
			} else {
101 2
				$body .= "<tr>$tds</tr>\n";
102
			}
103 2
			$first = false;
104 2
			$this->_tableCellCount = 0;
105
		}
106 2
		return $this->composeTable($head, $body);
107
	}
108
109
	/**
110
	 * This method composes a table from parsed body and head HTML.
111
	 *
112
	 * You may override this method to customize the table rendering, for example by
113
	 * adding a `class` to the table tag:
114
	 *
115
	 * ```php
116
	 * return "<table class="table table-striped">\n<thead>\n$head</thead>\n<tbody>\n$body</tbody>\n</table>\n"
117
	 * ```
118
	 *
119
	 * @param string $head table head HTML.
120
	 * @param string $body table body HTML.
121
	 * @return string the complete table HTML.
122
	 * @since 1.2.0
123
	 */
124 2
	protected function composeTable($head, $body)
125
	{
126 2
		return "<table>\n<thead>\n$head</thead>\n<tbody>\n$body</tbody>\n</table>\n";
127
	}
128
129
	/**
130
	 * @marker |
131
	 */
132 4
	protected function parseTd($markdown)
133
	{
134 4
		if (isset($this->context[1]) && $this->context[1] === 'table') {
135 2
			$align = empty($this->_tableCellAlign[$this->_tableCellCount]) ? '' : ' align="' . $this->_tableCellAlign[$this->_tableCellCount] . '"';
136 2
			$this->_tableCellCount++;
137 2
			return [['text', "</$this->_tableCellTag><$this->_tableCellTag$align>"], isset($markdown[1]) && $markdown[1] === ' ' ? 2 : 1]; // TODO make a absy node
138
		}
139 4
		return [['text', $markdown[0]], 1];
140
	}
141
142
	abstract protected function parseInline($text);
143
	abstract protected function renderAbsy($absy);
144
}
145