From fc8ab96c511ed542062ddf079036b5108a083af7 Mon Sep 17 00:00:00 2001 From: Will Rossiter Date: Fri, 14 Jan 2011 01:03:46 +0000 Subject: [PATCH] ENHANCEMENT: use urls in the format module/lang/version rather than version first. Tweaks to the parser to prevent infinite loops --- README.md | 4 ++- code/DocumentationEntity.php | 4 +-- code/DocumentationParser.php | 12 ++++--- code/DocumentationService.php | 9 +++--- code/DocumentationViewer.php | 48 +++++++++++++-------------- tests/DocumentationPageTest.php | 8 ++--- tests/DocumentationParserTest.php | 9 ++++++ tests/DocumentationViewerTest.php | 52 +++++++++++++++--------------- tests/docs/en/subfolder/subpage.md | 5 ++- tests/docs/en/test.md | 2 ++ 10 files changed, 87 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index c223093..7115a58 100755 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ Reads markdown documentation files from the /docs/ folder in . To read documenta For more documentation on how to use the module please read /docs/Writing-Documentation.md (or via this in /dev/docs/sapphiredocs/Writing-Documentation in your webbrowser) +**Note** This module assumes you are using numeric values for your versions. + ## Syntax Highlighting ## The custom Markdown parser can render custom prefixes for code blocks, @@ -58,4 +60,4 @@ To include the syntax highlighter source, add the following to your `Documentati Requirements::css('sapphiredocs/thirdparty/syntaxhighlighter/styles/shThemeRDark.css'); You can overload the `DocumentationViewer` class and add a custom route through `Director::addRule()` -if you prefer not to modify the module file.>>>>>>> .r115400 +if you prefer not to modify the module file. diff --git a/code/DocumentationEntity.php b/code/DocumentationEntity.php index 64ff3c8..dca6430 100644 --- a/code/DocumentationEntity.php +++ b/code/DocumentationEntity.php @@ -238,9 +238,9 @@ class DocumentationEntity extends ViewableData { return Controller::join_links( Director::absoluteBaseURL(), DocumentationViewer::get_link_base(), - $version, + $this->moduleFolder, $lang, - $this->moduleFolder + $version ); } diff --git a/code/DocumentationParser.php b/code/DocumentationParser.php index c1b143e..9974ab4 100644 --- a/code/DocumentationParser.php +++ b/code/DocumentationParser.php @@ -34,10 +34,11 @@ class DocumentationParser { if(!$page || (!$page instanceof DocumentationPage)) return false; $md = $page->getMarkdown(); - + // Pre-processing $md = self::rewrite_image_links($md, $page); $md = self::rewrite_relative_links($md, $page, $baselink); + $md = self::rewrite_api_links($md, $page); $md = self::rewrite_heading_anchors($md, $page); $md = self::rewrite_code_blocks($md, $page); @@ -103,6 +104,7 @@ class DocumentationParser { // Don't process absolute links (based on protocol detection) $urlParts = parse_url($url); + if($urlParts && isset($urlParts['scheme'])) continue; // Rewrite URL (relative or absolute) @@ -246,6 +248,7 @@ class DocumentationParser { * @return String Markdown */ static function rewrite_relative_links($md, $page, $baselink) { + $re = '/ ([^\!]?) # exclude image format \[ @@ -262,6 +265,7 @@ class DocumentationParser { if($relativePath == '.') $relativePath = ''; if($matches) { + foreach($matches[0] as $i => $match) { $title = $matches[2][$i]; $url = $matches[3][$i]; @@ -272,12 +276,12 @@ class DocumentationParser { // Don't process absolute links (based on protocol detection) $urlParts = parse_url($url); if($urlParts && isset($urlParts['scheme'])) continue; - + // Rewrite URL (relative or absolute) if(preg_match('/^\//', $url)) { - $relativeUrl = $baselink . $url; + $relativeUrl = Controller::join_links($baselink, $url); } else { - $relativeUrl = $baselink . '/' . $relativePath . '/' . $url; + $relativeUrl = Controller::join_links($baselink, $relativePath, $url); } // Resolve relative paths diff --git a/code/DocumentationService.php b/code/DocumentationService.php index d261e40..39483fa 100644 --- a/code/DocumentationService.php +++ b/code/DocumentationService.php @@ -232,13 +232,14 @@ class DocumentationService { * @return DocumentationEntity $module the registered module */ public static function is_registered_module($module, $version = false, $lang = false) { - $check = ($module instanceof DocumentationEntity) ? $module->getModuleFolder() : (string) $module; - + if(isset(self::$registered_modules[$check])) { $module = self::$registered_modules[$check]; - if($lang && !$module->hasLanguage($lang)) return false; - if($version && !$module->hasVersion($version)) return false; + + if(($lang && !$module->hasLanguage($lang)) || ($version && !$module->hasVersion($version))) { + return false; + } return $module; } diff --git a/code/DocumentationViewer.php b/code/DocumentationViewer.php index e50f399..949a053 100755 --- a/code/DocumentationViewer.php +++ b/code/DocumentationViewer.php @@ -25,7 +25,7 @@ class DocumentationViewer extends Controller { /** * @var string */ - public $version = "current"; + public $version = ""; /** * @var string @@ -128,7 +128,6 @@ class DocumentationViewer extends Controller { $thirdParam = $request->shift(); $this->Remaining = $request->shift(10); - DocumentationService::load_automatic_registration(); if(isset($firstParam)) { @@ -146,33 +145,34 @@ class DocumentationViewer extends Controller { return $this->response; } - else if(is_numeric($firstParam) || $firstParam == "current") { - // its a version number first in the form 2.4/en/sapphire - $this->version = $firstParam; - $this->lang = $secondParam; - $this->module = $thirdParam; + + $this->module = $firstParam; + $this->lang = $secondParam; + + if(isset($thirdParam) && (is_numeric($thirdParam))) { + $this->version = $thirdParam; } else { - // we have a language first in the form /en/sapphire + // current version so store one area para array_unshift($this->Remaining, $thirdParam); - - $this->lang = $firstParam; - $this->module = $secondParam; + + $this->version = ""; } } // 'current' version mapping $module = DocumentationService::is_registered_module($this->module, null, $this->getLang()); - - if($module && $this->getVersion()) { + + if($module) { $current = $module->getCurrentVersion(); - + $version = $this->getVersion(); - if($version == 'current') { + if(!$version || $version == '') { $this->version = $current; } else if($current == $version) { - $this->version = 'current'; + $this->version = ''; + $link = $this->Link($this->Remaining); $this->response = new SS_HTTPResponse(); @@ -180,8 +180,7 @@ class DocumentationViewer extends Controller { return $this->response; } - } - + } return parent::handleRequest($request); } @@ -216,7 +215,8 @@ class DocumentationViewer extends Controller { } /** - * Returns the current version + * Returns the current version. If no version is set then it is the current + * set version so need to pull that from the module * * @return String */ @@ -369,9 +369,9 @@ class DocumentationViewer extends Controller { */ function getPage() { $module = $this->getModule(); - - if(!$module) return false; + if(!$module) return false; + $absFilepath = DocumentationService::find_page($module, $this->Remaining); if($absFilepath) { @@ -399,7 +399,7 @@ class DocumentationViewer extends Controller { function getModulePages() { if($module = $this->getModule()) { $pages = DocumentationService::get_pages_from_folder($module, null, false); - + if($pages) { foreach($pages as $page) { if(strtolower($page->Title) == "index") { @@ -479,7 +479,7 @@ class DocumentationViewer extends Controller { if($page = $this->getPage()) { // Remove last portion of path (filename), we want a link to the folder base - $html = DocumentationParser::parse($page, $this->Link(array_slice($this->Remaining, -1, -1))); + $html = DocumentationParser::parse($page, $this->Link(array_slice($this->Remaining, 0))); return DBField::create("HTMLText", $html); } @@ -563,7 +563,7 @@ class DocumentationViewer extends Controller { } } - $link = Controller::join_links($base, self::get_link_base(), $version, $lang, $module, $action); + $link = Controller::join_links($base, self::get_link_base(), $module, $lang, $version, $action); return $link; } diff --git a/tests/DocumentationPageTest.php b/tests/DocumentationPageTest.php index 1430743..85ca4e6 100644 --- a/tests/DocumentationPageTest.php +++ b/tests/DocumentationPageTest.php @@ -15,21 +15,21 @@ class DocumentationPageTest extends SapphireTest { $page->setEntity($entity); // single layer - $this->assertStringEndsWith('en/testmodule/test', $page->Link(), 'The page link should have no extension and have a language'); + $this->assertStringEndsWith('testmodule/en/test', $page->Link(), 'The page link should have no extension and have a language'); $folder = new DocumentationPage(); $folder->setRelativePath('sort'); $folder->setEntity($entity); // folder, should have a trailing slash - $this->assertStringEndsWith('en/testmodule/sort/', $folder->Link()); + $this->assertStringEndsWith('testmodule/en/sort/', $folder->Link()); // second $nested = new DocumentationPage(); $nested->setRelativePath('subfolder/subpage.md'); $nested->setEntity($entity); - $this->assertStringEndsWith('en/testmodule/subfolder/subpage', $nested->Link()); + $this->assertStringEndsWith('testmodule/en/subfolder/subpage', $nested->Link()); // test with version. $entity = DocumentationService::register("versionlinks", BASE_PATH . "/sapphiredocs/tests/docs-2/", '1'); @@ -37,7 +37,7 @@ class DocumentationPageTest extends SapphireTest { $page->setRelativePath('test.md'); $page->setEntity($entity); $page->setVersion('1'); - $this->assertStringEndsWith('1/en/versionlinks/test', $page->Link()); + $this->assertStringEndsWith('versionlinks/en/1/test', $page->Link()); } diff --git a/tests/DocumentationParserTest.php b/tests/DocumentationParserTest.php index 8f70f2b..0945f73 100644 --- a/tests/DocumentationParserTest.php +++ b/tests/DocumentationParserTest.php @@ -139,6 +139,10 @@ HTML; '[link: api](api:DataObject)', $result ); + $this->assertContains( + '[link: relative](mycontroller/cms/2.4/a-relative-file.md)', + $result + ); // Page in subfolder $page = new DocumentationPage(); @@ -147,6 +151,11 @@ HTML; $result = DocumentationParser::rewrite_relative_links($page->getMarkdown(), $page, 'mycontroller/cms/2.4/en/'); + $this->assertContains( + '[link: relative](mycontroller/cms/2.4/en/subfolder/subpage.md)', + $result + ); + $this->assertContains( '[link: absolute index](mycontroller/cms/2.4/en/)', $result diff --git a/tests/DocumentationViewerTest.php b/tests/DocumentationViewerTest.php index 0e6d64e..4c9b7ca 100644 --- a/tests/DocumentationViewerTest.php +++ b/tests/DocumentationViewerTest.php @@ -41,7 +41,7 @@ class DocumentationViewerTest extends FunctionalTest { function testGetModulePagesShort() { $v = new DocumentationViewer(); - $response = $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/DocumentationViewerTests/subfolder/')); + $response = $v->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/2.4/subfolder/')); $pages = $v->getModulePages(); $arr = $pages->toArray(); @@ -52,7 +52,7 @@ class DocumentationViewerTest extends FunctionalTest { function testGetModulePages() { $v = new DocumentationViewer(); - $response = $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/DocumentationViewerTests/subfolder/')); + $response = $v->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/2.4/subfolder/')); $pages = $v->getModulePages(); $this->assertEquals( array('sort/', 'subfolder/', 'test.md'), @@ -69,9 +69,9 @@ class DocumentationViewerTest extends FunctionalTest { $links = $pages->column('Link'); - $this->assertStringEndsWith('2.4/en/DocumentationViewerTests/sort/', $links[0]); - $this->assertStringEndsWith('2.4/en/DocumentationViewerTests/subfolder/', $links[1]); - $this->assertStringEndsWith('2.4/en/DocumentationViewerTests/test', $links[2]); + $this->assertStringEndsWith('DocumentationViewerTests/en/2.4/sort/', $links[0]); + $this->assertStringEndsWith('DocumentationViewerTests/en/2.4/subfolder/', $links[1]); + $this->assertStringEndsWith('DocumentationViewerTests/en/2.4/test', $links[2]); // Children $pagesArr = $pages->toArray(); @@ -96,44 +96,44 @@ class DocumentationViewerTest extends FunctionalTest { $child2Links = $children->column('Link'); $subpage = $children->First(); - $this->assertStringEndsWith('2.4/en/DocumentationViewerTests/subfolder/subpage', $child2Links[0]); - $this->assertStringEndsWith('2.4/en/DocumentationViewerTests/subfolder/subsubfolder/', $child2Links[1]); + $this->assertStringEndsWith('DocumentationViewerTests/en/2.4/subfolder/subpage', $child2Links[0]); + $this->assertStringEndsWith('DocumentationViewerTests/en/2.4/subfolder/subsubfolder/', $child2Links[1]); } function testCurrentRedirection() { - $response = $this->get('dev/docs/3.0/en/DocumentationViewerTests/test'); + $response = $this->get('dev/docs/DocumentationViewerTests/en/3.0/test'); $this->assertEquals(301, $response->getStatusCode()); $this->assertEquals( - Director::absoluteBaseURL() . 'dev/docs/current/en/DocumentationViewerTests/test/', + Director::absoluteBaseURL() . 'dev/docs/DocumentationViewerTests/en/test/', $response->getHeader('Location'), 'Redirection to current on page' ); - $response = $this->get('dev/docs/3.0/en/DocumentationViewerTests/'); + $response = $this->get('dev/docs/DocumentationViewerTests/en/3.0'); $this->assertEquals(301, $response->getStatusCode()); $this->assertEquals( - Director::absoluteBaseURL() . 'dev/docs/current/en/DocumentationViewerTests/', + Director::absoluteBaseURL() . 'dev/docs/DocumentationViewerTests/en/', $response->getHeader('Location'), 'Redirection to current on index' ); - $response = $this->get('dev/docs/2.3/en/DocumentationViewerTests/'); + $response = $this->get('dev/docs/DocumentationViewerTests/en/2.3'); $this->assertEquals(200, $response->getStatusCode(), 'No redirection on older versions'); } function testUrlParsing() { // Module index $v = new DocumentationViewer(); - $response = $v->handleRequest(new SS_HTTPRequest('GET', '2.3/en/DocumentationViewerTests/test')); + $response = $v->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/2.3/test')); $this->assertEquals('2.3', $v->getVersion()); $this->assertEquals('en', $v->getLang()); $this->assertEquals('DocumentationViewerTests', $v->module); $this->assertEquals(array('test'), $v->Remaining); - + // Module index without version and language. Should pick up the defaults $v2 = new DocumentationViewer(); - $response = $v2->handleRequest(new SS_HTTPRequest('GET', 'en/DocumentationViewerTests/test')); + $response = $v2->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/test')); $this->assertEquals('3.0', $v2->getVersion()); $this->assertEquals('en', $v2->getLang()); @@ -143,7 +143,7 @@ class DocumentationViewerTest extends FunctionalTest { // Overall index $v = new DocumentationViewer(); $response = $v->handleRequest(new SS_HTTPRequest('GET', '')); - $this->assertEquals('current', $v->getVersion()); + $this->assertEquals('', $v->getVersion()); $this->assertEquals('en', $v->getLang()); $this->assertEquals('', $v->module); $this->assertEquals(array(), $v->Remaining); @@ -152,35 +152,35 @@ class DocumentationViewerTest extends FunctionalTest { function testBreadcrumbs() { // Module index $v = new DocumentationViewer(); - $response = $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/DocumentationViewerTests/')); + $response = $v->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/2.4')); $crumbs = $v->getBreadcrumbs(); $this->assertEquals(1, $crumbs->Count()); $crumbLinks = $crumbs->column('Link'); - $this->assertStringEndsWith('DocumentationViewerTests/', $crumbLinks[0]); + $this->assertStringEndsWith('DocumentationViewerTests/en/2.4/', $crumbLinks[0]); // Subfolder index $v = new DocumentationViewer(); - $response = $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/DocumentationViewerTests/subfolder/')); + $response = $v->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/2.4/subfolder/')); $crumbs = $v->getBreadcrumbs(); $this->assertEquals(2, $crumbs->Count()); $crumbLinks = $crumbs->column('Link'); - $this->assertStringEndsWith('DocumentationViewerTests/', $crumbLinks[0]); - $this->assertStringEndsWith('DocumentationViewerTests/subfolder/', $crumbLinks[1]); + $this->assertStringEndsWith('DocumentationViewerTests/en/2.4/', $crumbLinks[0]); + $this->assertStringEndsWith('DocumentationViewerTests/en/2.4/subfolder/', $crumbLinks[1]); // Subfolder page $v = new DocumentationViewer(); - $response = $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/DocumentationViewerTests/subfolder/subpage')); + $response = $v->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/2.4/subfolder/subpage')); $crumbs = $v->getBreadcrumbs(); $this->assertEquals(3, $crumbs->Count()); $crumbLinks = $crumbs->column('Link'); - $this->assertStringEndsWith('DocumentationViewerTests/', $crumbLinks[0]); - $this->assertStringEndsWith('DocumentationViewerTests/subfolder/', $crumbLinks[1]); - $this->assertStringEndsWith('DocumentationViewerTests/subfolder/subpage/', $crumbLinks[2]); + $this->assertStringEndsWith('DocumentationViewerTests/en/2.4/', $crumbLinks[0]); + $this->assertStringEndsWith('DocumentationViewerTests/en/2.4/subfolder/', $crumbLinks[1]); + $this->assertStringEndsWith('DocumentationViewerTests/en/2.4/subfolder/subpage/', $crumbLinks[2]); } function testRouting() { - $response = $this->get('dev/docs/2.4/en/DocumentationViewerTests/test'); + $response = $this->get('dev/docs/DocumentationViewerTests/en/2.4/test'); $this->assertEquals(200, $response->getStatusCode()); $this->assertContains('english test', $response->getBody(), 'Toplevel content page'); } diff --git a/tests/docs/en/subfolder/subpage.md b/tests/docs/en/subfolder/subpage.md index 29c925e..eadaff0 100644 --- a/tests/docs/en/subfolder/subpage.md +++ b/tests/docs/en/subfolder/subpage.md @@ -1,9 +1,12 @@ [link: absolute index](/) [link: absolute index with name](/index) [link: relative index](../) +[link: relative](../subfolder/subpage.md) +[link: relative multiline +](../subfolder/subpage.md) [link: relative parent page](../test) [link: absolute parent page](/test) ![relative image link](_images/image.png) ![parent image link](../_images/image.png) -![absolute image link](/_images/image.png) \ No newline at end of file +![absolute image link](/_images/image.png) diff --git a/tests/docs/en/test.md b/tests/docs/en/test.md index 9f7d357..df723d0 100644 --- a/tests/docs/en/test.md +++ b/tests/docs/en/test.md @@ -9,6 +9,8 @@ test [link: with anchor](/test#anchor) [link: http](http://silverstripe.org) [link: api](api:DataObject) +[link: relative](../a-relative-file.md) + [api:DataObject::$has_one] :::php