`). +Inline elements are elements that are added inside of block elements i.e. inside of text. + +This markdown parser allows you to extend the markdown language by changing existing elements behavior and also adding +new block and inline elements. You do this by extending from the parser class and adding/overriding class methods and +properties. For the different element types there are different ways to extend them as you will see in the following sections. + +### Adding block elements + +The markdown is parsed line by line to identify each non-empty line as one of the block element types. +To identify a line as the beginning of a block element it calls all protected class methods who's name begins with `identify`. +An identify function returns true if it has identified the block element it is responsible for or false if not. +In the following example we will implement support for [fenced code blocks][] which are part of the github flavored markdown. + +[fenced code blocks]: https://help.github.com/articles/github-flavored-markdown#fenced-code-blocks + "Fenced code block feature of github flavored markdown" + +```php + [], + ]; + $line = rtrim($lines[$current]); + + // detect language and fence length (can be more than 3 backticks) + $fence = substr($line, 0, $pos = strrpos($line, '`') + 1); + $language = substr($line, $pos); + if (!empty($language)) { + $block['language'] = $language; + } + + // consume all lines until ``` + for($i = $current + 1, $count = count($lines); $i < $count; $i++) { + if (rtrim($line = $lines[$i]) !== $fence) { + $block['content'][] = $line; + } else { + // stop consuming when code block is over + break; + } + } + return [$block, $i]; + } + ``` + +2. "rendering" the element. After all blocks have been consumed, they are being rendered using the + `render{elementName}()`-method where `elementName` refers to the name of the element in the abstract syntax tree: + + ```php + protected function renderFencedCode($block) + { + $class = isset($block['language']) ? ' class="language-' . $block['language'] . '"' : ''; + return "
" . htmlspecialchars(implode("\n", $block['content']) . "\n", ENT_NOQUOTES, 'UTF-8') . '
';
+ }
+ ```
+
+ You may also add code highlighting here. In general it would also be possible to render ouput in a different language than
+ HTML for example LaTeX.
+
+
+### Adding inline elements
+
+Adding inline elements is different from block elements as they are parsed using markers in the text.
+An inline element is identified by a marker that marks the beginning of an inline element (e.g. `[` will mark a possible
+beginning of a link or `` ` `` will mark inline code).
+
+Parsing methods for inline elements are also protected and identified by the prefix `parse`. Additionally a `@marker` annotation
+in PHPDoc is needed to register the parse function for one or multiple markers.
+The method will then be called when a marker is found in the text. As an argument it takes the text starting at the position of the marker.
+The parser method will return an array containing the element of the abstract sytnax tree and an offset of text it has
+parsed from the input markdown. All text up to this offset will be removed from the markdown before the next marker will be searched.
+
+As an example, we will add support for the [strikethrough][] feature of github flavored markdown:
+
+[strikethrough]: https://help.github.com/articles/github-flavored-markdown#strikethrough "Strikethrough feature of github flavored markdown"
+
+```php
+parseInline($matches[1])],
+ // return the offset of the parsed text
+ strlen($matches[0])
+ ];
+ }
+ // in case we did not find a closing ~~ we just return the marker and skip 2 characters
+ return [['text', '~~'], 2];
+ }
+
+ // rendering is the same as for block elements, we turn the abstract syntax array into a string.
+ protected function renderStrike($element)
+ {
+ return '