ApiMarkdownTrait.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\apidoc\helpers;
  8. use phpDocumentor\Reflection\DocBlock\Type\Collection;
  9. use yii\apidoc\models\MethodDoc;
  10. use yii\apidoc\models\TypeDoc;
  11. /**
  12. * Class ApiMarkdownTrait
  13. *
  14. * @property TypeDoc $renderingContext
  15. */
  16. trait ApiMarkdownTrait
  17. {
  18. /**
  19. * @marker [[
  20. */
  21. protected function parseApiLinks($text)
  22. {
  23. $context = $this->renderingContext;
  24. if (preg_match('/^\[\[([\w\d\\\\\(\):$]+)(\|[^\]]*)?\]\]/', $text, $matches)) {
  25. $offset = strlen($matches[0]);
  26. $object = $matches[1];
  27. $title = (empty($matches[2]) || $matches[2] == '|') ? null : substr($matches[2], 1);
  28. if (($pos = strpos($object, '::')) !== false) {
  29. $typeName = substr($object, 0, $pos);
  30. $subjectName = substr($object, $pos + 2);
  31. if ($context !== null) {
  32. // Collection resolves relative types
  33. $typeName = (new Collection([$typeName], $context->phpDocContext))->__toString();
  34. }
  35. /** @var $type TypeDoc */
  36. $type = static::$renderer->apiContext->getType($typeName);
  37. if ($type === null) {
  38. static::$renderer->apiContext->errors[] = [
  39. 'file' => ($context !== null) ? $context->sourceFile : null,
  40. 'message' => 'broken link to ' . $typeName . '::' . $subjectName . (($context !== null) ? ' in ' . $context->name : ''),
  41. ];
  42. return [
  43. ['brokenApiLink', '<span class="broken-link">' . $typeName . '::' . $subjectName . '</span>'],
  44. $offset
  45. ];
  46. } else {
  47. if (($subject = $type->findSubject($subjectName)) !== null) {
  48. if ($title === null) {
  49. $title = $type->name . '::' . $subject->name;
  50. if ($subject instanceof MethodDoc) {
  51. $title .= '()';
  52. }
  53. }
  54. return [
  55. ['apiLink', static::$renderer->createSubjectLink($subject, $title)],
  56. $offset
  57. ];
  58. } else {
  59. static::$renderer->apiContext->errors[] = [
  60. 'file' => ($context !== null) ? $context->sourceFile : null,
  61. 'message' => 'broken link to ' . $type->name . '::' . $subjectName . (($context !== null) ? ' in ' . $context->name : ''),
  62. ];
  63. return [
  64. ['brokenApiLink', '<span class="broken-link">' . $type->name . '::' . $subjectName . '</span>'],
  65. $offset
  66. ];
  67. }
  68. }
  69. } elseif ($context !== null && ($subject = $context->findSubject($object)) !== null) {
  70. return [
  71. ['apiLink', static::$renderer->createSubjectLink($subject, $title)],
  72. $offset
  73. ];
  74. }
  75. if ($context !== null) {
  76. // Collection resolves relative types
  77. $object = (new Collection([$object], $context->phpDocContext))->__toString();
  78. }
  79. if (($type = static::$renderer->apiContext->getType($object)) !== null) {
  80. return [
  81. ['apiLink', static::$renderer->createTypeLink($type, null, $title)],
  82. $offset
  83. ];
  84. } elseif (strpos($typeLink = static::$renderer->createTypeLink($object, null, $title), '<a href') !== false) {
  85. return [
  86. ['apiLink', $typeLink],
  87. $offset
  88. ];
  89. }
  90. static::$renderer->apiContext->errors[] = [
  91. 'file' => ($context !== null) ? $context->sourceFile : null,
  92. 'message' => 'broken link to ' . $object . (($context !== null) ? ' in ' . $context->name : ''),
  93. ];
  94. return [
  95. ['brokenApiLink', '<span class="broken-link">' . $object . '</span>'],
  96. $offset
  97. ];
  98. }
  99. return [['text', '[['], 2];
  100. }
  101. /**
  102. * Renders API link
  103. * @param array $block
  104. * @return string
  105. */
  106. protected function renderApiLink($block)
  107. {
  108. return $block[1];
  109. }
  110. /**
  111. * Renders API link that is broken i.e. points nowhere
  112. * @param array $block
  113. * @return string
  114. */
  115. protected function renderBrokenApiLink($block)
  116. {
  117. return $block[1];
  118. }
  119. /**
  120. * Consume lines for a blockquote element
  121. */
  122. protected function consumeQuote($lines, $current)
  123. {
  124. $block = parent::consumeQuote($lines, $current);
  125. $blockTypes = [
  126. 'warning',
  127. 'note',
  128. 'info',
  129. 'tip',
  130. ];
  131. // check whether this is a special Info, Note, Warning, Tip block
  132. $content = $block[0]['content'];
  133. $first = reset($content);
  134. if (isset($first[0]) && $first[0] === 'paragraph') {
  135. $parfirst = reset($first['content']);
  136. if (isset($parfirst[0]) && $parfirst[0] === 'text') {
  137. foreach ($blockTypes as $type) {
  138. if (strncasecmp("$type: ", $parfirst[1], $len = strlen($type) + 2) === 0) {
  139. // remove block indicator
  140. $block[0]['content'][0]['content'][0][1] = substr($parfirst[1], $len);
  141. // add translated block indicator as bold text
  142. array_unshift($block[0]['content'][0]['content'], [
  143. 'strong',
  144. [
  145. ['text', $this->translateBlockType($type)],
  146. ],
  147. ]);
  148. $block[0]['blocktype'] = $type;
  149. break;
  150. }
  151. }
  152. }
  153. }
  154. return $block;
  155. }
  156. /**
  157. * @since 2.0.5
  158. */
  159. protected abstract function translateBlockType($type);
  160. /**
  161. * Renders a blockquote
  162. */
  163. protected function renderQuote($block)
  164. {
  165. $class = '';
  166. if (isset($block['blocktype'])) {
  167. $class = ' class="' . $block['blocktype'] . '"';
  168. }
  169. return "<blockquote{$class}>" . $this->renderAbsy($block['content']) . "</blockquote>\n";
  170. }
  171. }