Skip to content
This repository has been archived by the owner on Mar 16, 2023. It is now read-only.

Commit

Permalink
Merge pull request #94 from SpiritLevel/master
Browse files Browse the repository at this point in the history
Further tidy up of api link parsing and testing
  • Loading branch information
dhensby committed Jan 24, 2016
2 parents bad24d8 + 26c66f4 commit f70d5fd
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 48 deletions.
77 changes: 48 additions & 29 deletions code/DocumentationParser.php
Expand Up @@ -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
*/
Expand Down Expand Up @@ -299,49 +294,73 @@ public static function rewrite_image_links($md, $page)
* (6) [Title](api:DataObject->populateDefaults()) gets re-written to
* <a href="https://api.silverstripe.org/search/lookup/?q=DataObject::populateDefaults()&version=2.4&module=framework">Title</a>
*
* 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 = '<a href="http://api.silverstripe.org/search/lookup/?q=%s&version=%s&module=%s">%s</a>';

// 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('<a href="%s">%s</a>', $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;

}

Expand Down
32 changes: 17 additions & 15 deletions tests/DocumentationParserTest.php
Expand Up @@ -196,12 +196,7 @@ public function testRelativeLinks()
'[link: http](http://silverstripe.org)',
$result
);
$this->assertContains(
'[link: api](api:DataObject)',
$result
);


$result = DocumentationParser::rewrite_relative_links(
$this->subPage->getMarkdown(),
$this->subPage
Expand Down Expand Up @@ -325,21 +320,28 @@ public function testApiLinks()
$page_version = $this->page->getVersion();

// expected url format resulting from rewriting api shortcode links
$url_format = '<a href="http://api.silverstripe.org/search/lookup/?q=%s&version='.$page_version.'&module=documentationparsertest">%s</a>';
$html_format = '<a href="http://api.silverstripe.org/search/lookup/?q=%s&version='.$page_version.'&module=documentationparsertest">%s</a>';

// 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);
}

}
Expand Down
13 changes: 9 additions & 4 deletions tests/docs/en/test.md
Expand Up @@ -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
Expand Down

0 comments on commit f70d5fd

Please sign in to comment.