Code coverage report for lib/output/markdown_ast.js

Statements: 100% (40 / 40)      Branches: 100% (36 / 36)      Functions: 100% (21 / 21)      Lines: 100% (40 / 40)      Ignored: none     

All files » lib/output/ » markdown_ast.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 17025                             25 80     80                   25   25 102 172                                     25 152           25 152           25 20   36                           25 152   13 13       25 152 60               25 152       10           25 152                   25 152   760 10   760   152     10                 152                     14       6         80 132       25  
var mdast = require('mdast'),
  u = require('unist-builder'),
  formatType = require('documentation-theme-utils').formatType,
  formatInlineTags = require('../format_inline_tags'),
  hljs = require('highlight.js');
 
/**
 * Given a hierarchy-nested set of comments, generate an mdast-compatible
 * Abstract Syntax Tree usable for generating Markdown output
 *
 * @param {Array<Object>} comments nested comment
 * @param {Object} opts currently none accepted
 * @param {Function} callback called with AST
 * @returns {undefined} calls callback
 */
function commentsToAST(comments, opts, callback) {
  var hljsOptions = (opts || {}).hljs || {},
    language = !hljsOptions.highlightAuto ? 'javascript' : undefined;
 
  hljs.configure(hljsOptions);
 
  /**
   * Generate an AST chunk for a comment at a given depth: this is
   * split from the main function to handle hierarchially nested comments
   *
   * @param {number} depth nesting of the comment, starting at 1
   * @param {Object} comment a single comment
   * @returns {Object} mdast-compatible AST
   */
  function generate(depth, comment) {
 
    function paramList(params) {
      return u('list', { ordered: false }, params.map(function (param) {
        return u('listItem', [
          u('paragraph', [
            u('inlineCode', param.name),
            u('text', ' '),
            !!param.type && u('strong', formatType(param.type)),
            u('text', ' ')
          ].concat(mdast.parse(formatInlineTags(param.description)).children)
          .concat([
            !!param.default && u('paragraph', [
              u('text', ' (optional, default '),
              u('inlineCode', param.default),
              u('text', ')')
            ])
          ]).filter(Boolean))
        ].concat(param.properties && paramList(param.properties))
        .filter(Boolean));
      }));
    }
 
    function paramSection(comment) {
      return !!comment.params && [
        u('strong', [u('text', 'Parameters')]),
        paramList(comment.params)
      ];
    }
 
    function propertySection(comment) {
      return !!comment.properties && [
        u('strong', [u('text', 'Properties')]),
        propertyList(comment.properties)
      ];
    }
 
    function propertyList(properties) {
      return u('list', { ordered: false },
        properties.map(function (property) {
          return u('listItem', [
            u('paragraph', [
              u('inlineCode', property.name),
              u('text', ' '),
              u('strong', formatType(property.type)),
              u('text', ' ')
            ]
            .concat(mdast.parse(formatInlineTags(property.description)).children)
            .filter(Boolean)),
            property.properties && propertyList(property.properties)
          ].filter(Boolean));
        }));
    }
 
    function examplesSection(comment) {
      return !!comment.examples && [u('strong', [u('text', 'Examples')])]
        .concat(comment.examples.map(function (example) {
          language = hljsOptions.highlightAuto ? hljs.highlightAuto(example).language : 'javascript';
          return u('code', { lang: language }, example);
        }));
    }
 
    function returnsSection(comment) {
      return !!comment.returns && comment.returns.map(function (returns) {
        return u('paragraph', [
          u('text', 'Returns '),
          u('strong', formatType(returns.type)),
          u('text', ' ')
        ].concat(mdast.parse(formatInlineTags(returns.description)).children));
      });
    }
 
    function augmentsLink(comment) {
      return comment.augments && u('paragraph', [
        u('strong', [
          u('text', 'Extends '),
          u('text', comment.augments.map(function (tag) {
            return tag.name;
          }).join(', '))
        ])
      ]);
    }
 
    function githubLink(comment) {
      return comment.context.github && u('paragraph', [
        u('link', {
          title: 'Source code on GitHub',
          href: comment.context.github
        }, [u('text', comment.context.path + ':' +
          comment.context.loc.start.line + '-' +
          comment.context.loc.end.line)])
      ]);
    }
 
    function metaSection(comment) {
      var meta = ['version', 'since', 'copyright', 'author', 'license']
        .reduce(function (memo, tag) {
          if (comment[tag]) {
            memo.push({ tag: tag, value: comment[tag] });
          }
          return memo;
        }, []);
      return !!meta.length && [u('strong', [u('text', 'Meta')])].concat(
        u('list', { ordered: false },
          meta.map(function (item) {
            return u('listItem', [
              u('paragraph', [
                u('strong', [u('text', item.tag)]),
                u('text', ': ' + item.value)
              ])
            ]);
          })));
    }
 
    return [u('heading', { depth: depth }, [u('text', comment.name)])]
    .concat(githubLink(comment))
    .concat(augmentsLink(comment))
    .concat(mdast.parse(formatInlineTags(comment.description)).children)
    .concat(paramSection(comment))
    .concat(propertySection(comment))
    .concat(examplesSection(comment))
    .concat(returnsSection(comment))
    .concat(metaSection(comment))
    .concat(!!comment.members.instance.length &&
      comment.members.instance.reduce(function (memo, child) {
        return memo.concat(generate(depth + 1, child));
      }, []))
    .concat(!!comment.members.static.length &&
      comment.members.static.reduce(function (memo, child) {
        return memo.concat(generate(depth + 1, child));
      }, []))
    .filter(Boolean);
  }
 
  return callback(null, u('root', comments.reduce(function (memo, comment) {
    return memo.concat(generate(1, comment));
  }, [])));
}
 
module.exports = commentsToAST;