Add the ability to do relative links in documentations
Cette révision appartient à :
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Référencer dans un nouveau ticket
Bloquer un utilisateur