mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-16 23:48:16 +08:00
fix breaking changes in markdown for console and API
API is not finished. issue #5082
This commit is contained in:
@ -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\">¶</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,50 +38,10 @@ 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
|
||||
*
|
||||
@ -81,7 +50,7 @@ class Markdown extends \cebe\markdown\Parser
|
||||
*/
|
||||
protected function renderCode($block)
|
||||
{
|
||||
return Console::ansiFormat(implode("\n", $block['content']), [Console::NEGATIVE]) . "\n";
|
||||
return Console::ansiFormat($block['content'], [Console::NEGATIVE]) . "\n\n";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,102 +58,46 @@ class Markdown extends \cebe\markdown\Parser
|
||||
*/
|
||||
protected function renderParagraph($block)
|
||||
{
|
||||
return rtrim($this->parseInline(implode("\n", $block['content']))) . "\n";
|
||||
return rtrim($this->renderAbsy($block['content'])) . "\n\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* Renders an inline code span `` ` ``.
|
||||
* @param array $element
|
||||
* @return string
|
||||
*/
|
||||
protected function inlineMarkers()
|
||||
protected function renderInlineCode($element)
|
||||
{
|
||||
return [
|
||||
'*' => 'parseEmphStrong',
|
||||
'_' => 'parseEmphStrong',
|
||||
'\\' => 'parseEscape',
|
||||
'`' => 'parseCode',
|
||||
'~~' => 'parseStrike',
|
||||
];
|
||||
return Console::ansiFormat($element[1], [Console::UNDERLINE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an inline code span `` ` ``.
|
||||
* @param string $text
|
||||
* @return array
|
||||
* Renders empathized elements.
|
||||
* @param array $element
|
||||
* @return string
|
||||
*/
|
||||
protected function parseCode($text)
|
||||
protected function renderEmph($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($this->renderAbsy($element[1]), Console::ITALIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses empathized and strong elements.
|
||||
* @param string $text
|
||||
* @return array
|
||||
* Renders strong elements.
|
||||
* @param array $element
|
||||
* @return string
|
||||
*/
|
||||
protected function parseEmphStrong($text)
|
||||
protected function renderStrong($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::BOLD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the strikethrough feature.
|
||||
* @param string $markdown
|
||||
* @return array
|
||||
* Renders the strike through feature.
|
||||
* @param array $element
|
||||
* @return string
|
||||
*/
|
||||
protected function parseStrike($markdown)
|
||||
protected function renderStrike($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];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses escaped special characters.
|
||||
* @param string $text
|
||||
* @return array
|
||||
*/
|
||||
protected function parseEscape($text)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
}
|
@ -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
|
||||
* see list of available components to flush:
|
||||
*
|
||||
* yii cache
|
||||
*
|
||||
* #flush particular components specified by their names
|
||||
* flush particular components specified by their names:
|
||||
*
|
||||
* yii cache/flush first second third
|
||||
*
|
||||
* #flush all cache components that can be found in the system
|
||||
* 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.
|
||||
|
Reference in New Issue
Block a user