Completed
Push — master ( 28e891...fcc325 )
by Carsten
02:35
created

block/HtmlTrait.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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 inline and block HTML support
12
 */
13
trait HtmlTrait
14
{
15
	/**
16
	 * @var array HTML elements considered as inline elements.
17
	 * @see http://www.w3.org/wiki/HTML/Elements#Text-level_semantics
18
	 */
19
	protected $inlineHtmlElements = [
20
		'a', 'abbr', 'acronym',
21
		'b', 'basefont', 'bdo', 'big', 'br', 'button', 'blink',
22
		'cite', 'code',
23
		'del', 'dfn',
24
		'em',
25
		'font',
26
		'i', 'img', 'ins', 'input', 'iframe',
27
		'kbd',
28
		'label', 'listing',
29
		'map', 'mark',
30
		'nobr',
31
		'object',
32
		'q',
33
		'rp', 'rt', 'ruby',
34
		's', 'samp', 'script', 'select', 'small', 'spacer', 'span', 'strong', 'sub', 'sup',
35
		'tt', 'var',
36
		'u',
37
		'wbr',
38
		'time',
39
	];
40
	/**
41
	 * @var array HTML elements known to be self-closing.
42
	 */
43
	protected $selfClosingHtmlElements = [
44
		'br', 'hr', 'img', 'input', 'nobr',
45
	];
46
47
	/**
48
	 * identify a line as the beginning of a HTML block.
49
	 */
50 198
	protected function identifyHtml($line, $lines, $current)
51
	{
52 198
		if ($line[0] !== '<' || isset($line[1]) && $line[1] == ' ') {
53 198
			return false; // no html tag
54
		}
55
56 29
		if (strncmp($line, '<!--', 4) === 0) {
57 6
			return true; // a html comment
58
		}
59
60 26
		$gtPos = strpos($lines[$current], '>');
61 26
		$spacePos = strpos($lines[$current], ' ');
62 26
		if ($gtPos === false && $spacePos === false) {
63 4
			return false; // no html tag
64 25
		} elseif ($spacePos === false) {
65 13
			$tag = rtrim(substr($line, 1, $gtPos - 1), '/');
66
		} else {
67 18
			$tag = rtrim(substr($line, 1, min($gtPos, $spacePos) - 1), '/');
68
		}
69
70 25
		if (!ctype_alnum($tag) || in_array(strtolower($tag), $this->inlineHtmlElements)) {
71 12
			return false; // no html tag or inline html tag
72
		}
73 16
		return true;
74
	}
75
76
	/**
77
	 * Consume lines for an HTML block
78
	 */
79 19
	protected function consumeHtml($lines, $current)
80
	{
81 19
		$content = [];
82 19
		if (strncmp($lines[$current], '<!--', 4) === 0) { // html comment
83 6 View Code Duplication
			for ($i = $current, $count = count($lines); $i < $count; $i++) {
84 6
				$line = $lines[$i];
85 6
				$content[] = $line;
86 6
				if (strpos($line, '-->') !== false) {
87 6
					break;
88
				}
89
			}
90
		} else {
91 16
			$tag = rtrim(substr($lines[$current], 1, min(strpos($lines[$current], '>'), strpos($lines[$current] . ' ', ' ')) - 1), '/');
92 16
			$level = 0;
93 16
			if (in_array($tag, $this->selfClosingHtmlElements)) {
94 6
				$level--;
95
			}
96 16
			for ($i = $current, $count = count($lines); $i < $count; $i++) {
97 16
				$line = $lines[$i];
98 16
				$content[] = $line;
99 16
				$level += substr_count($line, "<$tag") - substr_count($line, "</$tag>") - substr_count($line, "/>");
100 16
				if ($level <= 0) {
101 16
					break;
102
				}
103
			}
104
		}
105
		$block = [
106 19
			'html',
107 19
			'content' => implode("\n", $content),
108
		];
109 19
		return [$block, $i];
110
	}
111
112
	/**
113
	 * Renders an HTML block
114
	 */
115 19
	protected function renderHtml($block)
116
	{
117 19
		return $block['content'] . "\n";
118
	}
119
120
	/**
121
	 * Parses an & or a html entity definition.
122
	 * @marker &
123
	 */
124 10 View Code Duplication
	protected function parseEntity($text)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
125
	{
126
		// html entities e.g. &copy; &#169; &#x00A9;
127 10
		if (preg_match('/^&#?[\w\d]+;/', $text, $matches)) {
128 6
			return [['inlineHtml', $matches[0]], strlen($matches[0])];
129
		} else {
130 10
			return [['text', '&amp;'], 1];
131
		}
132
	}
133
134
	/**
135
	 * renders a html entity.
136
	 */
137 18
	protected function renderInlineHtml($block)
138
	{
139 18
		return $block[1];
140
	}
141
142
	/**
143
	 * Parses inline HTML.
144
	 * @marker <
145
	 */
146 16
	protected function parseInlineHtml($text)
147
	{
148 16
		if (strpos($text, '>') !== false) {
149 16 View Code Duplication
			if (preg_match('~^</?(\w+\d?)( .*?)?>~s', $text, $matches)) {
150
				// HTML tags
151 12
				return [['inlineHtml', $matches[0]], strlen($matches[0])];
152 7
			} elseif (preg_match('~^<!--.*?-->~s', $text, $matches)) {
153
				// HTML comments
154 6
				return [['inlineHtml', $matches[0]], strlen($matches[0])];
155
			}
156
		}
157 1
		return [['text', '&lt;'], 1];
158
	}
159
160
	/**
161
	 * Escapes `>` characters.
162
	 * @marker >
163
	 */
164 7
	protected function parseGt($text)
0 ignored issues
show
The parameter $text is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
165
	{
166 7
		return [['text', '&gt;'], 1];
167
	}
168
}
169