Add doc module (WIP)

refs #4820
This commit is contained in:
Eric Lippmann 2013-10-16 14:45:23 +02:00
parent 89f6bedb10
commit af33599e19
5 changed files with 197 additions and 0 deletions

View File

@ -0,0 +1,15 @@
<?php
// @codingStandardsIgnoreStart
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use Icinga\Web\Controller\ActionController;
class Doc_IndexController extends ActionController
{
public function indexAction()
{
$this->_forward('index', 'view');
}
}
// @codingStandardsIgnoreEnd

View File

@ -0,0 +1,52 @@
<?php
// @codingStandardsIgnoreStart
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
use Icinga\Application\Icinga;
use Icinga\Module\Doc\Parser as DocParser;
use Icinga\Web\Controller\ActionController;
class Doc_ViewController extends ActionController
{
public function init()
{
$this->_helper->viewRenderer->setRender('view');
}
/**
* Populate view
*
* @param string $dir
*/
private function populateView($dir)
{
$parser = new DocParser();
list($html, $toc) = $parser->parseDirectory($dir);
$this->view->html = $html;
$this->view->toc = $toc;
}
public function indexAction()
{
$this->populateView(Icinga::app()->getApplicationDir('/../doc'));
}
/**
* Provide run-time dispatching of module documentation
*
* @param string $methodName
* @param array $args
*/
public function __call($methodName, $args)
{
$moduleManager = Icinga::app()->getModuleManager();
$moduleName = substr($methodName, 0, -6); // Strip 'Action' suffix
if ($moduleManager->hasEnabled($moduleName)) {
$this->populateView($moduleManager->getModuleDir($moduleName, '/doc'));
} else {
parent::__call($methodName, $args);
}
}
}
// @codingStandardsIgnoreEnd

View File

@ -0,0 +1,10 @@
<div class="doc-toc pull-left">
<ul class="nav nav-stacked">
<?php foreach ($toc as $i): ?>
<li class="toc-h<?= $i['level'] ?>">
<a href="#<?= $i['fragment'] ?>"><?= $this->escape($i['heading']); ?></a>
</li>
<?php endforeach; ?>
</ul>
</div>
<?= $html ?>

View File

@ -0,0 +1,27 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}
namespace Icinga\Module\Doc;
use \RecursiveFilterIterator;
class MarkdownFileIterator extends RecursiveFilterIterator
{
/**
* Accept files with .md suffix
*
* @return bool Whether the current element of the iterator is acceptable
* through this filter
*/
public function accept()
{
$current = $this->getInnerIterator()->current();
if (!$current->isFile()) {
return false;
}
$filename = $current->getFilename();
$sfx = substr($filename, -3);
return $sfx === false ? false : strtolower($sfx) === '.md';
}
}

View File

@ -0,0 +1,93 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}
namespace Icinga\Module\Doc;
require_once 'vendor/Michelf/Markdown.php';
require_once 'vendor/Michelf/MarkdownExtra.php';
use \RecursiveIteratorIterator;
use \RecursiveDirectoryIterator;
use \Exception;
use Michelf\MarkdownExtra;
/**
* Markdown parser
*/
class Parser
{
/**
* Retrieve table of contents and HTML converted from all markdown files in the given directory sorted by filename
*
* @param $dir
*
* @return array
* @throws Exception
*/
public function parseDirectory($dir)
{
$iter = new RecursiveIteratorIterator(
new MarkdownFileIterator(
new RecursiveDirectoryIterator($dir)
)
);
$fileInfos = iterator_to_array($iter);
natcasesort($fileInfos);
$cat = array();
$toc = array();
foreach ($fileInfos as $fileInfo) {
try {
$fileObject = $fileInfo->openFile();
} catch (RuntimeException $e) {
throw new Exception($e->getMessage());
}
if ($fileObject->flock(LOCK_SH) === false) {
throw new Exception('Couldn\'t get the lock');
}
while (!$fileObject->eof()) {
$line = $fileObject->fgets();
if ($line &&
$line[0] === '#' &&
preg_match('/^#+/', $line, $match) === 1
) {
// Atx-style
$level = strlen($match[0]);
$heading = trim(strip_tags(substr($line, $level)));
$fragment = urlencode($heading);
$toc[] = array(
'heading' => $heading,
'level' => $level,
'fragment' => $fragment
);
$line = '<span id="' . $fragment . '">' . "\n" . $line;
} elseif (
$line &&
($line[0] === '=' || $line[0] === '-') &&
preg_match('/^[=-]+\s*$/', $line, $match) === 1
) {
// Setext
if ($match[0][0] === '=') {
// H1
$level = 1;
} else {
// H2
$level = 2;
}
$heading = trim(strip_tags(end($cat)));
$fragment = urlencode($heading);
$toc[] = array(
'heading' => $heading,
'level' => $level,
'fragment' => $fragment
);
$line = '<span id="' . $fragment . '">' . "\n" . $line;
}
$cat[] = $line;
}
$fileObject->flock(LOCK_UN);
}
$html = MarkdownExtra::defaultTransform(implode('', $cat));
return array($html, $toc);
}
}