diff --git a/libs/ContentTypes/Markdown/LinkRenderer.php b/libs/ContentTypes/Markdown/LinkRenderer.php
index 9730850..ba7b11e 100644
--- a/libs/ContentTypes/Markdown/LinkRenderer.php
+++ b/libs/ContentTypes/Markdown/LinkRenderer.php
@@ -109,18 +109,38 @@ class LinkRenderer extends \League\CommonMark\Inline\Renderer\LinkRenderer
$urlAndHash = explode('#', $url);
$url = $urlAndHash[0];
+ $foundWithHash = false;
+
try {
$file = $this->resolveInternalFile($url);
$url = DauxHelper::getRelativePath($this->daux->getCurrentPage()->getUrl(), $file->getUrl());
} catch (LinkNotFoundException $e) {
- if ($this->daux->isStatic()) {
- throw $e;
+
+
+
+ // For some reason, the filename could contain a # and thus the link needs to resolve to that.
+ try {
+ if (strlen($urlAndHash[1]) > 0) {
+ $file = $this->resolveInternalFile($url . '#' . $urlAndHash[1]);
+ $url = DauxHelper::getRelativePath($this->daux->getCurrentPage()->getUrl(), $file->getUrl());
+ $foundWithHash = true;
+ }
+ } catch (LinkNotFoundException $e2) {
+ // If it's still not found here, we'll only
+ // report on the first error as the second
+ // one will tell the same.
}
- $element->setAttribute('class', 'Link--broken');
+ if (!$foundWithHash) {
+ if ($this->daux->isStatic()) {
+ throw $e;
+ }
+
+ $element->setAttribute('class', 'Link--broken');
+ }
}
- if (isset($urlAndHash[1])) {
+ if (!$foundWithHash && isset($urlAndHash[1])) {
$url .= '#' . $urlAndHash[1];
}
diff --git a/libs/DauxHelper.php b/libs/DauxHelper.php
index ca5b13d..2b97f5d 100644
--- a/libs/DauxHelper.php
+++ b/libs/DauxHelper.php
@@ -189,7 +189,7 @@ class DauxHelper
continue;
}
- $node = urldecode($node);
+ $node = DauxHelper::slug(urldecode($node));
// if the node exists in the current request tree,
// change the $tree variable to reference the new
@@ -241,18 +241,21 @@ class DauxHelper
*/
public static function slug($title)
{
+ // Convert to ASCII
foreach (static::charsArray() as $key => $value) {
$title = str_replace($value, $key, $title);
}
+ // Remove unsupported characters
$title = preg_replace('/[^\x20-\x7E]/u', '', $title);
$separator = '_';
// Convert all dashes into underscores
$title = preg_replace('![' . preg_quote('-') . ']+!u', $separator, $title);
- // Remove all characters that are not the separator, letters, numbers, or whitespace.
- $title = preg_replace('![^' . preg_quote($separator) . '\pL\pN\s]+!u', '', $title);
+ // Remove all characters that are not valid in a URL:
+ // $-_.+!*'(), separator, letters, numbers, or whitespace.
+ $title = preg_replace('![^-' . preg_quote($separator) . '\!\'\(\),\.\+\*\$\pL\pN\s]+!u', '', $title);
// Replace all separator characters and whitespace by a single separator
$title = preg_replace('![' . preg_quote($separator) . '\s]+!u', $separator, $title);
diff --git a/libs/Tree/Builder.php b/libs/Tree/Builder.php
index b3587d5..a93b26d 100644
--- a/libs/Tree/Builder.php
+++ b/libs/Tree/Builder.php
@@ -115,6 +115,7 @@ class Builder
}
$uri = static::removeSortingInformations($name);
+ $uri = DauxHelper::slug($uri);
if ($config->isStatic()) {
$uri .= '.html';
}
diff --git a/tests/ContentTypes/Markdown/LinkRendererTest.php b/tests/ContentTypes/Markdown/LinkRendererTest.php
index a0e7668..f82e926 100644
--- a/tests/ContentTypes/Markdown/LinkRendererTest.php
+++ b/tests/ContentTypes/Markdown/LinkRendererTest.php
@@ -20,6 +20,7 @@ class LinkRendererTest extends TestCase
'Widgets' => [
'Page.md' => 'another page',
'Button.md' => 'another page',
+ 'Page_with_#_hash.md' => 'page with hash',
],
];
$root = vfsStream::setup('root', null, $structure);
@@ -38,6 +39,11 @@ class LinkRendererTest extends TestCase
public function providerRenderLink()
{
return [
+ // /Widgets/Page_with_#_hash
+ ['Link', '[Link](../Widgets/Page_with_#_hash.md)', 'Content/Page.html'],
+ ['Link', '[Link](!Widgets/Page_with_#_hash)', 'Content/Page.html'],
+ ['Link', '[Link](Page_with_#_hash.md)', 'Widgets/Page.html'],
+
// /Widgets/Page
['Link', '[Link](http://google.ch)', 'Widgets/Page.html'],
['Link', '[Link](#features)', 'Widgets/Page.html'],
diff --git a/tests/Tree/BuilderTest.php b/tests/Tree/BuilderTest.php
index d675925..a742527 100644
--- a/tests/Tree/BuilderTest.php
+++ b/tests/Tree/BuilderTest.php
@@ -82,16 +82,27 @@ class BuilderTest extends TestCase
return new Root($config);
}
- public function testGetOrCreatePage()
+ public function providerCreatePage()
+ {
+ return [
+ ['A Page.md', 'dir/A_Page.html', 'A_Page.html', 'A Page'],
+ ['Page#1.md', 'dir/Page1.html', 'Page1.html', 'Page#1']
+ ];
+ }
+
+ /**
+ * @dataProvider providerCreatePage
+ */
+ public function testGetOrCreatePage($file, $url, $uri, $title)
{
$directory = new Directory($this->getStaticRoot(), 'dir');
- $entry = Builder::getOrCreatePage($directory, 'A Page.md');
+ $entry = Builder::getOrCreatePage($directory, $file);
$this->assertSame($directory, $entry->getParent());
- $this->assertEquals('dir/A_Page.html', $entry->getUrl());
- $this->assertEquals('A_Page.html', $entry->getUri());
- $this->assertEquals('A Page', $entry->getTitle());
+ $this->assertEquals($url, $entry->getUrl());
+ $this->assertEquals($uri, $entry->getUri());
+ $this->assertEquals($title, $entry->getTitle());
$this->assertInstanceOf('Todaymade\Daux\Tree\Content', $entry);
}