Home Manual Reference Source Test Repository

src/Publisher/Builder/SourceDocBuilder.js

import path from 'path';
import fs from 'fs';
import IceCap from 'ice-cap';
import DocBuilder from './DocBuilder.js';
import {dateForUTC} from './util.js';

/**
 * Source output html builder class.
 */
export default class SourceDocBuilder extends DocBuilder {
  /**
   * create instance.
   * @param {Taffy} data - doc object database.
   * @param {ESDocConfig} config - use config to build output.
   * @param {CoverageObject} coverage - use coverage to build output.
   */
  constructor(data, config, coverage) {
    super(data, config);
    this._coverage = coverage;
  }

  /**
   * execute building output html.
   * @param {function(html: string, filePath: string)} callback - is called with output html.
   */
  exec(callback) {
    let ice = this._buildLayoutDoc();
    let fileName = 'source.html';
    let baseUrl = this._getBaseUrl(fileName);
    let title = this._getTitle('Source');

    ice.attr('baseUrl', 'href', baseUrl);
    ice.load('content', this._buildSourceHTML());
    ice.text('title', title, IceCap.MODE_WRITE);

    callback(ice.html, fileName);
  }

  /**
   * build source list output html.
   * @returns {string} html of source list.
   * @private
   */
  _buildSourceHTML() {
    let ice = new IceCap(this._readTemplate('source.html'));
    let docs = this._find({kind: 'file'});
    let config = this._config;
    let useCoverage = this._config.coverage;
    let coverage;
    if (useCoverage) coverage = this._coverage.files;

    ice.drop('coverageBadge', !useCoverage);
    ice.attr('files', 'data-use-coverage', !!useCoverage);

    if (useCoverage) {
      let actual = this._coverage.actualCount;
      let expect = this._coverage.expectCount;
      let coverageCount = `${actual}/${expect}`;
      ice.text('totalCoverageCount', coverageCount);
    }

    ice.loop('file', docs, (i, doc, ice)=>{
      let sourceDirPath = path.resolve(config.source);
      let filePath = doc.longname;
      let absFilePath = path.resolve(path.dirname(sourceDirPath), filePath);
      let content = fs.readFileSync(absFilePath).toString();
      let lines = content.split('\n').length - 1;
      let stat = fs.statSync(absFilePath);
      let date = dateForUTC(stat.ctime);
      let coverageRatio;
      let coverageCount;
      let undocumentLines;
      if (useCoverage && coverage[filePath]) {
        let actual = coverage[filePath].actualCount;
        let expect = coverage[filePath].expectCount;
        coverageRatio = `${Math.floor(100 * actual / expect)} %`;
        coverageCount = `${actual}/${expect}`;
        undocumentLines = coverage[filePath].undocumentLines.sort().join(',');
      } else {
        coverageRatio = '-';
      }

      let identifierDocs = this._find({
        longname: {left: `${doc.longname}~`},
        kind: ['class', 'function', 'variable']});
      let identifiers = identifierDocs.map(doc =>{
        return this._buildDocLinkHTML(doc.longname);
      });

      if (undocumentLines) {
        const url = this._getURL(doc);
        const link = this._buildFileDocLinkHTML(doc).replace(/href=".*\.html"/, `href="${url}#errorLines=${undocumentLines}"`);
        ice.load('filePath', link);
      } else {
        ice.load('filePath', this._buildFileDocLinkHTML(doc));
      }
      ice.text('coverage', coverageRatio);
      ice.text('coverageCount', coverageCount);
      ice.text('lines', lines);
      ice.text('updated', date);
      ice.text('size', `${stat.size} byte`);
      ice.load('identifier', identifiers.join('\n') || '-');
    });
    return ice.html;
  }
}