UNPKG

wat

Version:

Community-controlled cheat sheets for every coder.

366 lines (307 loc) 9.84 kB
'use strict'; var _ = require('lodash'); var rimraf = require('rimraf'); var fs = require('fs'); var chalk = require('chalk'); var util = require('../../../util'); var path = require('path'); var javascript = require('./parser.javascript'); var mdast = require('./mdast'); var markdownParser = { javascript: javascript, mdast: mdast, run: function run(name, options, callback) { callback = callback || {}; options = options || {}; var self = this; var urls = options.urls; var lang = options.language || 'javascript'; var isStatic = options['static'] || false; var aliases = options.aliases || []; var repoName = String(name).trim(); var allNames = aliases; var results = {}; var errors = []; var writeOptions = { 'static': isStatic }; allNames.push(repoName); // Set appropriate parsing language. this.mdast.language(lang); var tree = {}; var final = {}; var finalAPI = []; var finalDocs = []; function traverse(node, pth) { pth = pth || ''; for (var item in node) { if (node.hasOwnProperty(item)) { var fullPath = pth !== '' ? '' + pth + path.sep + item : String(item); if (_.isObject(node[item])) { traverse(node[item], fullPath); } else { tree[fullPath] = node[item]; } } } } traverse(urls); var done = 0; var total = Object.keys(tree).length; function doneHandler() { done++; if (options.progress) { options.progress({ total: total, downloaded: done, action: 'fetch' }); } if (done >= total) { parse(); } } function fetchOne(key, value) { util.fetchRemote(value, function (err, data) { if (!err) { results[key] = data; } else { errors.push(err); } doneHandler(); }); } for (var url in tree) { if (tree.hasOwnProperty(url)) { fetchOne(url, tree[url]); } } var autodocPath = '' + self.app.clerk.paths['static'].autodocs + repoName; var localAutodocPath = '' + self.app.clerk.paths.temp.autodocs + repoName; try { if (writeOptions['static']) { rimraf.sync(autodocPath); } rimraf.sync(localAutodocPath); } catch (e) {} if (writeOptions['static']) { util.mkdirSafe(autodocPath); } util.mkdirSafe(localAutodocPath); function parse() { if (options.progress) { options.progress({ total: 50, downloaded: 50, action: 'parse' }); } for (var result in results) { if (results.hasOwnProperty(result)) { var md = results[result]; md = self.mdast.stripHTML(md); var ast = self.mdast.parse(md); ast = self.mdast.sequenceAst(ast); var _urls = self.mdast.getUrlsFromAst(ast); var headers = self.mdast.groupByHeaders(ast); var orphans = headers.orphans; var pathParts = String(result).split('/'); var last = pathParts.pop(); var resultRoot = pathParts.length > 0 ? pathParts.join('/') : ''; var api = self.mdast.filterAPINodes(headers, allNames); api = self.mdast.buildAPIPaths(api, repoName); // Make an index for that doc set. if (headers.length === 1) { headers[0].children = [{ type: 'text', value: last, position: {} }]; } else if (headers.length > 1) { headers = [{ type: 'heading', ignore: true, depth: 1, children: [{ type: 'text', value: last, position: {} }], position: {}, fold: headers, junk: [] }]; } var docs = self.mdast.buildDocPaths(headers, '/autodocs/' + repoName + '/' + resultRoot); finalAPI = finalAPI.concat(api); finalDocs = finalDocs.concat(docs); final[result] = { api: api, docs: docs, orphans: orphans || [], headers: headers, urls: _urls }; } } if (options.progress) { options.progress({ total: 50, downloaded: 50, action: 'build' }); } var config = self.mdast.buildAPIConfig(finalAPI); var docSequence = self.mdast.buildDocConfig(finalDocs, repoName); config.docs = []; config.docSequence = docSequence; for (var doc in final) { if (final.hasOwnProperty(doc)) { config.docs.push(doc); self.writeDocSet(final[doc].docs, final[doc].orphans, writeOptions); } } if (options.progress) { options.progress({ total: 50, downloaded: 50, action: 'write' }); } if (writeOptions['static']) { self.writeConfig(autodocPath, config); } self.writeConfig(localAutodocPath, config); self.writeAPI(finalAPI, writeOptions); callback(); } }, writeConfig: function writeConfig(path, config) { try { fs.writeFileSync(path + '/config.json', JSON.stringify(config, null, ' ')); } catch (e) { console.log('\n\n' + chalk.yellow(' In building an autodoc, Wat couldn\'t write its config file.') + '\n'); throw new Error(e); } }, writeDocSet: function writeDocSet(docs, orphans, options) { options = options || {}; var result = ''; var orphanString = ''; for (var i = 0; i < orphans.length; ++i) { orphanString += mdast.stringify(orphans[i]) + '\n\n'; } for (var i = 0; i < docs.length; ++i) { var local = ''; if (!docs[i].docPath) { continue; } var temp = this.app.clerk.paths.temp.root; var pth = String(docs[i].docPath); var parts = pth.split('/'); var file = parts.pop(); var directory = parts.join('/'); var fileAddon = docs[i].fold.length > 0 ? '/' + file : ''; var dir = path.join(__dirname, '/../..', directory); var tempDir = temp + directory; if (options['static']) { util.mkdirSafe(dir + fileAddon); } util.mkdirSafe(tempDir + fileAddon); docs[i].junk = docs[i].junk || []; var fullPath = docs[i].fold.length > 0 ? '/' + file + '/index.md' : '/' + file + '.md'; var header = docs[i].ignore !== true ? mdast.stringify(docs[i]) + '\n\n' : ''; var allJunk = header; for (var j = 0; j < docs[i].junk.length; ++j) { allJunk += mdast.stringify(docs[i].junk[j]) + '\n\n'; } local += allJunk; if (docs[i].fold.length > 0) { local += this.writeDocSet(docs[i].fold, [], options); } local = orphanString + local; if (options['static']) { fs.writeFileSync(dir + fullPath, local); } fs.writeFileSync(tempDir + fullPath, local); result += local; } return result; }, writeAPI: function writeAPI(api, options) { var _this = this; options = options || {}; var _loop = function (i) { var buildFolds = function buildFolds(itm) { items.push(itm); for (var j = 0; j < itm.junk.length; ++j) { items.push(itm.junk[j]); } for (var j = 0; j < itm.fold.length; ++j) { buildFolds(itm.fold[j]); } }; if (!api[i].apiPath) { return 'continue'; } var temp = _this.app.clerk.paths.temp.root; var pathStr = String(api[i].apiPath); var parts = pathStr.split('/'); var file = parts.pop(); var directory = parts.join('/'); var dir = path.join(__dirname, '/../..', directory); var tempDir = temp + directory; if (options['static']) { util.mkdirSafe(dir); } util.mkdirSafe(tempDir); var codeSampleFound = false; var basicText = '## ' + api[i].formatted + '\n\n'; var detailText = basicText; var lineX = 2; var lineXBasic = 2; var items = []; buildFolds(api[i]); for (var j = 1; j < items.length; ++j) { var item = items[j]; var lines = item.position.end.line - item.position.start.line + 1; var content = mdast.stringify(item) + '\n\n'; var isCode = item.type === 'code'; lineX += lines; var basic = undefined; if (lineX <= 20) { basic = true; } else if (lineX - lines > 10 && codeSampleFound) { basic = false; } else if (lineX > 20 && !codeSampleFound && isCode && lineX < 40) { basic = true; } if (basic) { lineXBasic = lineX; basicText += content; } detailText += content; if (isCode) { codeSampleFound = true; } } // If detail has no more content than // basic, just get rid of it. if (lineX === lineXBasic) { detailText = ''; } try { fs.writeFileSync('' + tempDir + path.sep + file + '.md', basicText, 'utf-8'); if (options['static']) { fs.writeFileSync('' + dir + path.sep + file + '.md', basicText, 'utf-8'); } if (detailText !== '') { fs.writeFileSync('' + tempDir + path.sep + file + '.detail.md', detailText, 'utf-8'); if (options['static']) { fs.writeFileSync('' + dir + path.sep + file + '.detail.md', detailText, 'utf-8'); } } } catch (e) { throw new Error(e); } }; for (var i = 0; i < api.length; ++i) { var _ret = _loop(i); if (_ret === 'continue') continue; } } }; module.exports = function (app) { markdownParser.app = app; return markdownParser; };