123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- <?php
- /**
- * @link http://www.yiiframework.com/
- * @copyright Copyright (c) 2008 Yii Software LLC
- * @license http://www.yiiframework.com/license/
- */
- namespace yii\apidoc\helpers;
- use cebe\markdown\GithubMarkdown;
- use DomainException;
- use Highlight\Highlighter;
- use yii\apidoc\models\TypeDoc;
- use yii\apidoc\renderers\BaseRenderer;
- use yii\helpers\Html;
- use yii\helpers\Inflector;
- use yii\helpers\Markdown;
- /**
- * A Markdown helper with support for class reference links.
- *
- * @author Carsten Brandt <mail@cebe.cc>
- * @since 2.0
- */
- class ApiMarkdown extends GithubMarkdown
- {
- use ApiMarkdownTrait;
- /**
- * @var BaseRenderer
- */
- public static $renderer;
- /**
- * @var array translation for guide block types
- * @since 2.0.5
- */
- public static $blockTranslations = [];
- protected $renderingContext;
- protected $headings = [];
- /**
- * @return array the headlines of this document
- * @since 2.0.5
- */
- public function getHeadings()
- {
- return $this->headings;
- }
- /**
- * @inheritDoc
- */
- protected function prepare()
- {
- parent::prepare();
- $this->headings = [];
- }
- public function parse($text)
- {
- $markup = parent::parse($text);
- $markup = $this->applyToc($markup);
- return $markup;
- }
- /**
- * @since 2.0.5
- */
- protected function applyToc($content)
- {
- // generate TOC
- if (!empty($this->headings)) {
- $toc = [];
- foreach ($this->headings as $heading)
- $toc[] = '<li>' . Html::a(strip_tags($heading['title']), '#' . $heading['id']) . '</li>';
- $toc = '<div class="toc"><ol>' . implode("\n", $toc) . "</ol></div>\n";
- if (strpos($content, '</h1>') !== false)
- $content = str_replace('</h1>', "</h1>\n" . $toc, $content);
- else
- $content = $toc . $content;
- }
- return $content;
- }
- /**
- * @var Highlighter
- */
- private static $highlighter;
- /**
- * @inheritdoc
- */
- protected function renderCode($block)
- {
- if (self::$highlighter === null) {
- self::$highlighter = new Highlighter();
- self::$highlighter->setAutodetectLanguages([
- 'apache', 'nginx',
- 'bash', 'dockerfile', 'http',
- 'css', 'less', 'scss',
- 'javascript', 'json', 'markdown',
- 'php', 'sql', 'twig', 'xml',
- ]);
- }
- try {
- if (isset($block['language'])) {
- $result = self::$highlighter->highlight($block['language'], $block['content'] . "\n");
- return "<pre><code class=\"hljs {$result->language} language-{$block['language']}\">{$result->value}</code></pre>\n";
- } else {
- $result = self::$highlighter->highlightAuto($block['content'] . "\n");
- return "<pre><code class=\"hljs {$result->language}\">{$result->value}</code></pre>\n";
- }
- } catch (DomainException $e) {
- echo $e;
- return parent::renderCode($block);
- }
- }
- /**
- * Highlights code
- *
- * @param string $code code to highlight
- * @param string $language language of the code to highlight
- * @return string HTML of highlighted code
- * @deprecated since 2.0.5 this method is not used anymore, highlight.php is used for highlighting
- */
- public static function highlight($code, $language)
- {
- if ($language !== 'php') {
- return htmlspecialchars($code, ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8');
- }
- if (strncmp($code, '<?php', 5) === 0) {
- $text = @highlight_string(trim($code), true);
- } else {
- $text = highlight_string("<?php ".trim($code), true);
- $text = str_replace('<?php', '', $text);
- if (($pos = strpos($text, ' ')) !== false) {
- $text = substr($text, 0, $pos) . substr($text, $pos + 6);
- }
- }
- // remove <code><span style="color: #000000">\n and </span>tags added by php
- $text = substr(trim($text), 36, -16);
- return $text;
- }
- /**
- * @inheritDoc
- */
- protected function renderHeadline($block)
- {
- $content = $this->renderAbsy($block['content']);
- if (preg_match('~<span id="(.*?)"></span>~', $content, $matches)) {
- $hash = $matches[1];
- $content = preg_replace('~<span id=".*?"></span>~', '', $content);
- } else {
- $hash = Inflector::slug(strip_tags($content));
- }
- $hashLink = "<span id=\"$hash\"></span><a href=\"#$hash\" class=\"hashlink\">¶</a>";
- if ($block['level'] == 2) {
- $this->headings[] = [
- 'title' => trim($content),
- 'id' => $hash,
- ];
- } elseif ($block['level'] > 2) {
- if (end($this->headings)) {
- $this->headings[key($this->headings)]['sub'][] = [
- 'title' => trim($content),
- 'id' => $hash,
- ];
- }
- }
- $tag = 'h' . $block['level'];
- return "<$tag>$content $hashLink</$tag>";
- }
- /**
- * @inheritdoc
- */
- protected function renderLink($block)
- {
- $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;
- }
- /**
- * @inheritdoc
- * @since 2.0.5
- */
- protected function translateBlockType($type)
- {
- $key = ucfirst($type) . ':';
- if (isset(static::$blockTranslations[$key])) {
- $translation = static::$blockTranslations[$key];
- } else {
- $translation = $key;
- }
- return "$translation ";
- }
- /**
- * Converts markdown into HTML
- *
- * @param string $content
- * @param TypeDoc $context
- * @param bool $paragraph
- * @return string
- */
- public static function process($content, $context = null, $paragraph = false)
- {
- if (!isset(Markdown::$flavors['api'])) {
- Markdown::$flavors['api'] = new static;
- }
- if (is_string($context)) {
- $context = static::$renderer->apiContext->getType($context);
- }
- Markdown::$flavors['api']->renderingContext = $context;
- if ($paragraph) {
- return Markdown::processParagraph($content, 'api');
- } else {
- return Markdown::process($content, 'api');
- }
- }
- /**
- * Add bootstrap classes to tables.
- * @inheritdoc
- */
- public function renderTable($block)
- {
- return str_replace('<table>', '<table class="table table-bordered table-striped">', parent::renderTable($block));
- }
- }
|