diff --git a/code/DocumentationParser.php b/code/DocumentationParser.php index 7cb77e2..c4f2d04 100755 --- a/code/DocumentationParser.php +++ b/code/DocumentationParser.php @@ -12,11 +12,6 @@ class DocumentationParser const CODE_BLOCK_BACKTICK = 1; const CODE_BLOCK_COLON = 2; - /** - * @var string Format string for api urls. See rewrite_api_links(). - */ - public static $api_link_base = 'http://api.silverstripe.org/search/lookup/?q=%s&version=%s&module=%s'; - /** * @var array */ @@ -299,49 +294,73 @@ class DocumentationParser * (6) [Title](api:DataObject->populateDefaults()) gets re-written to * Title * - * The markdown parser gets confused by the extra pair of parentheses in links of the form [DataObject](api:DataObject->populateDefaults()) so + * The above api links can be enclosed in backticks. + * + * The markdown parser gets confused by the extra pair of parentheses in links of the form [DataObject](api:DataObject->populateDefaults()) so * all links are re-written as html markup instead of markdown [Title](url). This also prevents other markdown parsing problems. * * @param String $md * @param DocumentationPage $page * @return String */ - public static function rewrite_api_links($md, $page) + public static function rewrite_api_links($markdown, $doc_page) { - + + $version = $doc_page->getVersion(); + $module = $doc_page->getEntity()->getKey(); + + // define regexs of the api links to be parsed (note: do not include backticks) $regexs = array( - 'title_and_method' => '\[(.*?)\]\(api:(.*?\(\))\)', // title_and_method handles case (6) and must precede title_remaining - 'title_remaining' => '\[(.*?)\]\(api:(.*?)\)', // title_and_remaining handles cases (4) and (5) - 'no_title' => '\[api:(.*?)\]' // no_title handles cases (1),(2) and (3) + 'title_and_method' => '# \[ ([^\]]*) \] \( api: ([^\)]*\(\)) \) #x', // title_and_method = (6) (must be first) + 'title_remaining' => '# \[ ([^\]]*) \] \( api: ([^\)]*) \) #x', // title_and_remaining = (4) and (5) + 'no_title' => '# \[ api: ([^\]]*) \] #x' // no_title = (1),(2) and (3) ); - - foreach($regexs as $regex_type => $regex) { - $link_regex = '/ `? '. $regex . ' `? /x'; - preg_match_all($link_regex, $md, $links); + + // define output format for parsing api links without backticks into html + $html_format = '%s'; + + // parse api links without backticks into html + foreach($regexs as $type => $regex) { + preg_match_all($regex, $markdown, $links); if($links) { foreach($links[0] as $i => $match) { - if( $regex_type === 'no_title' ){ + if($type === 'no_title'){ $title = $links[1][$i]; $link = $links[1][$i]; + // change backticked links to avoid being parsed in the same way as non-backticked links + $markdown = str_replace('`'.$match.'`','SS'.$link.'SS',$markdown); } else { $title = $links[1][$i]; $link = $links[2][$i]; + // change backticked links to avoid being parsed in the same way as non-backticked links + $markdown = str_replace('`'.$match.'`','XX'.$title.'YY'.$link.'ZZ',$markdown); } - $url = sprintf( - self::$api_link_base, - $link, - $page->getVersion(), - $page->getEntity()->getKey() - ); - $md = str_replace( - $match, - sprintf('%s', $url, $title), - $md - ); + $html = sprintf($html_format, $link, $version, $module, $title); + $markdown = str_replace($match,$html,$markdown); } - } + } } - return $md; + + // recover backticked links with no titles + preg_match_all('#SS(.*)?SS#', $markdown, $links); + if($links) { + foreach($links[0] as $i => $match) { + $link = $links[1][$i]; + $markdown = str_replace($match,'`[api:'.$link.']`',$markdown); + } + } + + // recover backticked links with titles + preg_match_all('#XX(.*)?YY(.*)?ZZ#', $markdown, $links); + if($links) { + foreach($links[0] as $i => $match) { + $title = $links[1][$i]; + $link = $links[2][$i]; + $markdown = str_replace($match,'`['.$title.'](api:'.$link.')`',$markdown); + } + } + + return $markdown; } diff --git a/tests/DocumentationParserTest.php b/tests/DocumentationParserTest.php index 651cd53..83e6e1e 100755 --- a/tests/DocumentationParserTest.php +++ b/tests/DocumentationParserTest.php @@ -196,12 +196,7 @@ HTML; '[link: http](http://silverstripe.org)', $result ); - $this->assertContains( - '[link: api](api:DataObject)', - $result - ); - $result = DocumentationParser::rewrite_relative_links( $this->subPage->getMarkdown(), $this->subPage @@ -325,21 +320,28 @@ HTML; $page_version = $this->page->getVersion(); // expected url format resulting from rewriting api shortcode links - $url_format = '%s'; + $html_format = '%s'; - // test cases: api shortcode references and the expected urls resulting from rewriting them + // test cases: non-backtick enclosed api links and the expected html resulting from rewriting them + // note that api links enclosed in backticks are left unchanged $test_cases = array( - array('[api:DataObject]', sprintf($url_format,'DataObject','DataObject')), - array('[api:DataObject::$defaults]',sprintf($url_format,'DataObject::$defaults','DataObject::$defaults')), - array('[api:DataObject::populateDefaults()]',sprintf($url_format,'DataObject::populateDefaults()','DataObject::populateDefaults()')), - array('[Title](api:DataObject)',sprintf($url_format,'DataObject','Title')), - array('[Title](api:DataObject::$defaults)',sprintf($url_format,'DataObject::$defaults','Title')), - array('[Title](api:DataObject::populateDefaults())',sprintf($url_format,'DataObject::populateDefaults()','Title')) + array('`[api:DataObject]`','`[api:DataObject]`'), + array('`[api:DataObject::$defaults]`','`[api:DataObject::$defaults]`'), + array('`[api:DataObject::populateDefaults()]`','`[api:DataObject::populateDefaults()]`'), + array('`[Title](api:DataObject)`','`[Title](api:DataObject)`'), + array('`[Title](api:DataObject::$defaults)`','`[Title](api:DataObject::$defaults)`'), + array('`[Title](api:DataObject::populateDefaults())`','`[Title](api:DataObject::populateDefaults())`'), + array('[api:DataObject]', sprintf($html_format,'DataObject','DataObject')), + array('[api:DataObject::$defaults]',sprintf($html_format,'DataObject::$defaults','DataObject::$defaults')), + array('[api:DataObject::populateDefaults()]',sprintf($html_format,'DataObject::populateDefaults()','DataObject::populateDefaults()')), + array('[Title](api:DataObject)',sprintf($html_format,'DataObject','Title')), + array('[Title](api:DataObject::$defaults)',sprintf($html_format,'DataObject::$defaults','Title')), + array('[Title](api:DataObject::populateDefaults())',sprintf($html_format,'DataObject::populateDefaults()','Title')) ); foreach($test_cases as $test_case) { - $expected_api_url = $test_case[1]; - $this->assertContains($expected_api_url,$parsed_page); + $expected_html = $test_case[1]; + $this->assertContains($expected_html,$parsed_page); } } diff --git a/tests/docs/en/test.md b/tests/docs/en/test.md index e5f56fb..082763e 100755 --- a/tests/docs/en/test.md +++ b/tests/docs/en/test.md @@ -8,14 +8,19 @@ test [link: subfolder page](subfolder/subpage) [link: with anchor](/test#anchor) [link: http](http://silverstripe.org) -[link: api](api:DataObject) -[api:DataObject] -[api:DataObject::$defaults] -[api:DataObject::populateDefaults()] +`[Title](api:DataObject)` +`[Title](api:DataObject::$defaults)` +`[Title](api:DataObject::populateDefaults())` +`[api:DataObject]` +`[api:DataObject::$defaults]` +`[api:DataObject::populateDefaults()]` [Title](api:DataObject) [Title](api:DataObject::$defaults) [Title](api:DataObject::populateDefaults()) +[api:DataObject] +[api:DataObject::$defaults] +[api:DataObject::populateDefaults()] :::php code block