diff --git a/extensions/yii/apidoc/helpers/Markdown.php b/extensions/yii/apidoc/helpers/Markdown.php new file mode 100644 index 0000000..2bbad50 --- /dev/null +++ b/extensions/yii/apidoc/helpers/Markdown.php @@ -0,0 +1,76 @@ + + */ + +namespace yii\apidoc\helpers; + + +use phpDocumentor\Reflection\DocBlock\Type\Collection; +use yii\apidoc\models\MethodDoc; +use yii\apidoc\models\TypeDoc; +use yii\apidoc\templates\BaseRenderer; +use yii\helpers\Html; + +class Markdown extends \yii\helpers\Markdown +{ + /** + * @var BaseRenderer + */ + public static $renderer; + + /** + * Converts markdown into HTML + * + * @param string $content + * @param TypeDoc $context + * @return string + */ + public static function process($content, $context) + { + $content = trim(parent::process($content, [])); + if (!strncmp($content, '
', 3) && substr($content, -4, 4) == '
') { + $content = substr($content, 3, -4); + } + + $content = preg_replace_callback('/\[\[([\w\d\\\\\(\):]+)(\|[\w\d ]*)?\]\]/xm', function($matches) use ($context) { + $object = $matches[1]; + $title = (empty($matches[2]) || $matches[2] == '|') ? null : substr($matches[2], 1); + + if (($pos = strpos($object, '::')) !== false) { + $typeName = substr($object, 0, $pos); + $subjectName = substr($object, $pos + 2); + // Collection resolves relative types + $typeName = (new Collection([$typeName], $context->phpDocContext))->__toString(); + $type = static::$renderer->context->getType($typeName); + if ($type === null) { + return '' . $typeName . '::' . $subjectName . ''; + } else { + if (($subject = $type->findSubject($subjectName)) !== null) { + if ($title === null) { + $title = $type->name . '::' . $subject->name; + if ($subject instanceof MethodDoc) { + $title .= '()'; + } + } + return static::$renderer->subjectLink($subject, $title); + } else { + return '' . $type->name . '::' . $subjectName . ''; + } + } + } elseif (($subject = $context->findSubject($object)) !== null) { + return static::$renderer->subjectLink($subject, $title); + } + // Collection resolves relative types + $object = (new Collection([$object], $context->phpDocContext))->__toString(); + if (($type = static::$renderer->context->getType($object)) !== null) { + return static::$renderer->typeLink($type, $title); + } + return '' . $object . ''; + }, $content); + + return $content; + } +} \ No newline at end of file diff --git a/extensions/yii/apidoc/models/BaseDoc.php b/extensions/yii/apidoc/models/BaseDoc.php index b595dcc..c470ab5 100644 --- a/extensions/yii/apidoc/models/BaseDoc.php +++ b/extensions/yii/apidoc/models/BaseDoc.php @@ -18,6 +18,11 @@ use yii\base\Object; */ class BaseDoc extends Object { + /** + * @var \phpDocumentor\Reflection\DocBlock\Context + */ + public $phpDocContext; + public $name; public $sourceFile; @@ -55,9 +60,11 @@ class BaseDoc extends Object $docblock = $reflector->getDocBlock(); if ($docblock !== null) { - $this->shortDescription = $docblock->getShortDescription(); + $this->shortDescription = ucfirst($docblock->getShortDescription()); $this->description = $docblock->getLongDescription(); + $this->phpDocContext = $docblock->getContext(); + $this->tags = $docblock->getTags(); foreach($this->tags as $i => $tag) { if ($tag instanceof SinceTag) { diff --git a/extensions/yii/apidoc/models/ClassDoc.php b/extensions/yii/apidoc/models/ClassDoc.php index a70ae85..d9b17a4 100644 --- a/extensions/yii/apidoc/models/ClassDoc.php +++ b/extensions/yii/apidoc/models/ClassDoc.php @@ -34,6 +34,24 @@ class ClassDoc extends TypeDoc public $constants = []; + public function findSubject($subjectName) + { + if (($subject = parent::findSubject($subjectName)) !== null) { + return $subject; + } + foreach($this->events as $name => $event) { + if ($subjectName == $name) { + return $event; + } + } + foreach($this->constants as $name => $constant) { + if ($subjectName == $name) { + return $constant; + } + } + return null; + } + /** * @return EventDoc[] */ diff --git a/extensions/yii/apidoc/models/FunctionDoc.php b/extensions/yii/apidoc/models/FunctionDoc.php index 1120f77..9c7e212 100644 --- a/extensions/yii/apidoc/models/FunctionDoc.php +++ b/extensions/yii/apidoc/models/FunctionDoc.php @@ -60,7 +60,7 @@ class FunctionDoc extends BaseDoc if (!isset($this->params[$paramName])) { echo 'undefined parameter documented: ' . $paramName . ' in ' . $this->name . "\n"; // todo add this to a log file } - $this->params[$paramName]->description = $tag->getDescription(); + $this->params[$paramName]->description = ucfirst($tag->getDescription()); $this->params[$paramName]->type = $tag->getType(); $this->params[$paramName]->types = $tag->getTypes(); unset($this->tags[$i]); diff --git a/extensions/yii/apidoc/models/TypeDoc.php b/extensions/yii/apidoc/models/TypeDoc.php index 9ceaf26..5a83383 100644 --- a/extensions/yii/apidoc/models/TypeDoc.php +++ b/extensions/yii/apidoc/models/TypeDoc.php @@ -30,6 +30,30 @@ class TypeDoc extends BaseDoc public $namespace; + + public function findSubject($subjectName) + { + if ($subjectName[0] != '$') { + foreach($this->methods as $name => $method) { + if (rtrim($subjectName, '()') == $name) { + return $method; + } + } + } + if (substr($subjectName, -2, 2) == '()') { + return null; + } + if ($this->properties === null) { + return null; + } + foreach($this->properties as $name => $property) { + if (ltrim($subjectName, '$') == ltrim($name, '$')) { + return $property; + } + } + return null; + } + /** * @return MethodDoc[] */ diff --git a/extensions/yii/apidoc/templates/BaseRenderer.php b/extensions/yii/apidoc/templates/BaseRenderer.php index 4f29e43..97d58a5 100644 --- a/extensions/yii/apidoc/templates/BaseRenderer.php +++ b/extensions/yii/apidoc/templates/BaseRenderer.php @@ -8,11 +8,16 @@ namespace yii\apidoc\templates; use Yii; +use yii\apidoc\models\ClassDoc; +use yii\apidoc\models\ConstDoc; +use yii\apidoc\models\Context; +use yii\apidoc\models\EventDoc; +use yii\apidoc\models\InterfaceDoc; +use yii\apidoc\models\MethodDoc; +use yii\apidoc\models\PropertyDoc; +use yii\apidoc\models\TraitDoc; use yii\base\Component; use yii\console\Controller; -use yii\apidoc\models\Context; -use yii\web\AssetManager; -use yii\web\View; /** * Base class for all API documentation renderers @@ -23,10 +28,32 @@ use yii\web\View; abstract class BaseRenderer extends Component { /** + * @var Context the [[Context]] currently being rendered. + */ + public $context; + + + /** * Renders a given [[Context]]. * * @param Context $context the api documentation context to render. * @param Controller $controller the apidoc controller instance. Can be used to control output. */ public abstract function render($context, $controller); + + /** + * creates a link to a type (class, interface or trait) + * @param ClassDoc|InterfaceDoc|TraitDoc $types + * @param string $title + * @return string + */ + public abstract function typeLink($types, $title = null); + + /** + * creates a link to a subject + * @param PropertyDoc|MethodDoc|ConstDoc|EventDoc $subject + * @param string $title + * @return string + */ + public abstract function subjectLink($subject, $title = null); } \ No newline at end of file diff --git a/extensions/yii/apidoc/templates/html/Renderer.php b/extensions/yii/apidoc/templates/html/Renderer.php index 4d5ae20..2129695 100644 --- a/extensions/yii/apidoc/templates/html/Renderer.php +++ b/extensions/yii/apidoc/templates/html/Renderer.php @@ -7,6 +7,7 @@ namespace yii\apidoc\templates\html; +use yii\apidoc\helpers\Markdown; use yii\apidoc\models\BaseDoc; use yii\apidoc\models\ConstDoc; use yii\apidoc\models\EventDoc; @@ -55,14 +56,16 @@ abstract class Renderer extends BaseRenderer implements ViewContextInterface */ public $indexView = '@yii/apidoc/templates/html/views/index.php'; /** - * @var Context the [[Context]] currently being rendered. - */ - protected $context; - /** * @var View */ private $_view; + + public function init() + { + Markdown::$renderer = $this; + } + /** * @return View the view instance */ @@ -179,7 +182,11 @@ abstract class Renderer extends BaseRenderer implements ViewContextInterface public function subjectLink($subject, $title = null) { if ($title === null) { - $title = $subject->name; + if ($subject instanceof MethodDoc) { + $title = $subject->name . '()'; + } else { + $title = $subject->name; + } } if (($type = $this->context->getType($subject->definedBy)) === null) { return $subject->name; diff --git a/extensions/yii/apidoc/templates/html/views/constSummary.php b/extensions/yii/apidoc/templates/html/views/constSummary.php index 63dbbfb..a872aa5 100644 --- a/extensions/yii/apidoc/templates/html/views/constSummary.php +++ b/extensions/yii/apidoc/templates/html/views/constSummary.php @@ -1,5 +1,6 @@ constants)) {description; ?>
+= Markdown::process($event->description, $type); ?>
= $this->render('seeAlso', ['object' => $event]); ?> diff --git a/extensions/yii/apidoc/templates/html/views/eventSummary.php b/extensions/yii/apidoc/templates/html/views/eventSummary.php index 56cb0fa..0c179b6 100644 --- a/extensions/yii/apidoc/templates/html/views/eventSummary.php +++ b/extensions/yii/apidoc/templates/html/views/eventSummary.php @@ -1,5 +1,6 @@ events)) {= $method->shortDescription ?>
-= nl2br($method->description) ?>
+= Markdown::process($method->shortDescription, $type) ?>
+= Markdown::process($method->description, $type) ?>
= $this->render('seeAlso', ['object' => $method]); ?> diff --git a/extensions/yii/apidoc/templates/html/views/methodSummary.php b/extensions/yii/apidoc/templates/html/views/methodSummary.php index e597d53..c3ca6d5 100644 --- a/extensions/yii/apidoc/templates/html/views/methodSummary.php +++ b/extensions/yii/apidoc/templates/html/views/methodSummary.php @@ -1,5 +1,6 @@ getProtectedMethods()) == 0 || !$protected && cou= nl2br($property->description) ?>
+= Markdown::process($property->description, $type) ?>
= $this->render('seeAlso', ['object' => $property]); ?> diff --git a/extensions/yii/apidoc/templates/html/views/propertySummary.php b/extensions/yii/apidoc/templates/html/views/propertySummary.php index ae95850..3730431 100644 --- a/extensions/yii/apidoc/templates/html/views/propertySummary.php +++ b/extensions/yii/apidoc/templates/html/views/propertySummary.php @@ -1,5 +1,6 @@ getProtectedProperties()) == 0 || !$protected &&= nl2br($type->description) ?>
+ = Markdown::process($type->shortDescription, $type) ?> += Markdown::process($type->description, $type) ?>