Skip to content

Instantly share code, notes, and snippets.

@ksimka
Last active August 29, 2015 14:05
Show Gist options
  • Save ksimka/9a40d2bbb4f566a5ff5e to your computer and use it in GitHub Desktop.
Save ksimka/9a40d2bbb4f566a5ff5e to your computer and use it in GitHub Desktop.
PADN example for yii2 / framework / console / Markdown.php
<?php
// Source: https://github.com/yiisoft/yii2/blob/a2c483fc19a0d46dcefd5e97293cde55ee552ecf/framework/console/Markdown.php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\console;
use yii\helpers\Console;
/**
* A Markdown parser that enhances markdown for reading in console environments.
*
* Based on [cebe/markdown](https://github.com/cebe/markdown).
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class Markdown extends \cebe\markdown\Parser
{
/**
* @var array these are "escapeable" characters. When using one of these prefixed with a
* backslash, the character will be outputted without the backslash and is not interpreted
* as markdown.
*/
protected $escapeCharacters = [
'\\', // backslash
'`', // backtick
'*', // asterisk
'_', // underscore
];
/**
* @inheritDoc
*/
protected function identifyLine($lines, $current)
{
if (isset($lines[$current]) && (strncmp($lines[$current], '```', 3) === 0 || strncmp($lines[$current], '~~~', 3) === 0)) {
return 'fencedCode';
}
return parent::identifyLine($lines, $current);
}
/**
* Consume lines for a fenced code block
*
* @param array $lines [str, ...]
* @param integer $current
* @return array [['type':str, 'content':[str, ...], 'language':str], int=block_length]
*/
protected function consumeFencedCode($lines, $current)
{
// consume until ```
$block = [
'type' => 'code',
'content' => [],
];
$line = rtrim($lines[$current]);
$fence = substr($line, 0, $pos = strrpos($line, $line[0]) + 1);
$language = substr($line, $pos);
if (!empty($language)) {
$block['language'] = $language;
}
for ($i = $current + 1, $count = count($lines); $i < $count; $i++) {
if (rtrim($line = $lines[$i]) !== $fence) {
$block['content'][] = $line;
} else {
break;
}
}
return [$block, $i];
}
/**
* Renders a code block
*
* @param array $block ['type':str, 'content':[str, ...], 'language':str]
* @return string
*/
protected function renderCode($block)
{
return Console::ansiFormat(implode("\n", $block['content']), [Console::BG_GREY]) . "\n";
}
/**
* @inheritdoc
*/
protected function renderParagraph($block)
{
return rtrim($this->parseInline(implode("\n", $block['content']))) . "\n";
}
/**
* @inheritDoc
*/
protected function inlineMarkers()
{
return [
'*' => 'parseEmphStrong',
'_' => 'parseEmphStrong',
'\\' => 'parseEscape',
'`' => 'parseCode',
'~~' => 'parseStrike',
];
}
/**
* Parses an inline code span `` ` ``.
* @param string $text
* @return array [str=block, int=block_length]
*/
protected function parseCode($text)
{
// skip fenced code
if (strncmp($text, '```', 3) === 0) {
return [$text[0], 1];
}
if (preg_match('/^(`+) (.+?) \1/', $text, $matches)) { // code with enclosed backtick
return [
Console::ansiFormat($matches[2], [Console::UNDERLINE]),
strlen($matches[0])
];
} elseif (preg_match('/^`(.+?)`/', $text, $matches)) {
return [
Console::ansiFormat($matches[1], [Console::UNDERLINE]),
strlen($matches[0])
];
}
return [$text[0], 1];
}
/**
* Parses empathized and strong elements.
* @param string $text
* @return array [str=block, int=block_length]
*/
protected function parseEmphStrong($text)
{
$marker = $text[0];
if (!isset($text[1])) {
return [$text[0], 1];
}
if ($marker == $text[1]) { // strong
if ($marker == '*' && preg_match('/^[*]{2}((?:[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s', $text, $matches) ||
$marker == '_' && preg_match('/^__((?:[^_]|_[^_]*_)+?)__(?!_)/us', $text, $matches)) {
return [Console::ansiFormat($this->parseInline($matches[1]), Console::BOLD), strlen($matches[0])];
}
} else { // emph
if ($marker == '*' && preg_match('/^[*]((?:[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', $text, $matches) ||
$marker == '_' && preg_match('/^_((?:[^_]|__[^_]*__)+?)_(?!_)\b/us', $text, $matches)) {
return [Console::ansiFormat($this->parseInline($matches[1]), Console::ITALIC), strlen($matches[0])];
}
}
return [$text[0], 1];
}
/**
* Parses the strikethrough feature.
* @param string $markdown
* @return array [str=block, int=block_length]
*/
protected function parseStrike($markdown)
{
if (preg_match('/^~~(.+?)~~/', $markdown, $matches)) {
return [
Console::ansiFormat($this->parseInline($matches[1]), [Console::CROSSED_OUT]),
strlen($matches[0])
];
}
return [$markdown[0] . $markdown[1], 2];
}
/**
* Parses escaped special characters.
* @param string $text
* @return array [str=block, int=block_length]
*/
protected function parseEscape($text)
{
if (isset($text[1]) && in_array($text[1], $this->escapeCharacters)) {
return [$text[1], 2];
}
return [$text[0], 1];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment