Exemple #1
0
 /**
  * Generates Markdown from JSDoc entries.
  *
  * @memberOf MarkdownGenerator
  * @returns {string} The rendered Markdown.
  */
 public function generate()
 {
     $api = array();
     $byCategory = $this->options['toc'] == 'categories';
     $categories = array();
     $closeTag = $this->closeTag;
     $compiling = false;
     $openTag = $this->openTag;
     $result = array('# ' . $this->options['title']);
     $toc = 'toc';
     // initialize $api array
     foreach ($this->entries as $entry) {
         // skip invalid or private entries
         $name = $entry->getName();
         if (!$name || $entry->isPrivate()) {
             continue;
         }
         $members = $entry->getMembers();
         $members = count($members) ? $members : array('');
         foreach ($members as $member) {
             // create api category arrays
             if ($member && !isset($api[$member])) {
                 // create temporary entry to be replaced later
                 $api[$member] = new stdClass();
                 $api[$member]->static = array();
                 $api[$member]->plugin = array();
             }
             // append entry to api member
             if (!$member || $entry->isCtor() || $entry->getType() == 'Object' && !preg_match('/[=:]\\s*(?:null|undefined)\\s*[,;]?$/', $entry->entry)) {
                 // assign the real entry, replacing the temporary entry if it exist
                 $member = ($member ? $member . ($entry->isPlugin() ? '#' : '.') : '') . $name;
                 $entry->static = @$api[$member] ? $api[$member]->static : array();
                 $entry->plugin = @$api[$member] ? $api[$member]->plugin : array();
                 $api[$member] = $entry;
                 foreach ($entry->getAliases() as $alias) {
                     $api[$member]->static[] = $alias;
                 }
             } else {
                 if ($entry->isStatic()) {
                     $api[$member]->static[] = $entry;
                     foreach ($entry->getAliases() as $alias) {
                         $api[$member]->static[] = $alias;
                     }
                 } else {
                     if (!$entry->isCtor()) {
                         $api[$member]->plugin[] = $entry;
                         foreach ($entry->getAliases() as $alias) {
                             $api[$member]->plugin[] = $alias;
                         }
                     }
                 }
             }
         }
     }
     // add properties to each entry
     foreach ($api as $entry) {
         $entry->hash = $this->getHash($entry);
         $entry->href = $this->getLineUrl($entry);
         $member = $entry->getMembers(0);
         $member = ($member ? $member . $this->getSeparator($entry) : '') . $entry->getName();
         $entry->member = preg_replace('/' . $entry->getName() . '$/', '', $member);
         // add properties to static and plugin sub-entries
         foreach (array('static', 'plugin') as $kind) {
             foreach ($entry->{$kind} as $subentry) {
                 $subentry->hash = $this->getHash($subentry);
                 $subentry->href = $this->getLineUrl($subentry);
                 $subentry->member = $member;
                 $subentry->separator = $this->getSeparator($subentry);
             }
         }
     }
     /*------------------------------------------------------------------------*/
     // custom sort for root level entries
     // TODO: see how well it handles deeper namespace traversal
     function sortCompare($a, $b)
     {
         $score = array('a' => 0, 'b' => 0);
         foreach (array('a' => $a, 'b' => $b) as $key => $value) {
             // capitalized properties are last
             if (preg_match('/[#.][A-Z]/', $value)) {
                 $score[$key] = 0;
             } else {
                 if (preg_match('/#[a-z]/', $value)) {
                     $score[$key] = 1;
                 } else {
                     if (preg_match('/\\.[a-z]/', $value)) {
                         $score[$key] = 2;
                     } else {
                         if (preg_match('/^[^#.]+$/', $value)) {
                             $score[$key] = 3;
                         }
                     }
                 }
             }
         }
         $score = $score['b'] - $score['a'];
         return $score ? $score : strcasecmp($a, $b);
     }
     uksort($api, 'sortCompare');
     // sort static and plugin sub-entries
     foreach ($api as $entry) {
         foreach (array('static', 'plugin') as $kind) {
             $sortBy = array('a' => array(), 'b' => array(), 'c' => array());
             foreach ($entry->{$kind} as $subentry) {
                 $name = $subentry->getName();
                 // functions w/o ALL-CAPs names are last
                 $sortBy['a'][] = $subentry->getType() == 'Function' && !preg_match('/^[A-Z_]+$/', $name);
                 // ALL-CAPs properties first
                 $sortBy['b'][] = preg_match('/^[A-Z_]+$/', $name);
                 // lowercase alphanumeric sort
                 $sortBy['c'][] = strtolower($name);
             }
             array_multisort($sortBy['a'], SORT_ASC, $sortBy['b'], SORT_DESC, $sortBy['c'], SORT_ASC, $entry->{$kind});
         }
     }
     /*------------------------------------------------------------------------*/
     // add categories
     foreach ($api as $entry) {
         $categories[$entry->getCategory()][] = $entry;
         foreach (array('static', 'plugin') as $kind) {
             foreach ($entry->{$kind} as $subentry) {
                 $categories[$subentry->getCategory()][] = $subentry;
             }
         }
     }
     // sort categories
     ksort($categories);
     foreach (array('Methods', 'Properties') as $category) {
         if (isset($categories[$category])) {
             $entries = $categories[$category];
             unset($categories[$category]);
             $categories[$category] = $entries;
         }
     }
     /*------------------------------------------------------------------------*/
     // compile TOC
     $result[] = $openTag;
     // compile TOC by categories
     if ($byCategory) {
         foreach ($categories as $category => $entries) {
             if ($compiling) {
                 $result[] = $closeTag;
             } else {
                 $compiling = true;
             }
             // assign TOC hash
             if (count($result) == 2) {
                 $toc = $category;
             }
             // add category
             array_push($result, $openTag, '## ' . (count($result) == 2 ? '<a id="' . $toc . '"></a>' : '') . '`' . $category . '`');
             // add entries
             foreach ($entries as $entry) {
                 $result[] = MarkdownGenerator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $entry);
             }
         }
     } else {
         foreach ($api as $entry) {
             if ($compiling) {
                 $result[] = $closeTag;
             } else {
                 $compiling = true;
             }
             $member = $entry->member . $entry->getName();
             // assign TOC hash
             if (count($result) == 2) {
                 $toc = $member;
             }
             // add root entry
             array_push($result, $openTag, '## ' . (count($result) == 2 ? '<a id="' . $toc . '"></a>' : '') . '`' . $member . '`', MarkdownGenerator::interpolate('* [`' . $member . '`](##{hash})', $entry));
             // add static and plugin sub-entries
             foreach (array('static', 'plugin') as $kind) {
                 if ($kind == 'plugin' && count($entry->plugin)) {
                     array_push($result, $closeTag, $openTag, '## `' . $member . ($entry->isCtor() ? '.prototype`' : '`'));
                 }
                 foreach ($entry->{$kind} as $subentry) {
                     $subentry->member = $member;
                     $result[] = MarkdownGenerator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $subentry);
                 }
             }
         }
     }
     array_push($result, $closeTag, $closeTag);
     /*------------------------------------------------------------------------*/
     // compile content
     $compiling = false;
     $result[] = $openTag;
     if ($byCategory) {
         foreach ($categories as $category => $entries) {
             if ($compiling) {
                 $result[] = $closeTag;
             } else {
                 $compiling = true;
             }
             if ($category != 'Methods' && $category != 'Properties') {
                 $category = '“' . $category . '” Methods';
             }
             array_push($result, $openTag, '## `' . $category . '`');
             $this->addEntries($result, $entries);
         }
     } else {
         foreach ($api as $entry) {
             // skip aliases
             if ($entry->isAlias()) {
                 continue;
             }
             if ($compiling) {
                 $result[] = $closeTag;
             } else {
                 $compiling = true;
             }
             // add root entry name
             $member = $entry->member . $entry->getName();
             array_push($result, $openTag, '## `' . $member . '`');
             foreach (array($entry, 'static', 'plugin') as $kind) {
                 $subentries = is_string($kind) ? $entry->{$kind} : array($kind);
                 // add sub-entry name
                 if ($kind != 'static' && $entry->getType() != 'Object' && count($subentries) && $subentries[0] != $kind) {
                     if ($kind == 'plugin') {
                         $result[] = $closeTag;
                     }
                     array_push($result, $openTag, '## `' . $member . ($kind == 'plugin' ? '.prototype`' : '`'));
                 }
                 $this->addEntries($result, $subentries);
             }
         }
     }
     // close tags add TOC link reference
     array_push($result, $closeTag, $closeTag, '', '  [1]: #' . $toc . ' "Jump back to the TOC."');
     // cleanup whitespace
     return trim(preg_replace('/[\\t ]+\\n/', "\n", join($result, "\n")));
 }
Exemple #2
0
/**
 * Generates Markdown from JSDoc entries in a given file.
 *
 * @param {Array} [$options=array()] The options array.
 * @returns {string} The generated Markdown.
 * @example
 *
 * // specify a file path
 * $markdown = docdown(array(
 *   // path to js file
 *   'path' => $filepath,
 *   // url used to reference line numbers in code
 *   'url' => 'https://github.com/username/project/blob/master/my.js'
 * ));
 *
 * // or pass raw js
 * $markdown = docdown(array(
 *   // raw JavaScript source
 *   'source' => $rawJS,
 *   // documentation title
 *   'title' => 'My API Documentation',
 *   // url used to reference line numbers in code
 *   'url' => 'https://github.com/username/project/blob/master/my.js'
 * ));
 */
function docdown($options = array())
{
    $gen = new MarkdownGenerator($options);
    return $gen->generate();
}