time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

doctool.js (3463B)


      1 /*
      2    Process a single doc file
      3 
      4    argv[2] = template file
      5    argv[3] = input file
      6    argv[4] = output file
      7 */
      8 
      9 var fs = require("fs");
     10 var path = require("path");
     11 var markdown = require("./lib/markdown");
     12 var argv = process.argv;
     13 var argc = argv.length;
     14 var template = fs.readFileSync(argv[2], "utf8");
     15 
     16 
     17 function formatIdString( str ) {
     18   str = str
     19       .replace(/\([^)}]*\)/gmi, "")
     20       .replace(/[^A-Za-z0-9_.]+/gmi, "_");
     21   return str.substr(0, 1).toLowerCase() + str.substr(1);
     22 }
     23 
     24 
     25 function generateToc(data) {
     26   var last_level = 0;
     27   var first_level = 0;
     28   var toc = [ '<div id="toc">', '<h2>Table Of Contents</h2>' ];
     29 
     30   data.replace(/(^#+)\W+([^$\n]+)/gmi, function(src, level, text) {
     31     level = level.length;
     32 
     33     if (first_level == 0) first_level = level;
     34 
     35     if (level <= last_level) toc.push("</li>");
     36 
     37     if (level > last_level) {
     38       toc.push("<ul>");
     39     } else if (level < last_level) {
     40       for (var c = last_level-level; 0 < c ; c--) {
     41         toc.push("</ul>");
     42         toc.push("</li>");
     43       }
     44     }
     45 
     46     toc.push("<li>");
     47     toc.push('<a href="#'+formatIdString(text)+'">'+text+'</a>');
     48 
     49     last_level = level;
     50   });
     51 
     52   for (var c = last_level-first_level; 0 <= c ; c--) {
     53     toc.push("</li>");
     54     toc.push("</ul>");
     55   }
     56 
     57   toc.push("<hr />")
     58   toc.push("</div>");
     59 
     60   return toc.join("");
     61 }
     62 
     63 
     64 var includeExpr = /^@include\s+([A-Za-z0-9-_]+)(?:\.)?([a-zA-Z]*)$/gmi;
     65 // Allow including other pages in the data.
     66 function loadIncludes(data, current_file) {
     67   return data.replace(includeExpr, function(src, name, ext) {
     68     try {
     69       var include_path =
     70           path.join(current_file, "../", name+"."+(ext || "markdown"))
     71       return loadIncludes(fs.readFileSync(include_path, "utf8"), current_file);
     72     } catch(e) {
     73       return "";
     74     }
     75   });
     76 }
     77 
     78 
     79 function convertData(data) {
     80   // Convert it to HTML from Markdown
     81   var html = markdown.toHTML(markdown.parse(data), {xhtml:true})
     82       .replace(/<hr><\/hr>/g, "<hr />")
     83       .replace(/\.md/g, ".html")
     84       .replace(/(\<h[2-6])\>([^<]+)(\<\/h[1-6]\>)/gmi, function(o, ts, c, te) {
     85         return ts+' id="'+formatIdString(c)+'">'+c+te;
     86       });
     87 
     88   return html;
     89 }
     90 
     91 
     92 if (argc > 3) {
     93   var filename = argv[3];
     94   var output = template;
     95   var version = require(__dirname + '/../package.json').version;
     96   var html;
     97 
     98   fs.readFile(filename, "utf8", function(err, data) {
     99     if (err) throw err;
    100 
    101     // go recursion.
    102     data = loadIncludes(data, filename);
    103     // go markdown.
    104     html = convertData(data);
    105     filename = path.basename(filename, '.md');
    106 
    107     if (filename != "_toc" && filename != "index") {
    108       if (data) {
    109         html = generateToc(data) + "\n" + html;
    110       }
    111 
    112       var nfilename =
    113         filename.replace(/[_-]/g, ' ').replace(/\w\S*/g, function(txt){
    114           return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
    115         });
    116       output = output.replace(/{{section}}/g, nfilename)
    117     } else {
    118       output = output.replace(/{{section}}/g, "");
    119       output = output.replace(/<body([^>]*)>/,
    120                               '<body class="'+filename+'" $1>');
    121     }
    122 
    123     if (html.length == 0) {
    124       html = "Sorry, this section is currently undocumented, \
    125       but we'll be working on it.";
    126     }
    127     output = output.replace(/{{content}}/g, html);
    128 
    129     output = output.replace(/{{version}}/g, 'v' + version);
    130 
    131     if (argc > 4) {
    132       fs.writeFileSync(argv[4], output);
    133     } else {
    134       process.stdout.write(output);
    135     }
    136   });
    137 }