Add the ability to do relative links in documentations

Cette révision appartient à :
Stéphane Goetz
2016-07-04 20:33:44 +02:00
Parent c846fec6b2
révision 4c98140329
15 fichiers modifiés avec 433 ajouts et 47 suppressions

Voir le fichier

@ -1,6 +1,7 @@
<?php namespace Todaymade\Daux;
use ArrayObject;
use Todaymade\Daux\Tree\Content;
class Config extends ArrayObject
{
@ -46,4 +47,14 @@ class Config extends ArrayObject
{
$this->merge($newValues, false);
}
public function getCurrentPage()
{
return $this['current_page'];
}
public function setCurrentPage(Content $entry)
{
$this['current_page'] = $entry;
}
}

Voir le fichier

@ -27,6 +27,7 @@ class ContentType implements \Todaymade\Daux\ContentTypes\ContentType
public function convert($raw, Content $node)
{
$this->config->setCurrentPage($node);
return $this->converter->convertToHtml($raw);
}
}

Voir le fichier

@ -28,13 +28,30 @@ class LinkRenderer extends \League\CommonMark\Inline\Renderer\LinkRenderer
*/
protected function resolveInternalFile($url)
{
$file = DauxHelper::getFile($this->daux['tree'], $url);
if ($file) {
$triedAbsolute = false;
// Legacy absolute paths could start with
// "!" In this case we will try to find
// the file starting at the root
if ($url[0] == '!' || $url[0] == '/') {
$url = ltrim($url, "!/");
if ($file = DauxHelper::getFile($this->daux['tree'], $url)) {
return $file;
}
$triedAbsolute = true;
}
// Seems it's not an absolute path or not found,
// so we'll continue with the current folder
if ($file = DauxHelper::getFile($this->daux->getCurrentPage()->getParent(), $url)) {
return $file;
}
$file = DauxHelper::getFile($this->daux['tree'], $url . '.html');
if ($file) {
// If we didn't already try it, we'll
// do a pass starting at the root
if (!$triedAbsolute && $file = DauxHelper::getFile($this->daux['tree'], $url)) {
return $file;
}
@ -42,10 +59,10 @@ class LinkRenderer extends \League\CommonMark\Inline\Renderer\LinkRenderer
}
/**
* @param Link $inline
* @param AbstractInline|Link $inline
* @param ElementRendererInterface $htmlRenderer
*
* @return HtmlElement
* @throws Exception
*/
public function render(AbstractInline $inline, ElementRendererInterface $htmlRenderer)
{
@ -63,12 +80,19 @@ class LinkRenderer extends \League\CommonMark\Inline\Renderer\LinkRenderer
$element = parent::render($inline, $htmlRenderer);
$url = $inline->getUrl();
if (!empty($url) && $url[0] == '!') {
$file = $this->resolveInternalFile(ltrim($url, "!"));
$element->setAttribute('href', $this->daux['base_url'] . $file->getUrl());
// Absolute urls, empty urls and anchors
// should not go through the url resolver
if (empty($url) || $url[0] == "#" || preg_match("|^(?:[a-z]+:)?//|", $url)) {
return $element;
}
$file = $this->resolveInternalFile($url);
$url = DauxHelper::getRelativePath($this->daux->getCurrentPage()->getUrl(), $file->getUrl());
$element->setAttribute('href', $url);
return $element;
}
}

Voir le fichier

@ -1,5 +1,6 @@
<?php namespace Todaymade\Daux;
use Todaymade\Daux\Tree\Builder;
use Todaymade\Daux\Tree\Directory;
class DauxHelper
@ -136,6 +137,16 @@ class DauxHelper
return implode(DIRECTORY_SEPARATOR, $absolutes);
}
public static function getFilenames(Config $config, $part)
{
$extensions = implode("|", array_map("preg_quote", $config["valid_content_extensions"])) . "|html";
$raw = preg_replace("/(.*)?\\.(" . $extensions . ")$/", "$1", $part);
$raw = Builder::removeSortingInformations($raw);
return ["$raw.html", $raw];
}
/**
* Locate a file in the tree. Returns the file if found or false
*
@ -153,6 +164,16 @@ class DauxHelper
return false;
}
// Some relative paths may start with ./
if ($node == '.') {
continue;
}
if ($node == '..') {
$tree = $tree->getParent();
continue;
}
$node = urldecode($node);
// if the node exists in the current request tree,
@ -163,6 +184,16 @@ class DauxHelper
continue;
}
// if the node doesn't exist, we can try
// two variants of the requested file:
// with and w/o the .html extension
foreach (static::getFilenames($tree->getConfig(), $node) as $filename) {
if (isset($tree->getEntries()[$filename])) {
$tree = $tree->getEntries()[$filename];
continue 2;
}
}
// At this stage, we're in a directory, but no
// sub-item matches, so the current node must
// be an index page or we failed
@ -190,7 +221,7 @@ class DauxHelper
*
* Taken from Stringy
*
* @param string $title
* @param string $title
* @return string
*/
public static function slug($title)
@ -353,4 +384,37 @@ class DauxHelper
"\xE2\x80\xAF", "\xE2\x81\x9F", "\xE3\x80\x80"),
);
}
public static function getRelativePath($from, $to)
{
// some compatibility fixes for Windows paths
$from = is_dir($from) ? rtrim($from, '\/') . '/' : $from;
$to = is_dir($to) ? rtrim($to, '\/') . '/' : $to;
$from = str_replace('\\', '/', $from);
$to = str_replace('\\', '/', $to);
$from = explode('/', $from);
$to = explode('/', $to);
$relPath = $to;
foreach ($from as $depth => $dir) {
// find first non-matching dir
if ($dir === $to[$depth]) {
// ignore this directory
array_shift($relPath);
} else {
// get number of remaining dirs to $from
$remaining = count($from) - $depth;
if ($remaining > 1) {
// add traversals up to first matching dir
$padLength = (count($relPath) + $remaining - 1) * -1;
$relPath = array_pad($relPath, $padLength, '..');
break;
} else {
//$relPath[0] = './' . $relPath[0];
}
}
}
return implode('/', $relPath);
}
}

Voir le fichier

@ -17,15 +17,17 @@ class Builder
protected static function isIgnored(\SplFileInfo $file, $ignore)
{
if (in_array($file->getFilename(), static::$IGNORED)) {
$filename = $file->getFilename();
if (in_array($filename, static::$IGNORED)) {
return true;
}
if ($file->isDir() && in_array($file->getFilename(), $ignore['folders'])) {
if (array_key_exists('folders', $ignore) && $file->isDir() && in_array($filename, $ignore['folders'])) {
return true;
}
if (!$file->isDir() && in_array($file->getFilename(), $ignore['files'])) {
if (array_key_exists('files', $ignore) && !$file->isDir() && in_array($filename, $ignore['files'])) {
return true;
}

Voir le fichier

@ -1,8 +1,10 @@
<?php namespace Todaymade\Daux\Tree;
use ArrayIterator;
use RuntimeException;
use Todaymade\Daux\Daux;
class Directory extends Entry
class Directory extends Entry implements \ArrayAccess, \IteratorAggregate
{
/** @var Entry[] */
protected $children = [];
@ -231,4 +233,54 @@ class Directory extends Entry
return $dump;
}
/**
* Whether a offset exists
* @param mixed $offset An offset to check for.
* @return boolean true on success or false on failure.
*/
public function offsetExists($offset)
{
return array_key_exists($offset, $this->children);
}
/**
* Offset to retrieve
* @param mixed $offset The offset to retrieve.
* @return Entry Can return all value types.
*/
public function offsetGet($offset)
{
return $this->children[$offset];
}
/**
* Offset to set
* @param mixed $offset The offset to assign the value to.
* @param Entry $value The value to set.
* @return void
*/
public function offsetSet($offset, $value)
{
if (!$value instanceof Entry) {
throw new RuntimeException("The value is not of type Entry");
}
$this->addChild($value);
}
/**
* Offset to unset
* @param string $offset the offset to unset
* @return void
*/
public function offsetUnset($offset)
{
unset($this->children[$offset]);
}
public function getIterator()
{
return new ArrayIterator($this->children);
}
}