Mailspring/packages/client-app/build/tasks/docs-task.js
Evan Morikawa a7686bb35b [client-app] build tasks now use absolute paths
Summary:
Grunt is hardcoded to use paths relative to wherever the Gruntfile is
located. Unfortunately it also expects the grunt packages to be siblings
of that gruntfile. We can get around this by changing the relative base
path, but then the cwd is different for each tasks. This is okay as long
as we use absolute paths for various files in each of our tasks. This
updates our grunt tasks to use absolute paths

Test Plan: `npm run build-client`

Reviewers: spang, halla, jerm, juan

Reviewed By: juan

Differential Revision: https://phab.nylas.com/D3987
2017-02-21 14:35:51 -05:00

178 lines
5.2 KiB
JavaScript

const path = require('path');
const cjsxtransform = require('coffee-react-transform');
const rimraf = require('rimraf');
const fs = require('fs-plus');
const _ = require('underscore');
const donna = require('donna');
const joanna = require('joanna');
const tello = require('tello');
module.exports = function(grunt) {
let {cp, mkdir, rm} = grunt.config('taskHelpers');
let getClassesToInclude = function() {
let modulesPath = path.join(grunt.config('appDir'), 'internal_packages');
let classes = {};
fs.traverseTreeSync(modulesPath, function(modulePath) {
// Don't traverse inside dependencies
if (modulePath.match(/node_modules/g)) { return false; }
// Don't traverse blacklisted packages (that have docs, but we don't want to include)
if (path.basename(modulePath) !== 'package.json') { return true; }
if (!fs.isFileSync(modulePath)) { return true; }
let apiPath = path.join(path.dirname(modulePath), 'api.json');
if (fs.isFileSync(apiPath)) {
_.extend(classes, grunt.file.readJSON(apiPath).classes);
}
return true;
});
return classes;
};
let sortClasses = function(classes) {
let sortedClasses = {};
for (let className of Array.from(Object.keys(classes).sort())) {
sortedClasses[className] = classes[className];
}
return sortedClasses;
};
var processFields = function(json, fields, tasks) {
let val;
if (fields == null) { fields = []; }
if (tasks == null) { tasks = []; }
if (json instanceof Array) {
return (() => {
let result = [];
for (val of Array.from(json)) {
result.push(processFields(val, fields, tasks));
}
return result;
})();
} else {
return (() => {
let result1 = [];
for (let key in json) {
val = json[key];
let item;
if (Array.from(fields).includes(key)) {
for (let task of Array.from(tasks)) {
val = task(val);
}
json[key] = val;
}
if (_.isObject(val)) {
item = processFields(val, fields, tasks);
}
result1.push(item);
}
return result1;
})();
}
};
return grunt.registerTask('docs', 'Builds the API docs in src', function() {
grunt.log.writeln("Time to build the docs!")
let done = this.async();
// Convert CJSX into coffeescript that can be read by Donna
// let classDocsOutputDir = grunt.config.get('classDocsOutputDir');
let classDocsOutputDir = '~/Desktop/Nylas Mail Docs/'
let cjsxOutputDir = path.join(classDocsOutputDir, 'temp-cjsx');
return rimraf(cjsxOutputDir, function() {
let api;
fs.mkdir(cjsxOutputDir);
let srcPath = path.resolve(grunt.config('appDir'), 'src');
fs.traverseTreeSync(srcPath, function(file) {
if (file.indexOf('/K2/') > 0) {
// Skip K2
}
else if (path.extname(file) === '.cjsx') { // Should also look for jsx and es6
let transformed = cjsxtransform(grunt.file.read(file));
// Only attempt to parse this file as documentation if it contains
// real Coffeescript classes.
if (transformed.indexOf('\nclass ') > 0) {
grunt.log.writeln("Found class in file: " + file)
grunt.file.write(path.join(cjsxOutputDir, path.basename(file).slice(0, -5 + 1 || undefined)+'coffee'), transformed);
}
}
else if (path.extname(file) === '.jsx') {
console.log('Transforming ' + file)
let fileStr = grunt.file.read(file);
let transformed = require("babel-core").transform(fileStr, {
plugins: ["transform-react-jsx",
"transform-class-properties"],
presets: ['react', 'stage-2']
});
if (transformed.code.indexOf('class ') > 0) {
grunt.log.writeln("Found class in file: " + file)
grunt.file.write(path.join(cjsxOutputDir, path.basename(file).slice(0, -3 || undefined)+'js'), transformed.code);
}
}
return true;
});
grunt.log.ok('Done transforming, starting donna extraction')
grunt.log.writeln('cjsxOutputDir: ' + cjsxOutputDir)
// Process coffeescript source
let metadata = donna.generateMetadata([cjsxOutputDir]);
grunt.log.ok('---- Done with Donna (cjsx metadata)----');
console.log(js_files);
var js_files = []
fs.traverseTreeSync(cjsxOutputDir, function(file) {
if (path.extname(file) === '.js') {
js_files.push(file.toString())
}
});
console.log(js_files);
let jsx_metadata = joanna(js_files);
grunt.log.ok('---- Done with Joanna (jsx metadata)----');
Object.assign(metadata, jsx_metadata);
console.log(metadata);
try {
api = tello.digest(metadata);
} catch (e) {
console.log(e.stack);
}
console.log('---- Done with Tello ----');
_.extend(api.classes, getClassesToInclude());
api.classes = sortClasses(api.classes);
let apiJson = JSON.stringify(api, null, 2);
let apiJsonPath = path.join(classDocsOutputDir, 'api.json');
grunt.file.write(apiJsonPath, apiJson);
return done();
});
});
};