From 277bca7b1157852f911c823b68175b7c81d2afc7 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Sun, 1 Aug 2010 04:46:32 +0000 Subject: [PATCH] FEATURE Added parsing support for relative links (relative to module base). Introduced DocumentationPage to encapsulate this information. ENHANCEMENT Saving $ModuleName in viewer instead of getting it from Remaining[0] MINOR Don't include version in breadcrumbs, doesn't make sense in this context (e.g. "2.4/en/cms", the "2.4" part is connecte to the cms module, hence an index of all versions regardless of module is not very useful) --- code/DocumentationEntity.php | 18 +- code/DocumentationPage.php | 90 ++++++++++ code/DocumentationParser.php | 92 +++++++++-- code/DocumentationViewer.php | 102 ++++++++---- tests/DocumentationEntityTest.php | 21 +++ tests/DocumentationPageTest.php | 33 ++++ tests/DocumentationParserTest.php | 103 ++++++++++++ tests/DocumentationViewerTests.php | 155 ++++++++++++++---- tests/docs/en/subfolder/subpage.md | 5 + .../en/subfolder/subsubfolder/subsubpage.md | 5 + tests/docs/en/test.md | 8 +- 11 files changed, 546 insertions(+), 86 deletions(-) create mode 100644 code/DocumentationPage.php create mode 100644 tests/DocumentationEntityTest.php create mode 100644 tests/DocumentationPageTest.php create mode 100644 tests/docs/en/subfolder/subpage.md create mode 100644 tests/docs/en/subfolder/subsubfolder/subsubpage.md diff --git a/code/DocumentationEntity.php b/code/DocumentationEntity.php index feff75b..55b0c37 100644 --- a/code/DocumentationEntity.php +++ b/code/DocumentationEntity.php @@ -5,6 +5,9 @@ * path with {@link DocumentationService::register()}. This refers to a whole package * rather than a specific page but if we need page options we may need to introduce * a class for that. + * + * Each folder must have at least one language subfolder, which is automatically + * determined through {@link addVersion()} and should not be included in the $path argument. * * @package sapphiredocs */ @@ -41,7 +44,7 @@ class DocumentationEntity extends ViewableData { * * @param String $module name of module * @param String $version version of this module - * @param String $path path to this module + * @param String $path Absolute path to this module (excluding language folders) */ function __construct($module, $version = '', $path, $title = false) { $this->addVersion($version, $path); @@ -165,7 +168,7 @@ class DocumentationEntity extends ViewableData { } /** - * Return the path to this documentation entity + * Return the absolute path to this documentation entity. * * @return String */ @@ -174,9 +177,14 @@ class DocumentationEntity extends ViewableData { if(!$version) $version = ''; if(!$lang) $lang = 'en'; - if(!$this->hasVersion($version)) $path = array_pop($this->versions); - else $path = $this->versions[$version]; + // Get version, or fall back to first available + if($this->hasVersion($version)) { + $path = $this->versions[$version]; + } else { + $versions = $this->getVersions(); + $path = $this->versions[$versions[0]]; + } - return $path . $lang .'/'; + return $path . '/' . $lang .'/'; } } \ No newline at end of file diff --git a/code/DocumentationPage.php b/code/DocumentationPage.php new file mode 100644 index 0000000..99cb538 --- /dev/null +++ b/code/DocumentationPage.php @@ -0,0 +1,90 @@ +entity = $entity; + $this->relativePath = $relativePath; + if($lang) $this->lang = $lang; + if($version) $this->version = $version; + + if(!file_exists($this->getPath())) { + throw new InvalidArgumentException(sprintf( + 'Path could not be found: "%s" (module path: %s, file path: %s)', + $this->getPath(), + $this->entity->getPath(), + $this->relativePath + )); + } + + parent::__construct(); + } + + /** + * @return DocumentationEntity + */ + function getEntity() { + return $this->entity; + } + + /** + * @return String Relative path to file or folder within the entity (including file extension), + * but excluding version or language folders. + */ + function getRelativePath() { + return $this->relativePath; + } + + /** + * Absolute path including version and lang folder. + * + * @return String + */ + function getPath() { + return realpath($this->entity->getPath($this->version, $this->lang) . '/' . $this->getRelativePath()); + } + + function getLang() { + return $this->lang; + } + + function getVersion() { + return $this->version; + } + + /** + * @return String + */ + function getMarkdown() { + return file_get_contents($this->getPath()); + } + + /** + * @param String $baselink + * @return String + */ + function getHTML($baselink = null) { + return DocumentationParser::parse($this, $baselink); + } + +} \ No newline at end of file diff --git a/code/DocumentationParser.php b/code/DocumentationParser.php index d3af3d9..07a6825 100644 --- a/code/DocumentationParser.php +++ b/code/DocumentationParser.php @@ -8,27 +8,95 @@ */ class DocumentationParser { - + /** * Parse a given path to the documentation for a file. Performs a case insensitive * lookup on the file system. Automatically appends the file extension to one of the markdown * extensions as well so /install/ in a web browser will match /install.md or /INSTALL.md - * - * @param String $module path to a module - * @param Array path of urls. Should be folders, last one is a page + * + * Filepath: /var/www/myproject/src/cms/en/folder/subfolder/page.md + * URL: http://myhost/mywebroot/dev/docs/2.4/cms/en/folder/subfolder/page + * Webroot: http://myhost/mywebroot/ + * Baselink: dev/docs/2.4/cms/en/ + * Pathparts: folder/subfolder/page + * + * @param DocumentationPage $page + * @param String $baselink Link relative to webroot, up until the "root" of the module. + * Necessary to rewrite relative links * * @return HTMLText */ - public static function parse($module, $path) { + public static function parse(DocumentationPage $page, $baselink = null) { require_once('../sapphiredocs/thirdparty/markdown.php'); - if($content = self::find_page($module, $path)) { - $content = Markdown(file_get_contents($content)); + $md = $page->getMarkdown(); + + // Pre-processing + $md = self::rewrite_relative_links($md, $page, $baselink); + + $html = Markdown($md); - return DBField::create('HTMLText', $content); + return DBField::create('HTMLText', $html); + } + + /** + * Resolves all relative links within markdown. + * + * @param String $md Markdown content + * @param DocumentationPage $page + * @param String $baselink + * @return String Markdown + */ + static function rewrite_relative_links($md, $page, $baselink) { + $re = '/ + \[ + (.*?) # link title (non greedy) + \] + \( + (.*?) # link url (non greedy) + \) + /x'; + preg_match_all($re, $md, $matches); + + // relative path (to module base folder), without the filename + $relativePath = dirname($page->getRelativePath()); + if($relativePath == '.') $relativePath = ''; + + if($matches) foreach($matches[0] as $i => $match) { + $title = $matches[1][$i]; + $url = $matches[2][$i]; + + // Don't process API links + if(preg_match('/^api:/', $url)) continue; + + // 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; + } else { + $relativeUrl = $baselink . '/' . $relativePath . '/' . $url; + } + + // Resolve relative paths + while(strpos($relativeUrl, '..') !== FALSE) { + $relativeUrl = preg_replace('/\w+\/\.\.\//', '', $relativeUrl); + } + + // Replace any double slashes (apart from protocol) + $relativeUrl = preg_replace('/([^:])\/{2,}/', '$1/', $relativeUrl); + + // Replace in original content + $md = str_replace( + $match, + sprintf('[%s](%s)', $title, $relativeUrl), + $md + ); } - return false; + return $md; } /** @@ -37,13 +105,13 @@ class DocumentationParser { * * Name may also be a path /install/foo/bar. * - * @param String $entity path to the entity + * @param String $modulePath Absolute path to the entity * @param Array $path path to the file in the entity * * @return String|false - File path */ - private static function find_page($entity, $path) { - return self::find_page_recursive($entity, $path); + static function find_page($modulePath, $path) { + return self::find_page_recursive($modulePath, $path); } /** diff --git a/code/DocumentationViewer.php b/code/DocumentationViewer.php index e1265f9..4343799 100755 --- a/code/DocumentationViewer.php +++ b/code/DocumentationViewer.php @@ -36,8 +36,7 @@ class DocumentationViewer extends Controller { 'Lang' => 'Text', 'Module' => 'Text', 'LanguageTitle' => 'Text' - ); - + ); function init() { parent::init(); @@ -61,9 +60,9 @@ class DocumentationViewer extends Controller { */ public function handleRequest(SS_HTTPRequest $request) { - $this->Version = $request->shift(); - $this->Lang = $request->shift(); - + $this->Version = $request->shift(); + $this->Lang = $request->shift(); + $this->ModuleName = $request->shift(); $this->Remaining = $request->shift(10); DocumentationService::load_automatic_registration(); @@ -75,9 +74,11 @@ class DocumentationViewer extends Controller { // /en/sapphire/page which is a link to the latest one if(!is_numeric($this->Version)) { + array_unshift($this->Remaining, $this->ModuleName); + // not numeric so /en/sapphire/folder/page if(isset($this->Lang) && $this->Lang) - array_unshift($this->Remaining, $this->Lang); + $this->ModuleName = $this->Lang; $this->Lang = $this->Version; $this->Version = null; @@ -108,18 +109,16 @@ class DocumentationViewer extends Controller { // count the number of parameters after the language, version are taken // into account. This automatically includes ' ' so all the counts // are 1 more than what you would expect - if($this->Remaining) { + if($this->ModuleName || $this->Remaining) { $paramCount = count($this->Remaining); - if($paramCount == 1) { + if($paramCount == 0) { return parent::getViewer('folder'); } else if($module = $this->getModule()) { $params = $this->Remaining; - array_shift($params); // module name - $path = implode('/', array_unique($params)); if(is_dir($module->getPath() . $path)) return parent::getViewer('folder'); @@ -224,11 +223,24 @@ class DocumentationViewer extends Controller { if($modules) { foreach($modules as $module) { + $filepath = $module->getPath() . '/index.md'; + if(file_exists($filepath)) { + $page = new DocumentationPage( + $filepath, + $module, + $this->Lang, + $this->Version + ); + $content = DocumentationParser::parse($page, $this->Link(array_slice($this->Remaining, -1, -1))); + } else { + $content = ''; + } + // build the dataset. Load the $Content from an index.md $output->push(new ArrayData(array( 'Title' => $module->getTitle(), 'Code' => $module, - 'Content' => DocumentationParser::parse($module->getPath(), array('index')) + 'Content' => $content ))); } } @@ -242,13 +254,34 @@ class DocumentationViewer extends Controller { * @return false|DocumentationEntity */ function getModule() { - if($this->Remaining && is_array($this->Remaining)) { - return DocumentationService::is_registered_module($this->Remaining[0], $this->Version, $this->Lang); + if($this->ModuleName) { + return DocumentationService::is_registered_module($this->ModuleName, $this->Version, $this->Lang); } return false; } + /** + * @return DocumentationPage + */ + function getPage() { + $module = $this->getModule(); + if(!$module) return false; + + $absFilepath = DocumentationParser::find_page($module->getPath(), $this->Remaining); + if($absFilepath) { + $relativeFilePath = str_replace($module->getPath(), '', $absFilepath); + return new DocumentationPage( + $relativeFilePath, + $module, + $this->Lang, + $this->Version + ); + } else { + return false; + } + } + /** * Get the related pages to this module and the children to those pages * @@ -262,7 +295,7 @@ class DocumentationViewer extends Controller { if($pages) { foreach($pages as $page) { - $linkParts = array($module->getModuleFolder()); + $linkParts = array(); // don't include the 'index in the url if($page->Title != "Index") $linkParts[] = $page->Filename; @@ -272,16 +305,14 @@ class DocumentationViewer extends Controller { $page->LinkingMode = 'link'; $page->Children = false; - if(isset($this->Remaining[1])) { - if(strtolower($this->Remaining[1]) == $page->Filename) { + if(isset($this->Remaining[0])) { + if(strtolower($this->Remaining[0]) == $page->Filename) { $page->LinkingMode = 'current'; if(is_dir($page->Path)) { $children = DocumentationParser::get_pages_from_folder($page->Path); - $segments = array($module->getModuleFolder(), $this->Remaining[1]); - - foreach($children as $child) { - $child->Link = $this->Link(array_merge($segments, array($child->Filename))); + foreach($children as $child) { + $child->Link = $this->Link(array($this->Remaining[0], $child->Filename)); } $page->Children = $children; @@ -296,6 +327,7 @@ class DocumentationViewer extends Controller { return false; } + /** * Return the content for the page. If its an actual documentation page then * display the content from the page, otherwise display the contents from @@ -304,12 +336,9 @@ class DocumentationViewer extends Controller { * @return HTMLText */ function getContent() { - if($module = $this->getModule()) { - // name of the module. Throw it away since we already have the module path. - $filepath = $this->Remaining; - array_shift($filepath); - - return DocumentationParser::parse($module->getPath(), $filepath); + if($page = $this->getPage()) { + // Remove last portion of path (filename), we want a link to the folder base + return DocumentationParser::parse($page, $this->Link(array_slice($this->Remaining, -1, -1))); } return false; @@ -322,21 +351,23 @@ class DocumentationViewer extends Controller { * @return DataObjectSet */ function getBreadcrumbs() { - $pages = $this->Remaining; + $pages = array_merge(array($this->ModuleName), $this->Remaining);; $output = new DataObjectSet(); - $output->push(new ArrayData(array( - 'Title' => ($this->Version) ? $this->Version : _t('DocumentationViewer.DOCUMENTATION', 'Documentation'), - 'Link' => $this->Link() - ))); + + // $output->push(new ArrayData(array( + // 'Title' => ($this->Version) ? $this->Version : _t('DocumentationViewer.DOCUMENTATION', 'Documentation'), + // 'Link' => $this->Link() + // ))); if($pages) { $path = array(); - foreach($pages as $page => $title) { + foreach($pages as $i => $title) { if($title) { - $path[] = $title; - + // Don't add module name, already present in Link() + if($i > 0) $path[] = $title; + $output->push(new ArrayData(array( 'Title' => DocumentationParser::clean_page_name($title), 'Link' => $this->Link($path) @@ -362,6 +393,7 @@ class DocumentationViewer extends Controller { $version = ($this->Version) ? $this->Version . '/' : false; $lang = ($this->Lang) ? $this->Lang .'/' : false; + $module = ($this->ModuleName) ? $this->ModuleName .'/' : false; $action = ''; if(is_string($path)) $action = $path . '/'; @@ -374,7 +406,7 @@ class DocumentationViewer extends Controller { } } - return $base . $loc . $version . $lang . $action; + return $base . $loc . $version . $lang . $module . $action; } /** diff --git a/tests/DocumentationEntityTest.php b/tests/DocumentationEntityTest.php new file mode 100644 index 0000000..a0cfb4a --- /dev/null +++ b/tests/DocumentationEntityTest.php @@ -0,0 +1,21 @@ +assertEquals($entity->getTitle(), 'My Test'); + $this->assertEquals($entity->getVersions(), array('1.0')); + $this->assertEquals($entity->getLanguages(), array('en', 'de')); + $this->assertEquals($entity->getModuleFolder(), 'docs'); + + $this->assertTrue($entity->hasVersion('1.0')); + $this->assertFalse($entity->hasVersion('2.0')); + + $this->assertTrue($entity->hasLanguage('en')); + $this->assertFalse($entity->hasLanguage('fr')); + } +} \ No newline at end of file diff --git a/tests/DocumentationPageTest.php b/tests/DocumentationPageTest.php new file mode 100644 index 0000000..d44d8c0 --- /dev/null +++ b/tests/DocumentationPageTest.php @@ -0,0 +1,33 @@ +assertEquals('test.md', $page->getRelativePath()); + + $page = new DocumentationPage( + 'subfolder/subpage.md', + new DocumentationEntity('mymodule', null, BASE_PATH . '/sapphiredocs/tests/docs/') + ); + $this->assertEquals('subfolder/subpage.md', $page->getRelativePath()); + } + + function testGetPath() { + $absPath = BASE_PATH . '/sapphiredocs/tests/docs/'; + $page = new DocumentationPage( + 'test.md', + new DocumentationEntity('mymodule', null, $absPath) + ); + $this->assertEquals($absPath . 'en/test.md', $page->getPath()); + + $page = new DocumentationPage( + 'subfolder/subpage.md', + new DocumentationEntity('mymodule', null, $absPath) + ); + $this->assertEquals($absPath . 'en/subfolder/subpage.md', $page->getPath()); + } + +} \ No newline at end of file diff --git a/tests/DocumentationParserTest.php b/tests/DocumentationParserTest.php index 5d611ef..99657fe 100644 --- a/tests/DocumentationParserTest.php +++ b/tests/DocumentationParserTest.php @@ -4,6 +4,109 @@ */ class DocumentationParserTest extends SapphireTest { + function testRelativeLinks() { + // Page on toplevel + $page = new DocumentationPage( + 'test.md', + new DocumentationEntity('mymodule', null, BASE_PATH . '/sapphiredocs/tests/docs/') + ); + $result = DocumentationParser::rewrite_relative_links($page->getMarkdown(), $page, 'mycontroller/cms/2.4/en/'); + $this->assertContains( + '[link: subfolder index](mycontroller/cms/2.4/en/subfolder/)', + $result + ); + $this->assertContains( + '[link: subfolder page](mycontroller/cms/2.4/en/subfolder/subpage)', + $result + ); + $this->assertContains( + '[link: http](http://silverstripe.org)', + $result + ); + $this->assertContains( + '[link: api](api:DataObject)', + $result + ); + + // Page in subfolder + $page = new DocumentationPage( + 'subfolder/subpage.md', + new DocumentationEntity('mymodule', null, BASE_PATH . '/sapphiredocs/tests/docs/') + ); + $result = DocumentationParser::rewrite_relative_links($page->getMarkdown(), $page, 'mycontroller/cms/2.4/en/'); + $this->assertContains( + '[link: absolute index](mycontroller/cms/2.4/en/)', + $result + ); + $this->assertContains( + '[link: absolute index with name](mycontroller/cms/2.4/en/index)', + $result + ); + $this->assertContains( + '[link: relative index](mycontroller/cms/2.4/en/)', + $result + ); + $this->assertContains( + '[link: relative parent page](mycontroller/cms/2.4/en/test)', + $result + ); + $this->assertContains( + '[link: absolute parent page](mycontroller/cms/2.4/en/test)', + $result + ); + + // Page in nested subfolder + $page = new DocumentationPage( + 'subfolder/subsubfolder/subsubpage.md', + new DocumentationEntity('mymodule', null, BASE_PATH . '/sapphiredocs/tests/docs/') + ); + $result = DocumentationParser::rewrite_relative_links($page->getMarkdown(), $page, 'mycontroller/cms/2.4/en/'); + $this->assertContains( + '[link: absolute index](mycontroller/cms/2.4/en/)', + $result + ); + $this->assertContains( + '[link: relative index](mycontroller/cms/2.4/en/subfolder/)', + $result + ); + $this->assertContains( + '[link: relative parent page](mycontroller/cms/2.4/en/subfolder/subpage)', + $result + ); + $this->assertContains( + '[link: relative grandparent page](mycontroller/cms/2.4/en/test)', + $result + ); + $this->assertContains( + '[link: absolute page](mycontroller/cms/2.4/en/test)', + $result + ); + } + + function testCleanPageNames() { + $names = array( + 'documentation-Page', + 'documentation_Page', + 'documentation.md', + 'documentation.pdf', + 'documentation.file.txt', + '.hidden' + ); + + $should = array( + 'Documentation Page', + 'Documentation Page', + 'Documentation', + 'Documentation', + 'Documentation', + '.hidden' // don't display something without a title + ); + + foreach($names as $key => $value) { + $this->assertEquals(DocumentationParser::clean_page_name($value), $should[$key]); + } + } + function testGetPagesFromFolder() { $pages = DocumentationParser::get_pages_from_folder(BASE_PATH . '/sapphiredocs/tests/docs/en/'); $this->assertContains('index', $pages->column('Filename'), 'Index'); diff --git a/tests/DocumentationViewerTests.php b/tests/DocumentationViewerTests.php index 79468ff..facd9fc 100644 --- a/tests/DocumentationViewerTests.php +++ b/tests/DocumentationViewerTests.php @@ -11,42 +11,131 @@ class DocumentationViewerTests extends FunctionalTest { static $fixture_file = 'sapphiredocs/tests/DocumentTests.yml'; - function testCleanPageNames() { - $names = array( - 'documentation-Page', - 'documentation_Page', - 'documentation.md', - 'documentation.pdf', - 'documentation.file.txt', - '.hidden' - ); - - $should = array( - 'Documentation Page', - 'Documentation Page', - 'Documentation', - 'Documentation', - 'Documentation', - '.hidden' // don't display something without a title - ); - - foreach($names as $key => $value) { - $this->assertEquals(DocumentationParser::clean_page_name($value), $should[$key]); + function setUpOnce() { + parent::setUpOnce(); + + $this->origEnabled = DocumentationService::automatic_registration_enabled(); + DocumentationService::set_automatic_registration(false); + $this->origModules = DocumentationService::get_registered_modules(); + foreach($this->origModules as $module) { + DocumentationService::unregister($module->getModuleFolder()); } + DocumentationService::register("DocumentationViewerTests", BASE_PATH . "/sapphiredocs/tests/docs/", '2.4'); } - function testDocumentationEntityAccessing() { - $entity = new DocumentationEntity('docs', '1.0', '../sapphiredocs/tests/docs/', 'My Test'); + function tearDownOnce() { + parent::tearDownOnce(); - $this->assertEquals($entity->getTitle(), 'My Test'); - $this->assertEquals($entity->getVersions(), array('1.0')); - $this->assertEquals($entity->getLanguages(), array('en', 'de')); - $this->assertEquals($entity->getModuleFolder(), 'docs'); - - $this->assertTrue($entity->hasVersion('1.0')); - $this->assertFalse($entity->hasVersion('2.0')); - - $this->assertTrue($entity->hasLanguage('en')); - $this->assertFalse($entity->hasLanguage('fr')); + DocumentationService::unregister("DocumentationViewerTests"); + DocumentationService::set_automatic_registration($this->origEnabled); + // $this->origModules = Documentation::get_registered_modules(); + // foreach($this->origModules as $name => $module) { + // DocumentationService::register($name); + // } } + + function testUrlParsing() { + // Module index + $v = new DocumentationViewer(); + $response = $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/DocumentationViewerTests/test')); + $this->assertEquals('2.4', $v->Version); + $this->assertEquals('en', $v->Lang); + $this->assertEquals('DocumentationViewerTests', $v->ModuleName); + $this->assertEquals(array('test'), $v->Remaining); + + // Module index without version and language + $v = new DocumentationViewer(); + $response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/DocumentationViewerTests/test')); + $this->assertEquals(null, $v->Version); + $this->assertEquals('en', $v->Lang); + $this->assertEquals('DocumentationViewerTests', $v->ModuleName); + $this->assertEquals(array('test'), $v->Remaining); + + // Overall index + // $v = new DocumentationViewer(); + // $response = $v->handleRequest(new SS_HTTPRequest('GET', '')); + // $this->assertEquals(null, $v->Version); + // $this->assertEquals(null, $v->Lang); + // $this->assertEquals(null, $v->ModuleName); + // $this->assertEquals(array(), $v->Remaining); + } + + function testBreadcrumbs() { + // Module index + $v = new DocumentationViewer(); + $response = $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/DocumentationViewerTests/')); + $crumbs = $v->getBreadcrumbs(); + $this->assertEquals(1, $crumbs->Count()); + $crumbLinks = $crumbs->column('Link'); + $this->assertStringEndsWith('DocumentationViewerTests/', $crumbLinks[0]); + + // Subfolder index + $v = new DocumentationViewer(); + $response = $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/DocumentationViewerTests/subfolder/')); + $crumbs = $v->getBreadcrumbs(); + $this->assertEquals(2, $crumbs->Count()); + $crumbLinks = $crumbs->column('Link'); + $this->assertStringEndsWith('DocumentationViewerTests/', $crumbLinks[0]); + $this->assertStringEndsWith('DocumentationViewerTests/subfolder/', $crumbLinks[1]); + + // Subfolder page + $v = new DocumentationViewer(); + $response = $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/DocumentationViewerTests/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]); + } + + function testGetModulePages() { + $v = new DocumentationViewer(); + $response = $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/DocumentationViewerTests/subfolder/')); + $pages = $v->getModulePages(); + $this->assertEquals( + array('index', 'subfolder', 'test'), + $pages->column('Filename') + ); + $this->assertEquals( + array('link', 'current', 'link'), + $pages->column('LinkingMode') + ); + $links = $pages->column('Link'); + $this->assertStringEndsWith('2.4/en/DocumentationViewerTests/', $links[0]); + $this->assertStringEndsWith('2.4/en/DocumentationViewerTests/subfolder/', $links[1]); + $this->assertStringEndsWith('2.4/en/DocumentationViewerTests/test/', $links[2]); + + // Children + $pagesArr = $pages->toArray(); + $child1 = $pagesArr[0]; + $this->assertFalse($child1->Children); + + $child2 = $pagesArr[1]; + $this->assertType('DataObjectSet', $child2->Children); + $this->assertEquals( + array('subpage', 'subsubfolder'), + $child2->Children->column('Filename') + ); + $child2Links = $child2->Children->column('Link'); + $this->assertStringEndsWith('2.4/en/DocumentationViewerTests/subfolder/subpage/', $child2Links[0]); + $this->assertStringEndsWith('2.4/en/DocumentationViewerTests/subfolder/subsubfolder/', $child2Links[1]); + } + + function testRouting() { + $response = $this->get('dev/docs/2.4/en/DocumentationViewerTests/test'); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertContains('english test', $response->getBody(), 'Toplevel content page'); + } + + // function testGetPage() { + // $v = new DocumentationViewer(); + // $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/cms')); + // $p = $v->getPage(); + // $this->assertType('DocumentationPage', $p); + // $this->assertEquals('/', $p->getRelativePath()); + // $this->assertEquals('en', $p->getLang()); + // $this->assertEquals('2.4', $p->getVersion()); + // } + } \ No newline at end of file diff --git a/tests/docs/en/subfolder/subpage.md b/tests/docs/en/subfolder/subpage.md new file mode 100644 index 0000000..8b1a28a --- /dev/null +++ b/tests/docs/en/subfolder/subpage.md @@ -0,0 +1,5 @@ +[link: absolute index](/) +[link: absolute index with name](/index) +[link: relative index](../) +[link: relative parent page](../test) +[link: absolute parent page](/test) \ No newline at end of file diff --git a/tests/docs/en/subfolder/subsubfolder/subsubpage.md b/tests/docs/en/subfolder/subsubfolder/subsubpage.md new file mode 100644 index 0000000..ee68140 --- /dev/null +++ b/tests/docs/en/subfolder/subsubfolder/subsubpage.md @@ -0,0 +1,5 @@ +[link: absolute index](/) +[link: relative index](../) +[link: relative parent page](../subpage) +[link: relative grandparent page](../../test) +[link: absolute page](/test) \ No newline at end of file diff --git a/tests/docs/en/test.md b/tests/docs/en/test.md index 9769498..bc03e35 100644 --- a/tests/docs/en/test.md +++ b/tests/docs/en/test.md @@ -2,4 +2,10 @@ test -1.0 \ No newline at end of file +1.0 + +[link: subfolder index](subfolder/) +[link: subfolder page](subfolder/subpage) +[link: with anchor](/test#anchor) +[link: http](http://silverstripe.org) +[link: api](api:DataObject) \ No newline at end of file