Commit 023f4d0a by Carsten Brandt

refactored apidoc extensions completely.

separated guide and apidoc, better maintainability
parent 683a46d9
<?php <?php
/** /**
* @link http://www.yiiframework.com/ * @author Carsten Brandt <mail@cebe.cc>
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/ */
namespace yii\apidoc\commands; namespace yii\apidoc\commands;
use phpDocumentor\Reflection\FileReflector;
use TokenReflection\ReflectionFile; use yii\apidoc\renderers\ApiRenderer;
use yii\apidoc\templates\BaseRenderer;
use yii\console\Controller;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
use yii\helpers\Console; use yii\helpers\Console;
use yii\helpers\FileHelper; use yii\helpers\FileHelper;
use yii\apidoc\components\OfflineRenderer;
use yii\apidoc\models\Context;
use Yii;
/** class ApiController extends BaseController
* Command to render API Documentation files
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class RenderController extends Controller
{ {
public $template = 'bootstrap'; /**
* @var string url to where the guide files are located
*/
public $guide; public $guide;
// TODO add force update option
/** /**
* Renders API documentation files * Renders API documentation files
* @param array $sourceDirs * @param array $sourceDirs
...@@ -38,56 +28,32 @@ class RenderController extends Controller ...@@ -38,56 +28,32 @@ class RenderController extends Controller
*/ */
public function actionIndex(array $sourceDirs, $targetDir) public function actionIndex(array $sourceDirs, $targetDir)
{ {
$targetDir = rtrim(Yii::getAlias($targetDir), '\\/'); $renderer = $this->findRenderer($this->template);
if (is_dir($targetDir) && !$this->confirm('TargetDirectory already exists. Overwrite?')) { $targetDir = $this->normalizeTargetDir($targetDir);
return 2; if ($targetDir === false || $renderer === false) {
}
if (!is_dir($targetDir)) {
mkdir($targetDir);
}
$renderer = $this->findRenderer();
if ($renderer === false) {
return 1; return 1;
} }
$renderer->targetDir = $targetDir;
if ($this->guide !== null && $renderer->hasProperty('guideUrl')) {
$renderer->guideUrl = './';
$renderer->markDownFiles = $this->findMarkdownFiles($this->guide, ['README.md']);
}
$this->stdout('Searching files to process... '); // setup reference to guide
$files = []; if ($this->guide !== null) {
foreach($sourceDirs as $source) { $renderer->guideUrl = $this->guide;
foreach($this->findFiles($source) as $fileName) { $renderer->guideReferences = []; // TODO set references
$files[$fileName] = $fileName;
}
}
$this->stdout('done.' . PHP_EOL, Console::FG_GREEN);
if (empty($files)) {
$this->stderr('Error: No php files found to process.' . PHP_EOL);
return 1;
} }
$context = new Context(); // search for files to process
$files = $this->searchFiles($sourceDirs);
$cacheFile = $targetDir . '/cache/' . md5(serialize($files)) . '.tmp';
if (file_exists($cacheFile)) {
$this->stdout('Loading processed data from cache... ');
$context = unserialize(file_get_contents($cacheFile));
$this->stdout('done.' . PHP_EOL, Console::FG_GREEN);
$this->stdout('Checking for updated files... '); // load context from cache
foreach($context->files as $file => $sha) { $context = $this->loadContext($targetDir);
if (sha1_file($file) === $sha) { $this->stdout('Checking for updated files... ');
unset($files[$file]); foreach($context->files as $file => $sha) {
} if (sha1_file($file) === $sha) {
unset($files[$file]);
} }
$this->stdout('done.' . PHP_EOL, Console::FG_GREEN);
} }
$this->stdout('done.' . PHP_EOL, Console::FG_GREEN);
// process files
$fileCount = count($files); $fileCount = count($files);
$this->stdout($fileCount . ' file' . ($fileCount == 1 ? '' : 's') . ' to update.' . PHP_EOL); $this->stdout($fileCount . ' file' . ($fileCount == 1 ? '' : 's') . ' to update.' . PHP_EOL);
Console::startProgress(0, $fileCount, 'Processing files... ', false); Console::startProgress(0, $fileCount, 'Processing files... ', false);
...@@ -100,42 +66,16 @@ class RenderController extends Controller ...@@ -100,42 +66,16 @@ class RenderController extends Controller
$this->stdout('done.' . PHP_EOL, Console::FG_GREEN); $this->stdout('done.' . PHP_EOL, Console::FG_GREEN);
// save processed data to cache // save processed data to cache
if (!is_dir(dirname($cacheFile))) { $this->storeContext($context, $targetDir);
mkdir(dirname($cacheFile));
}
file_put_contents($cacheFile, serialize($context));
$this->stdout('Updating cross references and backlinks... '); $this->updateContext($context);
$context->updateReferences();
$this->stdout('done.' . PHP_EOL, Console::FG_GREEN);
// render models // render models
$renderer->renderApi($context, $this); $renderer->controller = $this;
$renderer->render($context, $targetDir);
ArrayHelper::multisort($context->errors, 'file'); ArrayHelper::multisort($context->errors, 'file');
print_r($context->errors); print_r($context->errors);
// render guide if specified
if ($this->guide !== null) {
$renderer->renderMarkdownFiles($this);
$this->stdout('Publishing images...');
FileHelper::copyDirectory(rtrim($this->guide, '/\\') . '/images', $targetDir . '/images');
$this->stdout('done.' . PHP_EOL, Console::FG_GREEN);
}
}
/**
* @return BaseRenderer
*/
protected function findRenderer()
{
$rendererClass = 'yii\\apidoc\\templates\\' . $this->template . '\\Renderer';
if (!class_exists($rendererClass)) {
$this->stderr('Renderer not found.' . PHP_EOL);
return false;
}
return new $rendererClass();
} }
protected function findFiles($path, $except = ['vendor/', 'tests/']) protected function findFiles($path, $except = ['vendor/', 'tests/'])
...@@ -143,28 +83,31 @@ class RenderController extends Controller ...@@ -143,28 +83,31 @@ class RenderController extends Controller
$path = FileHelper::normalizePath($path); $path = FileHelper::normalizePath($path);
$options = [ $options = [
'filter' => function ($path) { 'filter' => function ($path) {
if (is_file($path)) { if (is_file($path)) {
$file = basename($path); $file = basename($path);
if ($file[0] < 'A' || $file[0] > 'Z') { if ($file[0] < 'A' || $file[0] > 'Z') {
return false; return false;
}
} }
} return null;
return null; },
},
'only' => ['*.php'], 'only' => ['*.php'],
'except' => $except, 'except' => $except,
]; ];
return FileHelper::findFiles($path, $options); return FileHelper::findFiles($path, $options);
} }
protected function findMarkdownFiles($path, $except = []) /**
* @return ApiRenderer
*/
protected function findRenderer($template)
{ {
$path = FileHelper::normalizePath($path); $rendererClass = 'yii\\apidoc\\templates\\' . $template . '\\ApiRenderer';
$options = [ if (!class_exists($rendererClass)) {
'only' => ['*.md'], $this->stderr('Renderer not found.' . PHP_EOL);
'except' => $except, return false;
]; }
return FileHelper::findFiles($path, $options); return new $rendererClass();
} }
/** /**
...@@ -174,4 +117,4 @@ class RenderController extends Controller ...@@ -174,4 +117,4 @@ class RenderController extends Controller
{ {
return array_merge(parent::globalOptions(), ['template', 'guide']); return array_merge(parent::globalOptions(), ['template', 'guide']);
} }
} }
\ No newline at end of file
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\apidoc\commands;
use yii\apidoc\renderers\BaseRenderer;
use yii\console\Controller;
use yii\helpers\Console;
use yii\apidoc\models\Context;
use Yii;
/**
* Command to render API Documentation files
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
abstract class BaseController extends Controller
{
/**
* @var string template to use for rendering
*/
public $template = 'bootstrap';
/**
* @var string|array files to exclude. NOT IMPLEMENTED YET
*/
public $exclude; // TODO implement
protected function normalizeTargetDir($target)
{
$target = rtrim(Yii::getAlias($target), '\\/');
if (file_exists($target)) {
if (is_dir($target) && !$this->confirm('TargetDirectory already exists. Overwrite?')) {
$this->stderr('User aborted.' . PHP_EOL);
return false;
}
if (is_file($target)) {
$this->stderr("Error: Target directory \"$target\" is a file!" . PHP_EOL);
return false;
}
} else {
mkdir($target, 0777, true);
}
return $target;
}
protected function searchFiles($sourceDirs)
{
$this->stdout('Searching files to process... ');
$files = [];
foreach($sourceDirs as $source) {
foreach($this->findFiles($source) as $fileName) {
$files[$fileName] = $fileName;
}
}
$this->stdout('done.' . PHP_EOL, Console::FG_GREEN);
if (empty($files)) {
$this->stderr('Error: No files found to process.' . PHP_EOL);
return 1;
}
return $files;
}
protected abstract function findFiles($dir);
protected function loadContext($location)
{
$context = new Context();
$cacheFile = $location . '/cache/apidoc.data';
$this->stdout('Loading apidoc data from cache... ');
if (file_exists($cacheFile)) {
$context = unserialize(file_get_contents($cacheFile));
$this->stdout('done.' . PHP_EOL, Console::FG_GREEN);
} else {
$this->stdout('no data available.' . PHP_EOL, Console::FG_YELLOW);
}
return $context;
}
protected function storeContext($context, $location)
{
$cacheFile = $location . '/cache/apidoc.data';
if (!is_dir($dir = dirname($cacheFile))) {
mkdir($dir, 0777, true);
}
file_put_contents($cacheFile, serialize($context));
}
/**
* @param Context $context
*/
protected function updateContext($context)
{
$this->stdout('Updating cross references and backlinks... ');
$context->updateReferences();
$this->stdout('done.' . PHP_EOL, Console::FG_GREEN);
}
/**
* @return BaseRenderer
*/
protected abstract function findRenderer($template);
/**
* @inheritdoc
*/
public function globalOptions()
{
return array_merge(parent::globalOptions(), ['template', 'exclude']);
}
}
<?php
/**
* @author Carsten Brandt <mail@cebe.cc>
*/
namespace yii\apidoc\commands;
use yii\apidoc\models\Context;
use yii\apidoc\renderers\BaseRenderer;
use yii\apidoc\renderers\GuideRenderer;
use yii\helpers\Console;
use yii\helpers\FileHelper;
use Yii;
/**
* This command can render documentation stored as markdown files such as the yii guide
* or your own applications documentation setup.
*
*/
class GuideController extends BaseController
{
/**
* @var string path or URL to the api docs to allow links to classes and properties/methods.
*/
public $apiDocs;
/**
* Renders API documentation files
* @param array $sourceDirs
* @param string $targetDir
* @return int
*/
public function actionIndex(array $sourceDirs, $targetDir)
{
$renderer = $this->findRenderer($this->template);
$targetDir = $this->normalizeTargetDir($targetDir);
if ($targetDir === false || $renderer === false) {
return 1;
}
// setup reference to apidoc
if ($this->apiDocs !== null) {
$renderer->apiUrl = $this->apiDocs;
$renderer->apiContext = $this->loadContext($this->apiDocs);
$this->updateContext($renderer->apiContext); // TODO autodetect API docs in same folder
} else {
$renderer->apiContext = new Context();
}
// search for files to process
$files = $this->searchFiles($sourceDirs);
$renderer->controller = $this;
$renderer->render($files, $targetDir);
$this->stdout('Publishing images...');
foreach($sourceDirs as $source) {
FileHelper::copyDirectory(rtrim($source, '/\\') . '/images', $targetDir . '/images');
}
$this->stdout('done.' . PHP_EOL, Console::FG_GREEN);
// TODO generate api references.txt
}
protected function findFiles($path, $except = ['README.md'])
{
$path = FileHelper::normalizePath($path);
$options = [
'only' => ['*.md'],
'except' => $except,
];
return FileHelper::findFiles($path, $options);
}
/**
* @return GuideRenderer
*/
protected function findRenderer($template)
{
$rendererClass = 'yii\\apidoc\\templates\\' . $template . '\\GuideRenderer';
if (!class_exists($rendererClass)) {
$this->stderr('Renderer not found.' . PHP_EOL);
return false;
}
return new $rendererClass();
}
}
\ No newline at end of file
...@@ -11,7 +11,7 @@ use cebe\markdown\GithubMarkdown; ...@@ -11,7 +11,7 @@ use cebe\markdown\GithubMarkdown;
use phpDocumentor\Reflection\DocBlock\Type\Collection; use phpDocumentor\Reflection\DocBlock\Type\Collection;
use yii\apidoc\models\MethodDoc; use yii\apidoc\models\MethodDoc;
use yii\apidoc\models\TypeDoc; use yii\apidoc\models\TypeDoc;
use yii\apidoc\templates\BaseRenderer; use yii\apidoc\renderers\BaseRenderer;
use yii\helpers\Inflector; use yii\helpers\Inflector;
use yii\helpers\Markdown; use yii\helpers\Markdown;
...@@ -35,7 +35,7 @@ class ApiMarkdown extends GithubMarkdown ...@@ -35,7 +35,7 @@ class ApiMarkdown extends GithubMarkdown
parent::prepare(); parent::prepare();
// add references to guide pages // add references to guide pages
$this->references = array_merge($this->references, static::$renderer->getGuideReferences()); $this->references = array_merge($this->references, static::$renderer->guideReferences);
} }
/** /**
...@@ -140,9 +140,9 @@ class ApiMarkdown extends GithubMarkdown ...@@ -140,9 +140,9 @@ class ApiMarkdown extends GithubMarkdown
// Collection resolves relative types // Collection resolves relative types
$typeName = (new Collection([$typeName], $context->phpDocContext))->__toString(); $typeName = (new Collection([$typeName], $context->phpDocContext))->__toString();
} }
$type = static::$renderer->context->getType($typeName); $type = static::$renderer->apiContext->getType($typeName);
if ($type === null) { if ($type === null) {
static::$renderer->context->errors[] = [ static::$renderer->apiContext->errors[] = [
'file' => ($context !== null) ? $context->sourceFile : null, 'file' => ($context !== null) ? $context->sourceFile : null,
'message' => 'broken link to ' . $typeName . '::' . $subjectName . (($context !== null) ? ' in ' . $context->name : ''), 'message' => 'broken link to ' . $typeName . '::' . $subjectName . (($context !== null) ? ' in ' . $context->name : ''),
]; ];
...@@ -159,11 +159,11 @@ class ApiMarkdown extends GithubMarkdown ...@@ -159,11 +159,11 @@ class ApiMarkdown extends GithubMarkdown
} }
} }
return [ return [
static::$renderer->subjectLink($subject, $title), static::$renderer->createSubjectLink($subject, $title),
$offset $offset
]; ];
} else { } else {
static::$renderer->context->errors[] = [ static::$renderer->apiContext->errors[] = [
'file' => ($context !== null) ? $context->sourceFile : null, 'file' => ($context !== null) ? $context->sourceFile : null,
'message' => 'broken link to ' . $type->name . '::' . $subjectName . (($context !== null) ? ' in ' . $context->name : ''), 'message' => 'broken link to ' . $type->name . '::' . $subjectName . (($context !== null) ? ' in ' . $context->name : ''),
]; ];
...@@ -175,7 +175,7 @@ class ApiMarkdown extends GithubMarkdown ...@@ -175,7 +175,7 @@ class ApiMarkdown extends GithubMarkdown
} }
} elseif ($context !== null && ($subject = $context->findSubject($object)) !== null) { } elseif ($context !== null && ($subject = $context->findSubject($object)) !== null) {
return [ return [
static::$renderer->subjectLink($subject, $title), static::$renderer->createSubjectLink($subject, $title),
$offset $offset
]; ];
} }
...@@ -183,13 +183,13 @@ class ApiMarkdown extends GithubMarkdown ...@@ -183,13 +183,13 @@ class ApiMarkdown extends GithubMarkdown
// Collection resolves relative types // Collection resolves relative types
$object = (new Collection([$object], $context->phpDocContext))->__toString(); $object = (new Collection([$object], $context->phpDocContext))->__toString();
} }
if (($type = static::$renderer->context->getType($object)) !== null) { if (($type = static::$renderer->apiContext->getType($object)) !== null) {
return [ return [
static::$renderer->typeLink($type, $title), static::$renderer->createTypeLink($type, null, $title),
$offset $offset
]; ];
} }
static::$renderer->context->errors[] = [ static::$renderer->apiContext->errors[] = [
'file' => ($context !== null) ? $context->sourceFile : null, 'file' => ($context !== null) ? $context->sourceFile : null,
'message' => 'broken link to ' . $object . (($context !== null) ? ' in ' . $context->name : ''), 'message' => 'broken link to ' . $object . (($context !== null) ? ' in ' . $context->name : ''),
]; ];
...@@ -228,7 +228,7 @@ class ApiMarkdown extends GithubMarkdown ...@@ -228,7 +228,7 @@ class ApiMarkdown extends GithubMarkdown
} }
if (is_string($context)) { if (is_string($context)) {
$context = static::$renderer->context->getType($context); $context = static::$renderer->apiContext->getType($context);
} }
Markdown::$flavors['api']->context = $context; Markdown::$flavors['api']->context = $context;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
namespace yii\apidoc\templates; namespace yii\apidoc\renderers;
use Yii; use Yii;
use yii\apidoc\models\ClassDoc; use yii\apidoc\models\ClassDoc;
...@@ -25,48 +25,13 @@ use yii\console\Controller; ...@@ -25,48 +25,13 @@ use yii\console\Controller;
* @author Carsten Brandt <mail@cebe.cc> * @author Carsten Brandt <mail@cebe.cc>
* @since 2.0 * @since 2.0
*/ */
abstract class BaseRenderer extends Component abstract class ApiRenderer extends BaseRenderer
{ {
/** /**
* @var Context the [[Context]] currently being rendered.
*/
public $context;
/**
* @var array files for guide pages
*/
public $markDownFiles = [];
/**
* Renders a given [[Context]]. * Renders a given [[Context]].
* *
* @param Context $context the api documentation context to render. * @param Context $context the api documentation context to render.
* @param Controller $controller the apidoc controller instance. Can be used to control output. * @param $targetDir
*/
public abstract function renderApi($context, $controller);
/**
* Renders a given [[Context]].
*
* @param array $files list of markdown files to render
* @param Context $context the api documentation context to render.
* @param Controller $controller the apidoc controller instance. Can be used to control output.
* @return
*/
public abstract function renderMarkdownFiles($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); public abstract function render($context, $targetDir);
} }
\ No newline at end of file
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\apidoc\renderers;
use Yii;
use yii\apidoc\helpers\ApiMarkdown;
use yii\apidoc\models\BaseDoc;
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\apidoc\models\TypeDoc;
use yii\base\Component;
use yii\console\Controller;
use yii\helpers\Html;
/**
* Base class for all documentation renderers
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
abstract class BaseRenderer extends Component
{
public $apiUrl;
/**
* @var Context the [[Context]] currently being rendered.
*/
public $apiContext;
/**
* @var Controller the apidoc controller instance. Can be used to control output.
*/
public $controller;
public $guideUrl;
public $guideReferences = [];
public function init()
{
ApiMarkdown::$renderer = $this;
}
/**
* creates a link to a type (class, interface or trait)
* @param ClassDoc|InterfaceDoc|TraitDoc|ClassDoc[]|InterfaceDoc[]|TraitDoc[] $types
* @param string $title a title to be used for the link TODO check whether [[yii\...|Class]] is supported
* @param BaseDoc $context
* @return string
*/
public function createTypeLink($types, $context = null, $title = null)
{
if (!is_array($types)) {
$types = [$types];
}
if (count($types) > 1) {
$title = null;
}
$links = [];
foreach($types as $type) {
$postfix = '';
if (!is_object($type)) {
if (substr($type, -2, 2) == '[]') {
$postfix = '[]';
$type = substr($type, 0, -2);
}
if (($t = $this->apiContext->getType(ltrim($type, '\\'))) !== null) {
$type = $t;
} elseif ($type[0] !== '\\' && ($t = $this->apiContext->getType($this->resolveNamespace($context) . '\\' . ltrim($type, '\\'))) !== null) {
$type = $t;
} else {
ltrim($type, '\\');
}
}
if (!is_object($type)) {
$links[] = $type;
} else {
$linkText = $type->name;
if ($title !== null) {
$linkText = $title;
}
$links[] = $this->generateLink($linkText, $this->generateApiUrl($type->name)) . $postfix;
}
}
return implode('|', $links);
}
/**
* creates a link to a subject
* @param PropertyDoc|MethodDoc|ConstDoc|EventDoc $subject
* @param string $title
* @return string
*/
public function createSubjectLink($subject, $title = null)
{
if ($title === null) {
if ($subject instanceof MethodDoc) {
$title = $subject->name . '()';
} else {
$title = $subject->name;
}
}
if (($type = $this->apiContext->getType($subject->definedBy)) === null) {
return $subject->name;
} else {
$link = $this->generateApiUrl($type->name);
if ($subject instanceof MethodDoc) {
$link .= '#' . $subject->name . '()';
} else {
$link .= '#' . $subject->name;
}
$link .= '-detail';
return Html::a($title, null, ['href' => $link]);
}
}
/**
* @param BaseDoc $context
*/
private function resolveNamespace($context)
{
// TODO use phpdoc Context for this
if ($context === null) {
return '';
}
if ($context instanceof TypeDoc) {
return $context->namespace;
}
if ($context->hasProperty('definedBy')) {
$type = $this->apiContext->getType($context);
if ($type !== null) {
return $type->namespace;
}
}
return '';
}
/**
* generate link markup
* @param $text
* @param $href
* @return mixed
*/
protected abstract function generateLink($text, $href);
/**
* Generate an url to a type in apidocs
* @param $typeName
* @return mixed
*/
public abstract function generateApiUrl($typeName);
}
\ No newline at end of file
...@@ -5,18 +5,34 @@ ...@@ -5,18 +5,34 @@
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
namespace yii\apidoc\templates\offline; namespace yii\apidoc\renderers;
use Yii; 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;
/** /**
* Base class for all Guide documentation renderers
* *
* @author Carsten Brandt <mail@cebe.cc> * @author Carsten Brandt <mail@cebe.cc>
* @since 2.0 * @since 2.0
*/ */
class Renderer extends \yii\apidoc\templates\html\Renderer abstract class GuideRenderer extends BaseRenderer
{ {
public $apiLayout = '@yii/apidoc/templates/offline/views/offline.php'; /**
public $indexView = '@yii/apidoc/templates/offline/views/index.php'; * Render markdown files
*
* @param array $files list of markdown files to render
* @param $targetDir
*/
public abstract function render($files, $targetDir);
public $pageTitle = 'Yii Framework 2.0 API Documentation';
} }
\ No newline at end of file
...@@ -7,26 +7,29 @@ ...@@ -7,26 +7,29 @@
namespace yii\apidoc\templates\bootstrap; namespace yii\apidoc\templates\bootstrap;
use yii\apidoc\helpers\ApiMarkdown; use yii\apidoc\helpers\ApiMarkdown;
use yii\apidoc\models\ClassDoc;
use yii\apidoc\models\ConstDoc;
use yii\apidoc\models\Context; 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\console\Controller; use yii\console\Controller;
use Yii; use Yii;
use yii\helpers\Console; use yii\helpers\Console;
use yii\helpers\Html;
/** /**
* *
* @author Carsten Brandt <mail@cebe.cc> * @author Carsten Brandt <mail@cebe.cc>
* @since 2.0 * @since 2.0
*/ */
class Renderer extends \yii\apidoc\templates\html\Renderer class ApiRenderer extends \yii\apidoc\templates\html\ApiRenderer
{ {
public $apiLayout = '@yii/apidoc/templates/bootstrap/layouts/api.php'; public $layout = '@yii/apidoc/templates/bootstrap/layouts/api.php';
public $guideLayout = '@yii/apidoc/templates/bootstrap/layouts/guide.php';
public $indexView = '@yii/apidoc/templates/bootstrap/views/index.php'; public $indexView = '@yii/apidoc/templates/bootstrap/views/index.php';
public $pageTitle = 'Yii Framework 2.0 Documentation';
public $guideUrl;
public $extensions = [ public $extensions = [
'apidoc', 'apidoc',
'authclient', 'authclient',
...@@ -48,35 +51,60 @@ class Renderer extends \yii\apidoc\templates\html\Renderer ...@@ -48,35 +51,60 @@ class Renderer extends \yii\apidoc\templates\html\Renderer
]; ];
/** /**
* Renders a given [[Context]]. * @inheritdoc
*
* @param Context $context the api documentation context to render.
* @param Controller $controller the apidoc controller instance. Can be used to control output.
*/ */
public function renderApi($context, $controller) public function render($context, $targetDir)
{ {
parent::renderApi($context, $controller);
$dir = Yii::getAlias($this->targetDir);
$types = array_merge($context->classes, $context->interfaces, $context->traits); $types = array_merge($context->classes, $context->interfaces, $context->traits);
$controller->stdout('generating extension index files...'); $extTypes = [];
foreach($this->extensions as $ext) { foreach($this->extensions as $k => $ext) {
$extType = $this->filterTypes($types, $ext);
if (empty($extType)) {
unset($this->extensions[$k]);
continue;
}
$extTypes[$ext] = $extType;
}
// render view files
parent::render($context, $targetDir);
if ($this->controller !== null) {
$this->controller->stdout('generating extension index files...');
}
foreach($extTypes as $ext => $extType) {
$readme = @file_get_contents("https://raw.github.com/yiisoft/yii2-$ext/master/README.md"); $readme = @file_get_contents("https://raw.github.com/yiisoft/yii2-$ext/master/README.md");
$indexFileContent = $this->renderWithLayout($this->indexView, [ $indexFileContent = $this->renderWithLayout($this->indexView, [
'docContext' => $context, 'docContext' => $context,
'types' => $this->filterTypes($types, $ext), 'types' => $extType,
'readme' => $readme ?: null,
]);
file_put_contents($targetDir . "/ext-{$ext}-index.html", $indexFileContent);
}
$yiiTypes = $this->filterTypes($types, 'yii');
if (empty($yiiTypes)) {
// $readme = @file_get_contents("https://raw.github.com/yiisoft/yii2-framework/master/README.md");
$indexFileContent = $this->renderWithLayout($this->indexView, [
'docContext' => $context,
'types' => $this->filterTypes($types, 'app'),
'readme' => null,
]);
} else {
$readme = @file_get_contents("https://raw.github.com/yiisoft/yii2-framework/master/README.md");
$indexFileContent = $this->renderWithLayout($this->indexView, [
'docContext' => $context,
'types' => $yiiTypes,
'readme' => $readme ?: null, 'readme' => $readme ?: null,
]); ]);
file_put_contents($dir . "/ext_{$ext}_index.html", $indexFileContent);
} }
$readme = @file_get_contents("https://raw.github.com/yiisoft/yii2-framework/master/README.md"); file_put_contents($targetDir . '/index.html', $indexFileContent);
$indexFileContent = $this->renderWithLayout($this->indexView, [
'docContext' => $context, if ($this->controller !== null) {
'types' => $this->filterTypes($types, 'yii'), $this->controller->stdout('done.' . PHP_EOL, Console::FG_GREEN);
'readme' => $readme ?: null, }
]);
file_put_contents($dir . '/index.html', $indexFileContent);
$controller->stdout('done.' . PHP_EOL, Console::FG_GREEN);
} }
public function getNavTypes($type, $types) public function getNavTypes($type, $types)
...@@ -130,77 +158,4 @@ class Renderer extends \yii\apidoc\templates\html\Renderer ...@@ -130,77 +158,4 @@ class Renderer extends \yii\apidoc\templates\html\Renderer
} }
return $types; return $types;
} }
/**
* Renders a given [[Context]].
*
* @param Controller $controller the apidoc controller instance. Can be used to control output.
*/
public function renderMarkdownFiles($controller)
{
$files = $this->markDownFiles;
$dir = Yii::getAlias($this->targetDir);
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
ApiMarkdown::$renderer = $this;
$fileCount = count($files) + 1;
Console::startProgress(0, $fileCount, 'Rendering markdown files: ', false);
$done = 0;
$fileData = [];
$headlines = [];
foreach($files as $file) {
$fileData[$file] = file_get_contents($file);
if (basename($file) == 'index.md') {
continue; // to not add index file to nav
}
if (preg_match("/^(.*)\n=+/", $fileData[$file], $matches)) {
$headlines[$file] = $matches[1];
} else {
$headlines[$file] = basename($file);
}
}
foreach($fileData as $file => $content) {
$output = ApiMarkdown::process($content); // TODO generate links to yiiframework.com by default
$output = $this->fixMarkdownLinks($output);
if ($this->guideLayout !== false) {
$params = [
'headlines' => $headlines,
'currentFile' => $file,
'content' => $output,
];
$output = $this->getView()->renderFile($this->guideLayout, $params, $this);
}
$fileName = $this->generateGuideFileName($file);
file_put_contents($dir . '/' . $fileName, $output);
Console::updateProgress(++$done, $fileCount);
}
Console::updateProgress(++$done, $fileCount);
Console::endProgress(true);
$controller->stdout('done.' . PHP_EOL, Console::FG_GREEN);
}
protected function generateGuideFileName($file)
{
return 'guide_' . basename($file, '.md') . '.html';
}
public function getGuideReferences()
{
$refs = [];
foreach($this->markDownFiles as $file) {
$refName = 'guide-' . basename($file, '.md');
$refs[$refName] = ['url' => $this->generateGuideFileName($file)];
}
return $refs;
}
protected function fixMarkdownLinks($content)
{
$content = preg_replace('/href\s*=\s*"([^"\/]+)\.md(#.*)?"/i', 'href="guide_\1.html\2"', $content);
return $content;
}
} }
\ No newline at end of file
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\apidoc\templates\bootstrap;
use yii\apidoc\helpers\ApiMarkdown;
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\console\Controller;
use Yii;
use yii\helpers\Console;
use yii\helpers\Html;
/**
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class GuideRenderer extends \yii\apidoc\templates\html\GuideRenderer
{
public $layout = '@yii/apidoc/templates/bootstrap/layouts/guide.php';
public $extensions = [
'apidoc',
'authclient',
'bootstrap',
'codeception',
'composer',
'debug',
'elasticsearch',
'faker',
'gii',
'imagine',
'jui',
'mongodb',
'redis',
'smarty',
'sphinx',
'swiftmailer',
'twig',
];
//
// /**
// * Renders a given [[Context]].
// *
// * @param Controller $controller the apidoc controller instance. Can be used to control output.
// */
// public function renderMarkdownFiles($controller)
// {
// $files = $this->markDownFiles;
// $dir = Yii::getAlias($this->targetDir);
// if (!is_dir($dir)) {
// mkdir($dir, 0777, true);
// }
//
// ApiMarkdown::$renderer = $this;
//
// $fileCount = count($files) + 1;
// Console::startProgress(0, $fileCount, 'Rendering markdown files: ', false);
// $done = 0;
// $fileData = [];
// $headlines = [];
// foreach($files as $file) {
// $fileData[$file] = file_get_contents($file);
// if (basename($file) == 'index.md') {
// continue; // to not add index file to nav
// }
// if (preg_match("/^(.*)\n=+/", $fileData[$file], $matches)) {
// $headlines[$file] = $matches[1];
// } else {
// $headlines[$file] = basename($file);
// }
// }
//
// foreach($fileData as $file => $content) {
// $output = ApiMarkdown::process($content); // TODO generate links to yiiframework.com by default
// $output = $this->fixMarkdownLinks($output);
// if ($this->guideLayout !== false) {
// $params = [
// 'headlines' => $headlines,
// 'currentFile' => $file,
// 'content' => $output,
// ];
// $output = $this->getView()->renderFile($this->guideLayout, $params, $this);
// }
// $fileName = $this->generateGuideFileName($file);
// file_put_contents($dir . '/' . $fileName, $output);
// Console::updateProgress(++$done, $fileCount);
// }
// Console::updateProgress(++$done, $fileCount);
// Console::endProgress(true);
// $controller->stdout('done.' . PHP_EOL, Console::FG_GREEN);
// }
//
}
\ No newline at end of file
<?php <?php
use yii\apidoc\templates\bootstrap\ApiRenderer;
use yii\apidoc\templates\bootstrap\SideNavWidget; use yii\apidoc\templates\bootstrap\SideNavWidget;
use yii\helpers\StringHelper; use yii\helpers\StringHelper;
/** /**
* @var yii\web\View $this * @var yii\web\View $this
* @var string $content
*/ */
/** @var ApiRenderer $renderer */
$renderer = $this->context;
$this->beginContent('@yii/apidoc/templates/bootstrap/layouts/main.php'); ?> $this->beginContent('@yii/apidoc/templates/bootstrap/layouts/main.php'); ?>
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-2">
<?php <?php
$types = $this->context->getNavTypes(isset($type) ? $type : null, $types); $types = $renderer->getNavTypes(isset($type) ? $type : null, $types);
ksort($types); ksort($types);
$nav = []; $nav = [];
foreach($types as $i=>$class) { foreach($types as $i=>$class) {
...@@ -28,7 +33,7 @@ $this->beginContent('@yii/apidoc/templates/bootstrap/layouts/main.php'); ?> ...@@ -28,7 +33,7 @@ $this->beginContent('@yii/apidoc/templates/bootstrap/layouts/main.php'); ?>
} }
$nav[$namespace]['items'][] = [ $nav[$namespace]['items'][] = [
'label' => StringHelper::basename($class->name), 'label' => StringHelper::basename($class->name),
'url' => './' . $this->context->generateUrl($class->name), 'url' => './' . $renderer->generateApiUrl($class->name),
'active' => isset($type) && ($class->name == $type->name), 'active' => isset($type) && ($class->name == $type->name),
]; ];
} ?> } ?>
......
...@@ -3,6 +3,7 @@ use yii\apidoc\templates\bootstrap\SideNavWidget; ...@@ -3,6 +3,7 @@ use yii\apidoc\templates\bootstrap\SideNavWidget;
/** /**
* @var yii\web\View $this * @var yii\web\View $this
* @var string $content
*/ */
$this->beginContent('@yii/apidoc/templates/bootstrap/layouts/main.php'); ?> $this->beginContent('@yii/apidoc/templates/bootstrap/layouts/main.php'); ?>
......
...@@ -45,18 +45,21 @@ $this->beginPage(); ...@@ -45,18 +45,21 @@ $this->beginPage();
'renderInnerContainer' => false, 'renderInnerContainer' => false,
'view' => $this, 'view' => $this,
]); ]);
$extItems = [];
foreach($this->context->extensions as $ext) {
$extItems[] = [
'label' => $ext,
'url' => "./ext_{$ext}_index.html",
];
}
$nav = [ $nav = [
['label' => 'Class reference', 'url' => './index.html'], ['label' => 'Class reference', 'url' => './index.html'],
// ['label' => 'Application API', 'url' => '/site/about'],
['label' => 'Extensions', 'items' => $extItems],
]; ];
if (!empty($this->context->extensions))
{
$extItems = [];
foreach($this->context->extensions as $ext) {
$extItems[] = [
'label' => $ext,
'url' => "./ext_{$ext}_index.html",
];
}
$nav[] = ['label' => 'Extensions', 'items' => $extItems];
}
if ($this->context->guideUrl !== null) { if ($this->context->guideUrl !== null) {
$nav[] = ['label' => 'Guide', 'url' => $this->context->guideUrl . 'guide_index.html']; $nav[] = ['label' => 'Guide', 'url' => $this->context->guideUrl . 'guide_index.html'];
} }
......
...@@ -6,8 +6,11 @@ use yii\apidoc\models\TraitDoc; ...@@ -6,8 +6,11 @@ use yii\apidoc\models\TraitDoc;
/** /**
* @var ClassDoc[]|InterfaceDoc[]|TraitDoc[] $types * @var ClassDoc[]|InterfaceDoc[]|TraitDoc[] $types
* @var yii\web\View $this * @var yii\web\View $this
* @var \yii\apidoc\templates\html\ApiRenderer $renderer
*/ */
$renderer = $this->context;
if (isset($readme)) { if (isset($readme)) {
echo \yii\apidoc\helpers\ApiMarkdown::process($readme); echo \yii\apidoc\helpers\ApiMarkdown::process($readme);
} }
...@@ -29,7 +32,7 @@ ksort($types); ...@@ -29,7 +32,7 @@ ksort($types);
foreach($types as $i=>$class): foreach($types as $i=>$class):
?> ?>
<tr> <tr>
<td><?= $this->context->typeLink($class, $class->name) ?></td> <td><?= $renderer->createTypeLink($class, $class, $class->name) ?></td>
<td><?= \yii\apidoc\helpers\ApiMarkdown::process($class->shortDescription, $class, true) ?></td> <td><?= \yii\apidoc\helpers\ApiMarkdown::process($class->shortDescription, $class, true) ?></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\apidoc\templates\html;
use yii\apidoc\helpers\ApiMarkdown;
use yii\console\Controller;
use yii\helpers\Console;
use yii\apidoc\renderers\GuideRenderer as BaseGuideRenderer;
use Yii;
use yii\helpers\Html;
use yii\web\AssetManager;
use yii\web\View;
/**
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
abstract class GuideRenderer extends BaseGuideRenderer
{
public $pageTitle;
public $layout;
/**
* @var View
*/
private $_view;
private $_targetDir;
public function init()
{
parent::init();
if ($this->pageTitle === null) {
$this->pageTitle = 'Yii Framework 2.0 API Documentation'; // TODO guess page title
}
}
/**
* @return View the view instance
*/
public function getView()
{
if ($this->_view === null) {
$this->_view = new View();
$assetPath = Yii::getAlias($this->_targetDir) . '/assets';
if (!is_dir($assetPath)) {
mkdir($assetPath);
}
$this->_view->assetManager = new AssetManager([
'basePath' => $assetPath,
'baseUrl' => './assets',
]);
}
return $this->_view;
}
/**
* Renders a given [[Context]].
*
* @param Controller $controller the apidoc controller instance. Can be used to control output.
*/
public function render($files, $targetDir)
{
$this->_targetDir = $targetDir;
$fileCount = count($files) + 1;
if ($this->controller !== null) {
Console::startProgress(0, $fileCount, 'Rendering markdown files: ', false);
}
$done = 0;
$fileData = [];
$headlines = [];
foreach($files as $file) {
$fileData[$file] = file_get_contents($file);
if (basename($file) == 'index.md') {
continue; // to not add index file to nav
}
if (preg_match("/^(.*)\n=+/", $fileData[$file], $matches)) {
$headlines[$file] = $matches[1];
} else {
$headlines[$file] = basename($file);
}
}
foreach($fileData as $file => $content) {
$output = ApiMarkdown::process($content); // TODO generate links to yiiframework.com by default
$output = $this->fixMarkdownLinks($output);
if ($this->layout !== false) {
$params = [
'headlines' => $headlines,
'currentFile' => $file,
'content' => $output,
];
$output = $this->getView()->renderFile($this->layout, $params, $this);
}
$fileName = $this->generateGuideFileName($file);
file_put_contents($targetDir . '/' . $fileName, $output);
if ($this->controller !== null) {
Console::updateProgress(++$done, $fileCount);
}
}
if ($this->controller !== null) {
Console::updateProgress(++$done, $fileCount);
Console::endProgress(true);
$this->controller->stdout('done.' . PHP_EOL, Console::FG_GREEN);
}
}
// TODO move these to guide renderer
protected function generateGuideFileName($file)
{
return 'guide_' . basename($file, '.md') . '.html';
}
public function getGuideReferences()
{
// TODO implement for api docs
// $refs = [];
// foreach($this->markDownFiles as $file) {
// $refName = 'guide-' . basename($file, '.md');
// $refs[$refName] = ['url' => $this->generateGuideFileName($file)];
// }
// return $refs;
}
protected function fixMarkdownLinks($content)
{
$content = preg_replace('/href\s*=\s*"([^"\/]+)\.md(#.*)?"/i', 'href="guide_\1.html\2"', $content);
return $content;
}
/**
* generate link markup
* @param $text
* @param $href
* @return mixed
*/
protected function generateLink($text, $href)
{
return Html::a($text, null, ['href' => $href]);
}
/**
* Generate an url to a type in apidocs
* @param $typeName
* @return mixed
*/
public function generateApiUrl($typeName)
{
// TODO: Implement generateApiUrl() method.
return $this->apiUrl . '...';
}
}
\ No newline at end of file
The html API doc template The html API doc template
------------------------- =========================
This templates provides view files and a Renderer class that can be reused in other html templates. This templates provides view files and a Renderer class that can be reused in other html templates.
\ No newline at end of file
...@@ -7,8 +7,11 @@ use yii\helpers\ArrayHelper; ...@@ -7,8 +7,11 @@ use yii\helpers\ArrayHelper;
/** /**
* @var ClassDoc $type * @var ClassDoc $type
* @var yii\web\View $this * @var yii\web\View $this
* @var \yii\apidoc\templates\html\ApiRenderer $renderer
*/ */
$renderer = $this->context;
if (empty($type->constants)) { if (empty($type->constants)) {
return; return;
} }
...@@ -34,7 +37,7 @@ ArrayHelper::multisort($constants, 'name'); ...@@ -34,7 +37,7 @@ ArrayHelper::multisort($constants, 'name');
<td><?= $constant->name ?><a name="<?= $constant->name ?>-detail"></a></td> <td><?= $constant->name ?><a name="<?= $constant->name ?>-detail"></a></td>
<td><?= $constant->value ?></td> <td><?= $constant->value ?></td>
<td><?= APiMarkdown::process($constant->shortDescription . "\n" . $constant->description, $constant->definedBy, true) ?></td> <td><?= APiMarkdown::process($constant->shortDescription . "\n" . $constant->description, $constant->definedBy, true) ?></td>
<td><?= $this->context->typeLink($constant->definedBy) ?></td> <td><?= $renderer->createTypeLink($constant->definedBy) ?></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</table> </table>
......
...@@ -7,8 +7,11 @@ use yii\helpers\ArrayHelper; ...@@ -7,8 +7,11 @@ use yii\helpers\ArrayHelper;
/** /**
* @var ClassDoc $type * @var ClassDoc $type
* @var yii\web\View $this * @var yii\web\View $this
* @var \yii\apidoc\templates\html\ApiRenderer $renderer
*/ */
$renderer = $this->context;
if (empty($type->events)) { if (empty($type->events)) {
return; return;
} }
...@@ -31,15 +34,15 @@ ArrayHelper::multisort($events, 'name'); ...@@ -31,15 +34,15 @@ ArrayHelper::multisort($events, 'name');
</tr> </tr>
<?php foreach($events as $event): ?> <?php foreach($events as $event): ?>
<tr<?= $event->definedBy != $type->name ? ' class="inherited"' : '' ?> id="<?= $event->name ?>"> <tr<?= $event->definedBy != $type->name ? ' class="inherited"' : '' ?> id="<?= $event->name ?>">
<td><?= $this->context->subjectLink($event) ?></td> <td><?= $renderer->createSubjectLink($event) ?></td>
<td><?= $this->context->typeLink($event->types) ?></td> <td><?= $renderer->createTypeLink($event->types) ?></td>
<td> <td>
<?= ApiMarkdown::process($event->shortDescription, $event->definedBy, true) ?> <?= ApiMarkdown::process($event->shortDescription, $event->definedBy, true) ?>
<?php if(!empty($event->since)): ?> <?php if(!empty($event->since)): ?>
(available since version <?php echo $event->since; ?>) (available since version <?php echo $event->since; ?>)
<?php endif; ?> <?php endif; ?>
</td> </td>
<td><?= $this->context->typeLink($event->definedBy) ?></td> <td><?= $renderer->createTypeLink($event->definedBy) ?></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</table> </table>
......
...@@ -8,8 +8,11 @@ use yii\helpers\ArrayHelper; ...@@ -8,8 +8,11 @@ use yii\helpers\ArrayHelper;
/** /**
* @var ClassDoc|TraitDoc $type * @var ClassDoc|TraitDoc $type
* @var yii\web\View $this * @var yii\web\View $this
* @var \yii\apidoc\templates\html\ApiRenderer $renderer
*/ */
$renderer = $this->context;
$methods = $type->getNativeMethods(); $methods = $type->getNativeMethods();
if (empty($methods)) { if (empty($methods)) {
return; return;
...@@ -33,27 +36,27 @@ ArrayHelper::multisort($methods, 'name'); ...@@ -33,27 +36,27 @@ ArrayHelper::multisort($methods, 'name');
<table class="summaryTable table table-striped table-bordered table-hover"> <table class="summaryTable table table-striped table-bordered table-hover">
<tr><td colspan="3"> <tr><td colspan="3">
<div class="signature2"><?= $this->context->renderMethodSignature($method) ?></div> <div class="signature2"><?= $renderer->renderMethodSignature($method) ?></div>
</td></tr> </td></tr>
<?php if(!empty($method->params) || !empty($method->return) || !empty($method->exceptions)): ?> <?php if(!empty($method->params) || !empty($method->return) || !empty($method->exceptions)): ?>
<?php foreach($method->params as $param): ?> <?php foreach($method->params as $param): ?>
<tr> <tr>
<td class="paramNameCol"><?= $param->name ?></td> <td class="paramNameCol"><?= $param->name ?></td>
<td class="paramTypeCol"><?= $this->context->typeLink($param->types) ?></td> <td class="paramTypeCol"><?= $renderer->createTypeLink($param->types) ?></td>
<td class="paramDescCol"><?= ApiMarkdown::process($param->description, $type) ?></td> <td class="paramDescCol"><?= ApiMarkdown::process($param->description, $type) ?></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
<?php if(!empty($method->return)): ?> <?php if(!empty($method->return)): ?>
<tr> <tr>
<td class="paramNameCol"><?= 'return'; ?></td> <td class="paramNameCol"><?= 'return'; ?></td>
<td class="paramTypeCol"><?= $this->context->typeLink($method->returnTypes); ?></td> <td class="paramTypeCol"><?= $renderer->createTypeLink($method->returnTypes); ?></td>
<td class="paramDescCol"><?= ApiMarkdown::process($method->return, $type); ?></td> <td class="paramDescCol"><?= ApiMarkdown::process($method->return, $type); ?></td>
</tr> </tr>
<?php endif; ?> <?php endif; ?>
<?php foreach($method->exceptions as $exception => $description): ?> <?php foreach($method->exceptions as $exception => $description): ?>
<tr> <tr>
<td class="paramNameCol"><?= 'throws' ?></td> <td class="paramNameCol"><?= 'throws' ?></td>
<td class="paramTypeCol"><?= $this->context->typeLink($exception) ?></td> <td class="paramTypeCol"><?= $renderer->createTypeLink($exception) ?></td>
<td class="paramDescCol"><?= ApiMarkdown::process($description, $type) ?></td> <td class="paramDescCol"><?= ApiMarkdown::process($description, $type) ?></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
......
...@@ -10,8 +10,11 @@ use yii\helpers\ArrayHelper; ...@@ -10,8 +10,11 @@ use yii\helpers\ArrayHelper;
* @var ClassDoc|InterfaceDoc|TraitDoc $type * @var ClassDoc|InterfaceDoc|TraitDoc $type
* @var boolean $protected * @var boolean $protected
* @var yii\web\View $this * @var yii\web\View $this
* @var \yii\apidoc\templates\html\ApiRenderer $renderer
*/ */
$renderer = $this->context;
if ($protected && count($type->getProtectedMethods()) == 0 || !$protected && count($type->getPublicMethods()) == 0) { if ($protected && count($type->getProtectedMethods()) == 0 || !$protected && count($type->getPublicMethods()) == 0) {
return; return;
} ?> } ?>
...@@ -36,9 +39,9 @@ ArrayHelper::multisort($methods, 'name'); ...@@ -36,9 +39,9 @@ ArrayHelper::multisort($methods, 'name');
foreach($methods as $method): ?> foreach($methods as $method): ?>
<?php if($protected && $method->visibility == 'protected' || !$protected && $method->visibility != 'protected'): ?> <?php if($protected && $method->visibility == 'protected' || !$protected && $method->visibility != 'protected'): ?>
<tr<?= $method->definedBy != $type->name ? ' class="inherited"' : '' ?> id="<?= $method->name ?>()"> <tr<?= $method->definedBy != $type->name ? ' class="inherited"' : '' ?> id="<?= $method->name ?>()">
<td><?= $this->context->subjectLink($method, $method->name.'()') ?></td> <td><?= $renderer->createSubjectLink($method, $method->name.'()') ?></td>
<td><?= ApiMarkdown::process($method->shortDescription, $method->definedBy, true) ?></td> <td><?= ApiMarkdown::process($method->shortDescription, $method->definedBy, true) ?></td>
<td><?= $this->context->typeLink($method->definedBy, $type) ?></td> <td><?= $renderer->createTypeLink($method->definedBy, $type) ?></td>
</tr> </tr>
<?php endif; ?> <?php endif; ?>
<?php endforeach; ?> <?php endforeach; ?>
......
...@@ -8,8 +8,11 @@ use yii\helpers\ArrayHelper; ...@@ -8,8 +8,11 @@ use yii\helpers\ArrayHelper;
/** /**
* @var ClassDoc|TraitDoc $type * @var ClassDoc|TraitDoc $type
* @var yii\web\View $this * @var yii\web\View $this
* @var \yii\apidoc\templates\html\ApiRenderer $renderer
*/ */
$renderer = $this->context;
$properties = $type->getNativeProperties(); $properties = $type->getNativeProperties();
if (empty($properties)) { if (empty($properties)) {
return; return;
...@@ -33,7 +36,7 @@ ArrayHelper::multisort($properties, 'name'); ...@@ -33,7 +36,7 @@ ArrayHelper::multisort($properties, 'name');
</span> </span>
</div> </div>
<div class="signature"><?php echo $this->context->renderPropertySignature($property); ?></div> <div class="signature"><?php echo $renderer->renderPropertySignature($property); ?></div>
<p><?= ApiMarkdown::process($property->description, $type) ?></p> <p><?= ApiMarkdown::process($property->description, $type) ?></p>
......
...@@ -9,8 +9,11 @@ use yii\helpers\ArrayHelper; ...@@ -9,8 +9,11 @@ use yii\helpers\ArrayHelper;
* @var ClassDoc|TraitDoc $type * @var ClassDoc|TraitDoc $type
* @var boolean $protected * @var boolean $protected
* @var yii\web\View $this * @var yii\web\View $this
* @var \yii\apidoc\templates\html\ApiRenderer $renderer
*/ */
$renderer = $this->context;
if ($protected && count($type->getProtectedProperties()) == 0 || !$protected && count($type->getPublicProperties()) == 0) { if ($protected && count($type->getProtectedProperties()) == 0 || !$protected && count($type->getPublicProperties()) == 0) {
return; return;
} ?> } ?>
...@@ -36,10 +39,10 @@ ArrayHelper::multisort($properties, 'name'); ...@@ -36,10 +39,10 @@ ArrayHelper::multisort($properties, 'name');
foreach($properties as $property): ?> foreach($properties as $property): ?>
<?php if($protected && $property->visibility == 'protected' || !$protected && $property->visibility != 'protected'): ?> <?php if($protected && $property->visibility == 'protected' || !$protected && $property->visibility != 'protected'): ?>
<tr<?= $property->definedBy != $type->name ? ' class="inherited"' : '' ?> id="<?= $property->name ?>"> <tr<?= $property->definedBy != $type->name ? ' class="inherited"' : '' ?> id="<?= $property->name ?>">
<td><?= $this->context->subjectLink($property) ?></td> <td><?= $renderer->createSubjectLink($property) ?></td>
<td><?= $this->context->typeLink($property->types) ?></td> <td><?= $renderer->createTypeLink($property->types) ?></td>
<td><?= ApiMarkdown::process($property->shortDescription, $property->definedBy, true) ?></td> <td><?= ApiMarkdown::process($property->shortDescription, $property->definedBy, true) ?></td>
<td><?= $this->context->typeLink($property->definedBy) ?></td> <td><?= $renderer->createTypeLink($property->definedBy) ?></td>
</tr> </tr>
<?php endif; ?> <?php endif; ?>
<?php endforeach; ?> <?php endforeach; ?>
......
...@@ -7,7 +7,7 @@ use yii\apidoc\models\TraitDoc; ...@@ -7,7 +7,7 @@ use yii\apidoc\models\TraitDoc;
/** /**
* @var ClassDoc|InterfaceDoc|TraitDoc $type * @var ClassDoc|InterfaceDoc|TraitDoc $type
* @var yii\web\View $this * @var yii\web\View $this
* @var \yii\apidoc\templates\html\Renderer $renderer * @var \yii\apidoc\templates\html\ApiRenderer $renderer
*/ */
$renderer = $this->context; $renderer = $this->context;
......
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\apidoc\templates\offline\assets;
use yii\web\View;
/**
* The asset bundle for the offline template.
*
* @author Carsten Brandt <mail@cebe.cc>
* @since 2.0
*/
class AssetBundle extends \yii\web\AssetBundle
{
public $sourcePath = '@yii/apidoc/templates/offline/assets/css';
public $css = [
'api.css',
'style.css',
];
public $depends = [
'yii\web\JqueryAsset',
];
public $jsOptions = [
'position' => View::POS_HEAD,
];
}
pre {
color: #000000;
background-color: #FFF5E6;
font-family: "courier new", "times new roman", monospace;
line-height: 1.3em;
/* Put a nice border around it. */
padding: 1px;
width: 90%;
/* Don't wrap its contents, and show scrollbars. */
/* white-space: nowrap;*/
overflow: auto;
/* Stop after about 24 lines, and just show a scrollbar. */
/* max-height: 24em; */
margin: 5px;
padding-left: 20px;
border: 1px solid #FFE6BF;
border-left: 6px solid #FFE6BF;
}
code {
color: #000000;
background-color: #FFF5E6;
padding: 1px;
}
div.code {
display: none;
color: #000000;
background-color: #FFF5E6;
font-family: "courier new", "times new roman", monospace;
line-height: 1.3em;
/* Put a nice border around it. */
padding: 1px;
width: 90%;
/* Don't wrap its contents, and show scrollbars. */
/* white-space: nowrap;*/
overflow: auto;
/* Stop after about 24 lines, and just show a scrollbar. */
/* max-height: 24em; */
margin: 5px;
padding-left: 20px;
border-left: 6px solid #FFE6BF;
}
table.summaryTable {
background: #E6ECFF;
border-collapse: collapse;
width: 100%;
}
table.summaryTable th, table.summaryTable td {
border: 1px #BFCFFF solid;
padding: 0.2em;
}
table.summaryTable th {
background: #CCD9FF;
text-align: left;
}
#nav {
padding: 3px;
margin: 0 0 10px 0;
border-top: 1px #BFCFFF solid;
}
#classDescription {
padding: 5px;
margin: 10px 0 20px 0;
border-bottom: 1px solid #BFCFFF;
}
.detailHeader {
font-weight: bold;
font-size: 12pt;
margin: 30px 0 5px 0;
border-bottom: 1px solid #BFCFFF;
}
.detailHeaderTag {
font-weight: normal;
font-size: 10pt;
}
.signature, .signature2 {
padding: 3px;
color: #000000;
font-family: "courier new", "times new roman", monospace;
line-height: 1.3em;
}
.signature {
margin: 10px 0 10px 0;
background: #E6ECFF;
border: 1px #BFCFFF solid;
}
.paramNameCol {
width: 12%;
font-weight: bold;
}
.paramTypeCol {
width: 12%;
}
.sourceCode {
margin: 5px 0;
padding:5px;
background:#FFF5E6;
}
\ No newline at end of file
body
{
}
body, div, span, p, input
{
font-family: Verdana, Arial, sans-serif;
font-size: 10pt;
color: #333333;
}
#apiPage {
}
#apiHeader {
padding: 3px;
color: white;
background: #6078BF;
margin-bottom: 5px;
font-weight: bold;
}
#apiHeader a {
color: white;
}
#apiFooter {
margin-top: 5px;
padding: 3px;
border-top: 1px solid #BFCFFF;
text-align: center;
}
<?php
use yii\apidoc\models\ClassDoc;
use yii\apidoc\models\InterfaceDoc;
use yii\apidoc\models\TraitDoc;
/**
* @var ClassDoc[]|InterfaceDoc[]|TraitDoc[] $types
* @var yii\web\View $this
*/
?><h1>Class Reference</h1>
<table class="summaryTable docIndex">
<colgroup>
<col class="col-package" />
<col class="col-class" />
<col class="col-description" />
</colgroup>
<tr>
<th>Class</th>
<th>Description</th>
</tr>
<?php
ksort($types);
foreach($types as $i=>$class):
?>
<tr>
<td><?= $this->context->typeLink($class, $class->name) ?></td>
<td><?= \yii\apidoc\helpers\Markdown::process($class->shortDescription, $class) ?></td>
</tr>
<?php endforeach; ?>
</table>
<?php
/**
* @var yii\web\View $this
*/
\yii\apidoc\templates\offline\assets\AssetBundle::register($this);
$this->beginPage();
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="language" content="en" />
<?php $this->head(); ?>
<title><?php echo $this->context->pageTitle; ?></title>
</head>
<body>
<?php $this->beginBody(); ?>
<div id="apiPage">
<div id="apiHeader">
<a href="http://www.yiiframework.com">Yii Framework</a> v<?php echo Yii::getVersion(); ?> Class Reference
</div><!-- end of header -->
<div id="content">
<?php echo $content; ?>
</div><!-- end of content -->
<div id="apiFooter">
<p>&copy; 2008-2013 by <a href="http://www.yiisoft.com">Yii Software LLC</a></p>
<p>All Rights Reserved.</p>
</div><!-- end of footer -->
<script type="text/javascript">
/*<![CDATA[*/
$("a.toggle").on('click', function() {
var $this = $(this);
if ($this.hasClass('properties-hidden')) {
$this.text($this.text().replace(/Show/,'Hide'));
$this.parents(".summary").find(".inherited").show();
$this.removeClass('properties-hidden');
} else {
$this.text($this.text().replace(/Hide/,'Show'));
$this.parents(".summary").find(".inherited").hide();
$this.addClass('properties-hidden');
}
return false;
});
/*
$(".sourceCode a.show").toggle(function(){
$(this).text($(this).text().replace(/show/,'hide'));
$(this).parents(".sourceCode").find("div.code").show();
},function(){
$(this).text($(this).text().replace(/hide/,'show'));
$(this).parents(".sourceCode").find("div.code").hide();
});
$("a.sourceLink").click(function(){
$(this).attr('target','_blank');
});
*/
/*]]>*/
</script>
</div><!-- end of page -->
<?php $this->endBody(); ?>
</body>
</html>
<?php $this->endPage(); ?>
...@@ -17,24 +17,23 @@ use yii\helpers\Console; ...@@ -17,24 +17,23 @@ use yii\helpers\Console;
* @author Carsten Brandt <mail@cebe.cc> * @author Carsten Brandt <mail@cebe.cc>
* @since 2.0 * @since 2.0
*/ */
class Renderer extends \yii\apidoc\templates\html\Renderer class ApiRenderer extends \yii\apidoc\templates\html\ApiRenderer
{ {
public $apiLayout = false; public $layout = false;
public $indexView = '@yii/apidoc/templates/online/views/index.php'; public $indexView = '@yii/apidoc/templates/online/views/index.php';
public $pageTitle = 'Yii Framework 2.0 API Documentation'; public $pageTitle = 'Yii Framework 2.0 API Documentation';
/** /**
* Renders a given [[Context]]. * @inheritdoc
*
* @param Context $context the api documentation context to render.
* @param Controller $controller the apidoc controller instance. Can be used to control output.
*/ */
public function renderApi($context, $controller) public function render($context, $targetDir)
{ {
parent::renderApi($context, $controller); parent::render($context, $targetDir);
$dir = Yii::getAlias($this->targetDir);
$controller->stdout("writing packages file..."); if ($this->controller !== null) {
$this->controller->stdout("writing packages file...");
}
$packages = []; $packages = [];
$notNamespaced = []; $notNamespaced = [];
foreach(array_merge($context->classes, $context->interfaces, $context->traits) as $type) { foreach(array_merge($context->classes, $context->interfaces, $context->traits) as $type) {
...@@ -50,17 +49,19 @@ class Renderer extends \yii\apidoc\templates\html\Renderer ...@@ -50,17 +49,19 @@ class Renderer extends \yii\apidoc\templates\html\Renderer
foreach($packages as $name => $classes) { foreach($packages as $name => $classes) {
sort($packages[$name]); sort($packages[$name]);
} }
file_put_contents($dir . '/packages.txt', serialize($packages)); file_put_contents($targetDir . '/packages.txt', serialize($packages));
$controller->stdout('done.' . PHP_EOL, Console::FG_GREEN); if ($this->controller !== null) {
$this->controller->stdout('done.' . PHP_EOL, Console::FG_GREEN);
}
} }
public function generateUrl($typeName) public function generateApiUrl($typeName)
{ {
return strtolower(str_replace('\\', '-', $typeName)); return strtolower(str_replace('\\', '-', $typeName));
} }
protected function generateFileName($typeName) protected function generateFileName($typeName)
{ {
return $this->generateUrl($typeName) . '.html'; return $this->generateApiUrl($typeName) . '.html';
} }
} }
\ No newline at end of file
The `online` API doc template
=============================
This template is used to generate the Yii framework API docs for yiiframework.com.
\ No newline at end of file
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