Commit 3e3948d8 by Carsten Brandt

fix breaking changes in markdown for console and API

API is not finished. issue #5082
parent b66c4cf4
......@@ -40,7 +40,7 @@ class ApiMarkdown extends GithubMarkdown
if (isset($block['language'])) {
$class = isset($block['language']) ? ' class="language-' . $block['language'] . '"' : '';
return "<pre><code$class>" . $this->highlight($block['content'] . "\n", $block['language']) . '</code></pre>';
return "<pre><code$class>" . $this->highlight($block['content'] . "\n", $block['language']) . "</code></pre>\n";
} else {
return parent::renderCode($block);
}
......@@ -49,7 +49,7 @@ class ApiMarkdown extends GithubMarkdown
public static function highlight($code, $language)
{
if ($language !== 'php') {
return htmlspecialchars($code, ENT_NOQUOTES, 'UTF-8');
return htmlspecialchars($code, ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
// TODO improve code highlighting
......@@ -68,39 +68,32 @@ class ApiMarkdown extends GithubMarkdown
return $text;
}
protected function inlineMarkers()
{
return array_merge(parent::inlineMarkers(), [
'[[' => 'parseApiLinks',
]);
}
/**
* @inheritDoc
*/
protected function renderHeadline($block)
{
$content = $this->parseInline($block['content']);
$content = $this->renderAbsy($block['content']);
$hash = Inflector::slug(strip_tags($content));
$hashLink = "<a href=\"#$hash\" name=\"$hash\" class=\"hashlink\">&para;</a>";
$tag = 'h' . $block['level'];
$tag = 'h' . $block['level'];
return "<$tag>$content $hashLink</$tag>";
}
/**
* @inheritdoc
*/
protected function parseLink($markdown)
protected function renderLink($block)
{
list($result, $skip) = parent::parseLink($markdown);
$result = parent::renderLink($block);
// add special syntax for linking to the guide
$result = preg_replace_callback('/href="guide:([A-z0-9-.#]+)"/i', function($match) {
return 'href="' . static::$renderer->generateGuideUrl($match[1]) . '"';
}, $result, 1);
return [$result, $skip];
return $result;
}
/**
......
......@@ -30,21 +30,11 @@ class ApiMarkdownLaTeX extends GithubMarkdown
protected $renderingContext;
protected function inlineMarkers()
protected function renderApiLink($block)
{
return array_merge(parent::inlineMarkers(), [
'[[' => 'parseApiLinksLatex',
]);
}
protected function parseApiLinksLatex($text)
{
list($html, $offset) = $this->parseApiLinks($text);
// TODO allow break also on camel case
$latex = '\texttt{'.str_replace(['\\textbackslash', '::'], ['\allowbreak{}\\textbackslash', '\allowbreak{}::\allowbreak{}'], $this->escapeLatex(strip_tags($html))).'}';
return [$latex, $offset];
$latex = '\texttt{'.str_replace(['\\textbackslash', '::'], ['\allowbreak{}\\textbackslash', '\allowbreak{}::\allowbreak{}'], $this->escapeLatex(strip_tags($block[1]))).'}';
return $latex;
}
/**
......
......@@ -20,7 +20,6 @@ trait ApiMarkdownTrait
{
/**
* @marker [[
* TODO adjust implementation
*/
protected function parseApiLinks($text)
{
......@@ -49,7 +48,7 @@ trait ApiMarkdownTrait
];
return [
'<span style="background: #f00;">' . $typeName . '::' . $subjectName . '</span>',
['text', '<span style="background: #f00;">' . $typeName . '::' . $subjectName . '</span>'],
$offset
];
} else {
......@@ -62,7 +61,7 @@ trait ApiMarkdownTrait
}
return [
static::$renderer->createSubjectLink($subject, $title),
['apiLink', static::$renderer->createSubjectLink($subject, $title)],
$offset
];
} else {
......@@ -72,14 +71,14 @@ trait ApiMarkdownTrait
];
return [
'<span style="background: #ff0;">' . $type->name . '</span><span style="background: #f00;">::' . $subjectName . '</span>',
['text', '<span style="background: #ff0;">' . $type->name . '</span><span style="background: #f00;">::' . $subjectName . '</span>'],
$offset
];
}
}
} elseif ($context !== null && ($subject = $context->findSubject($object)) !== null) {
return [
static::$renderer->createSubjectLink($subject, $title),
['apiLink', static::$renderer->createSubjectLink($subject, $title)],
$offset
];
}
......@@ -90,12 +89,12 @@ trait ApiMarkdownTrait
}
if (($type = static::$renderer->apiContext->getType($object)) !== null) {
return [
static::$renderer->createTypeLink($type, null, $title),
['apiLink', static::$renderer->createTypeLink($type, null, $title)],
$offset
];
} elseif (strpos($typeLink = static::$renderer->createTypeLink($object, null, $title), '<a href') !== false) {
return [
$typeLink,
['apiLink', $typeLink],
$offset
];
}
......@@ -105,11 +104,16 @@ trait ApiMarkdownTrait
];
return [
'<span style="background: #f00;">' . $object . '</span>',
['text', '<span style="background: #f00;">' . $object . '</span>'],
$offset
];
}
return ['[[', 2];
return [['text', '[['], 2];
}
protected function renderApiLink($block)
{
return $block[1];
}
}
......@@ -28,13 +28,13 @@ class IndexFileAnalyzer extends Markdown
protected function renderHeadline($block)
{
if ($this->_chapter === 0) {
$this->title = $block['content']; // TODO adjust implementation
$this->title = $this->renderAbsy($block['content']);
$this->introduction = '';
$this->_chapter++;
} else {
$this->_chapter++;
$this->_chapters[$this->_chapter] = [
'headline' => $block['content'],
'headline' => $this->renderAbsy($block['content']),
'content' => [],
];
}
......@@ -44,7 +44,7 @@ class IndexFileAnalyzer extends Markdown
protected function renderParagraph($block)
{
if ($this->_chapter < 1) {
$this->introduction .= implode("\n", $block['content']);
$this->introduction .= $this->renderAbsy($block['content']);
}
return parent::renderParagraph($block);
}
......@@ -53,7 +53,7 @@ class IndexFileAnalyzer extends Markdown
{
if ($this->_chapter > 0) {
foreach ($block['items'] as $item => $itemLines) {
if (preg_match('~\[([^\]]+)\]\(([^\)]+)\)(.*)~', implode("\n", $itemLines), $matches)) {
if (preg_match('~\[([^\]]+)\]\(([^\)]+)\)(.*)~', $this->renderAbsy($itemLines), $matches)) {
$this->_chapters[$this->_chapter]['content'][] = [
'headline' => $matches[1],
'file' => $matches[2],
......
......@@ -7,6 +7,10 @@
namespace yii\console;
use cebe\markdown\block\FencedCodeTrait;
use cebe\markdown\inline\CodeTrait;
use cebe\markdown\inline\EmphStrongTrait;
use cebe\markdown\inline\StrikeoutTrait;
use yii\helpers\Console;
/**
......@@ -19,6 +23,11 @@ use yii\helpers\Console;
*/
class Markdown extends \cebe\markdown\Parser
{
use FencedCodeTrait;
use CodeTrait;
use EmphStrongTrait;
use StrikeoutTrait;
/**
* @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
......@@ -29,162 +38,66 @@ class Markdown extends \cebe\markdown\Parser
'`', // backtick
'*', // asterisk
'_', // underscore
'~', // tilde
];
/**
* @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
* @param integer $current
* @return array
*/
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
* @return string
*/
protected function renderCode($block)
{
return Console::ansiFormat(implode("\n", $block['content']), [Console::NEGATIVE]) . "\n";
}
protected function renderCode($block)
{
return Console::ansiFormat($block['content'], [Console::NEGATIVE]) . "\n\n";
}
/**
* @inheritdoc
*/
protected function renderParagraph($block)
{
return rtrim($this->parseInline(implode("\n", $block['content']))) . "\n";
return rtrim($this->renderAbsy($block['content'])) . "\n\n";
}
/**
* @inheritDoc
*/
protected function inlineMarkers()
{
return [
'*' => 'parseEmphStrong',
'_' => 'parseEmphStrong',
'\\' => 'parseEscape',
'`' => 'parseCode',
'~~' => 'parseStrike',
];
}
/**
* Parses an inline code span `` ` ``.
* @param string $text
* @return array
* Renders an inline code span `` ` ``.
* @param array $element
* @return string
*/
protected function parseCode($text)
protected function renderInlineCode($element)
{
// 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];
return Console::ansiFormat($element[1], [Console::UNDERLINE]);
}
/**
* Parses empathized and strong elements.
* @param string $text
* @return array
* Renders empathized elements.
* @param array $element
* @return string
*/
protected function parseEmphStrong($text)
protected function renderEmph($element)
{
$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];
return Console::ansiFormat($this->renderAbsy($element[1]), Console::ITALIC);
}
/**
* Parses the strikethrough feature.
* @param string $markdown
* @return array
* Renders strong elements.
* @param array $element
* @return string
*/
protected function parseStrike($markdown)
protected function renderStrong($element)
{
if (preg_match('/^~~(.+?)~~/', $markdown, $matches)) {
return [
Console::ansiFormat($this->parseInline($matches[1]), [Console::CROSSED_OUT]),
strlen($matches[0])
];
}
return [$markdown[0] . $markdown[1], 2];
return Console::ansiFormat($this->renderAbsy($element[1]), Console::BOLD);
}
/**
* Parses escaped special characters.
* @param string $text
* @return array
* Renders the strike through feature.
* @param array $element
* @return string
*/
protected function parseEscape($text)
protected function renderStrike($element)
{
if (isset($text[1]) && in_array($text[1], $this->escapeCharacters)) {
return [$text[1], 2];
}
return [$text[0], 1];
return Console::ansiFormat($this->parseInline($this->renderAbsy($element[1])), [Console::CROSSED_OUT]);
}
}
\ No newline at end of file
}
......@@ -16,6 +16,7 @@ use yii\helpers\VarDumper;
* Allows you to combine and compress your JavaScript and CSS files.
*
* Usage:
*
* 1. Create a configuration file using the `template` action:
*
* yii asset/template /path/to/myapp/config.php
......
......@@ -16,16 +16,17 @@ use yii\console\Exception;
/**
* Allows you to flush cache.
*
* ~~~
* #see list of available components to flush
* yii cache
* see list of available components to flush:
*
* #flush particular components specified by their names
* yii cache/flush first second third
* yii cache
*
* #flush all cache components that can be found in the system
* yii cache/flush-all
* ~~~
* flush particular components specified by their names:
*
* yii cache/flush first second third
*
* flush all cache components that can be found in the system
*
* yii cache/flush-all
*
* @author Alexander Makarov <sam@rmcreative.ru>
* @author Mark Jebri <mark.github@yandex.ru>
......
......@@ -37,6 +37,10 @@ class BaseMarkdown
'html5' => true,
'enableNewlines' => true,
],
'extra' => [
'class' => 'cebe\markdown\MarkdownExtra',
'html5' => true,
],
];
/**
* @var string the markdown flavor to use when none is specified explicitly.
......
......@@ -15,6 +15,7 @@ namespace yii\helpers;
* ```php
* $myHtml = Markdown::process($myText); // use original markdown flavor
* $myHtml = Markdown::process($myText, 'gfm'); // use github flavored markdown
* $myHtml = Markdown::process($myText, 'extra'); // use markdown extra
* ```
*
* You can configure multiple flavors using the [[$flavors]] property.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment