Example #1
0
 /**
  * Generates Markdown from JSDoc entries.
  *
  * @memberOf Generator
  * @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 . ($entry->isPlugin() ? '.prototype.' : '.') : '') . $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[] = Generator::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 . '`', Generator::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[] = Generator::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('/ +\\n/', "\n", join($result, "\n")));
 }
Example #2
0
 /**
  * Generates Markdown from JSDoc entries.
  *
  * @memberOf Generator
  * @returns {String} The rendered Markdown.
  */
 public function generate()
 {
     $api = array();
     $compiling = false;
     $openTag = "\n<!-- div -->\n";
     $closeTag = "\n<!-- /div -->\n";
     $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 (!isset($api[$member]) && $member) {
                 // create temporary entry to be replaced later
                 $api[$member] = new Entry('', '', $entry->lang);
                 $api[$member]->static = array();
                 $api[$member]->plugin = array();
             }
             // append entry to api category
             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] = $alias;
                     $alias->static = array();
                     $alias->plugin = array();
                 }
             } 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;
                         }
                     }
                 }
             }
         }
     }
     /*------------------------------------------------------------------------*/
     // 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 keys that represent constructor 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});
         }
     }
     /*------------------------------------------------------------------------*/
     // compile TOC
     $result[] = $openTag;
     foreach ($api as $key => $entry) {
         $entry->hash = $this->getHash($entry);
         $entry->href = $this->getLineUrl($entry);
         $member = $entry->getMembers(0);
         $member = ($member ? $member . ($entry->isPlugin() ? '.prototype.' : '.') : '') . $entry->getName();
         $entry->member = preg_replace('/' . $entry->getName() . '$/', '', $member);
         $compiling = $compiling ? $result[] = $closeTag : true;
         // assign TOC hash
         if (count($result) == 2) {
             $toc = $member;
         }
         // add root entry
         array_push($result, $openTag, '## ' . (count($result) == 2 ? '<a id="' . $toc . '"></a>' : '') . '`' . $member . '`', Generator::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->hash = $this->getHash($subentry);
                 $subentry->href = $this->getLineUrl($subentry);
                 $subentry->member = $member;
                 $subentry->separator = $this->getSeparator($subentry);
                 $result[] = Generator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $subentry);
             }
         }
     }
     array_push($result, $closeTag, $closeTag);
     /*------------------------------------------------------------------------*/
     // compile content
     $compiling = false;
     $result[] = $openTag;
     foreach ($api as $entry) {
         // skip aliases
         if ($entry->isAlias()) {
             continue;
         }
         // add root entry
         $member = $entry->member . $entry->getName();
         $compiling = $compiling ? $result[] = $closeTag : true;
         array_push($result, $openTag, '## `' . $member . '`');
         foreach (array($entry, 'static', 'plugin') as $kind) {
             $subentries = is_string($kind) ? $entry->{$kind} : array($kind);
             // title
             if ($kind != 'static' && $entry->getType() != 'Object' && count($subentries) && $subentries[0] != $kind) {
                 if ($kind == 'plugin') {
                     $result[] = $closeTag;
                 }
                 array_push($result, $openTag, '## `' . $member . ($kind == 'plugin' ? '.prototype`' : '`'));
             }
             // body
             foreach ($subentries as $subentry) {
                 // skip aliases
                 if ($subentry->isAlias()) {
                     continue;
                 }
                 // description
                 array_push($result, $openTag, Generator::interpolate("### <a id=\"#{hash}\"></a>`#{member}#{separator}#{call}`\n<a href=\"##{hash}\">#</a> [&#x24C8;](#{href} \"View in source\") [&#x24C9;][1]\n\n#{desc}", $subentry));
                 // @alias
                 if (count($aliases = $subentry->getAliases())) {
                     array_push($result, '', '#### Aliases');
                     foreach ($aliases as $index => $alias) {
                         $aliases[$index] = $alias->getName();
                     }
                     $result[] = '*' . implode(', ', $aliases) . '*';
                 }
                 // @param
                 if (count($params = $subentry->getParams())) {
                     array_push($result, '', '#### Arguments');
                     foreach ($params as $index => $param) {
                         $result[] = Generator::interpolate('#{num}. `#{name}` (#{type}): #{desc}', array('desc' => $param[2], 'name' => $param[1], 'num' => $index + 1, 'type' => $param[0]));
                     }
                 }
                 // @returns
                 if (count($returns = $subentry->getReturns())) {
                     array_push($result, '', '#### Returns', Generator::interpolate('(#{type}): #{desc}', array('desc' => $returns[1], 'type' => $returns[0])));
                 }
                 // @example
                 if ($example = $subentry->getExample()) {
                     array_push($result, '', '#### Example', $example);
                 }
                 array_push($result, "\n* * *", $closeTag);
             }
         }
     }
     // close tags add TOC link reference
     array_push($result, $closeTag, $closeTag, '', '  [1]: #' . $toc . ' "Jump back to the TOC."');
     // cleanup whitespace
     return trim(preg_replace('/ +\\n/', "\n", join($result, "\n")));
 }