Skip to content

Instantly share code, notes, and snippets.

@derek
Created July 19, 2012 00:22
Show Gist options
  • Save derek/3139908 to your computer and use it in GitHub Desktop.
Save derek/3139908 to your computer and use it in GitHub Desktop.
Milo utilities
assets/serverRoutes.json
config.json

Scripts require the following modules. Specified version is what it was tested against.

If you don't already have them installed, from within your milo root npm install {module}@{version}

express >= 3.0

handlebars >= 1.0

jslint >= 0.1.8

selleck >= 0.1.13

yql >= 0.4.7

yui-coverage >= 0.0.14

module.exports = function (template) {
var fs = require('fs'),
exec = require('child_process').exec,
config = this.config,
getAsset = require('../../utils').getAsset,
get = require('../milo/fetch'),
gistID;
gistID = config.apps[template];
get(gistID, template);
};
YUI.add('{{{name}}}', function(Y){
{{{body}}}
}, '', {{{config}}});
// todo: Store the build time from previous builds and do a countdown
module.exports = function (module) {
console.log("Building.... (could take a bit)\n");
var exec = require('child_process').exec,
fs = require('fs'),
config = this.config,
modulePath = config.yuiPath + 'src/' + module,
buildSwitch = (module === undefined) ? '' : '-f ' + modulePath + '/build.xml',
cmd = 'ant all -q -Dlint.skip=true ' + buildSwitch,
process,
files;
// If you want to ensure files pass jslint first
// files = fs.readdirSync(modulePath + '/js/');
// files.forEach(function(file) {
// if (lint(modulePath + '/js/' + file).errors.length > 0) {
// console.log('Errors!');
// // return;
// }
// });
process = exec(cmd, 'utf-8');
process.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
process.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
process.on('exit', function (code) {
console.log('child process exited with code ' + code);
});
};
function checkREADME() {
var config = this.config,
fs = require('fs'),
modules = fs.readdirSync(config.yuiPath + '/src');
console.log();
console.log('Checking README files...');
modules.forEach(function (module) {
var readmePath = config.yuiPath + 'src/' + module,
stat, exists;
if(fs.existsSync(readmePath)) {
stat = fs.statSync(readmePath, 'utf-8');
if (stat.isDirectory()) {
exists = fs.existsSync(readmePath + '/README.md');
if (!exists) {
console.log('\t' + module + ' is missing a README');
}
}
}
});
}
function checkHistory() {
var config = this.config,
fs = require('fs'),
modules = fs.readdirSync(config.yuiPath + '/src'),
historyFiles = [];
console.log();
console.log('Checking HISTORY files...');
modules.forEach(function (module) {
var historyPath = config.yuiPath + 'src/' + module,
stat, exists;
if(fs.existsSync(historyPath)) {
stat = fs.statSync(historyPath, 'utf-8');
if (stat.isDirectory()) {
exists = fs.existsSync(historyPath + '/HISTORY.md');
if (!exists) {
console.log('\t' + module + ' is missing a HISTORY.md');
}
else {
historyFiles.push(historyPath + '/HISTORY.md');
}
}
}
});
historyFiles.forEach(function (path){
var text = fs.readFileSync(path, 'utf-8'),
version = '3.6.0';
if (!text.match(version)) {
console.log('\t' + path + ' is missing a ' + version + ' entry');
}
});
}
module.exports = function () {
checkREADME.apply(this);
checkHistory.apply(this);
};
{
"docsCommand" : "selleck -s",
"coverageCommand" : "yui-coverage",
"yuiPath" : "/Users/drg/src/yui/yui3/",
"yuilibrary" : {
"user" : "drgath"
},
"apps" : {
"simple" : 3131146,
"Y.app" : 3141472
},
"jslintOptions" : {
"sloppy" : true,
"node" : true,
"nomen" : true,
"white" : true,
"stupid" : true
}
}
module.exports = function (module) {
if (!module) {
console.log('Error: Please specify a module');
return false;
}
var config = this.config,
exec = require('child_process').exec,
process = exec(config.coverageCommand, {cwd: config.yuiPath + 'src/' + module});
console.log('Starting server...');
process.stdout.on('data', function (data) {
if (data.toString().match('Starting server')) {
exec(config.browserCommand + ' http://127.0.0.1:3000/');
}
console.log('stdout: ' + data);
});
process.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
process.on('exit', function (code) {
console.log('child process exited with code ' + code);
});
};
// Note: This script is super hacky & ugly, but hey... it works
// Look, a global. Told ya.
var config;
function runServer () {
var express = require('express'),
fs = require('fs'),
miloPath = require('../../utils').getMiloPath();
if (!fs.existsSync(miloPath + 'libraries/yui/assets/serverRoutes.json')) {
console.log('Error: Cannot find server routes. Please run `milo dms generate` to generate the routing map');
return;
}
var map = require('./assets/serverRoutes'),
utils = require('../../utils'),
server = express.createServer();
server.get(/([.*])/, routeHandler);
server.listen(3000);
console.log("Ready to rock!");
function routeHandler (req, res){
var url = req.url,
build = config.yuiPath + 'build',
src = config.yuiPath + 'src',
output = '';
console.log('serving: ' + url);
if (url.match('.js')) {
map[url].targets.forEach(function (target) {
output += fs.readFileSync(config.yuiPath + target, 'utf-8');
});
if (url.match('yui/yui.js')) {
output = output.replace(/@YUI_CORE@/g, "['get','features','intl-base','yui-log','yui-later','loader-base', 'loader-rollup', 'loader-yui3']");
output += "\n\nYUI.add('yui', function(Y){}, '3.6.0pr2' ,{use:['yui-base','get','features','intl-base','yui-log','yui-later','loader-base', 'loader-rollup', 'loader-yui3']});";
}
else {
output = wrap(map[url].module, output, map[url].requires);
}
serve(res, output, 'js');
}
else {
// TODO: Actually pull the /src/ CSS
fs.readFile(build + url, 'utf-8', function (err, data) {
serve(res, data, 'css');
});
}
}
function serve(res, output, type) {
var mime;
switch (type) {
case "css":
mime = "text/css";
break;
case "js":
mime = "application/javascript";
break;
}
res.header('Content-Length', output.length);
res.header('Content-Type', mime + '; charset=utf-8');
res.send(output);
}
function wrap(module, code, requires) {
var config = {};
if (requires.length > 0) {
config.requires = requires;
}
return utils.renderTemplate(utils.getAsset('yui', 'module.mustache'), {
name: module,
body: code,
config: JSON.stringify(config)
});
}
}
function generateMap () {
console.log("Generating...");
var fs = require('fs'),
src = config.yuiPath + 'src/',
modules = fs.readdirSync(src),
miloPath = require('../../utils').getMiloPath(),
output = {};
// modules = ['attribute']
modules.forEach(function (module) {
var stat = fs.statSync(src + module, 'utf-8');
if (stat.isDirectory()) {
var buildFiles = fs.readdirSync(src + module);
buildFiles.forEach(function (file) {
var requires = [], mod,
source, targets, props, properties;
if (file.match('.properties')) {
var properties = fs.readFileSync(src + module + '/' + file, 'utf-8'),
props = parseProperties(properties),
mod = props.component,
source = '/' + mod + '/' + mod + '.js',
targets;
if (props.jsfiles) {
if (!props.jsfiles.splice) {
targets = [props.jsfiles];
}
else {
targets = props.jsfiles;
}
for(var i=0; i < targets.length; i++) {
targets[i] = ('/src/' + module + '/js/' + targets[i]).trim();
}
}
if (props.requires) {
if (!props.requires.splice) {
props.requires = [props.requires.replace(',', ' ')]
}
// Cleanup the array. Ridiculous chaining is ridiculous
requires = props.requires.join(' ').replace(',', ' ').replace(' ', ' ').replace(' ', ' ').split(' ');
}
output[source] = {
module: mod,
source: source,
targets: targets,
prependfiles: props.prependfiles || null,
requires: requires
};
}
});
}
}); // We made it out alive !
// Todo: This library path shouldn't be fixed to milo
fs.writeFile(miloPath + 'libraries/yui/assets/serverRoutes.json', JSON.stringify(output, null, 4));
console.log("Done.");
// This is so gross
function parseProperties(properties) {
var lines = properties.split('\n'),
data = {},
key;
for (var i =0; i < lines.length; i++) {
var line = lines[i];
if (!line.match('#')) {
if (line.match('=')) {
// console.log(line);
key = line.split('=')[0].replace('component.', '');
val = line.split('=')[1].replace('\\', '').replace(',', '').trim();
data[key] = val.replace(/,/g, ' ').replace(/ /g, ' ').split(' ');
}
else {
if (line.trim().length > 0) {
line = line.trim().replace('\\', '').replace(',', '');
if (data[key]) {
if (!data[key].splice) {
data[key] = [data[key]];
}
data[key].push(line);
}
else {
data[key] = line.trim();
}
}
}
}
}
return data;
}
}
module.exports = function (action) {
config = this.config;
if (action === "generate") {
generateMap.apply(this);
}
else {
runServer.apply(this);
}
}
module.exports = function (module) {
var config = this.config,
exec = require('child_process').exec,
process = exec(config.docsCommand, {cwd: config.yuiPath + 'src'});
console.log('Starting server...');
process.stdout.on('data', function (data) {
var url = 'http://127.0.0.1:3000/';
if (module) {
url += module;
}
exec(config.browserCommand + ' ' + url);
console.log('stdout: ' + data);
});
process.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
process.on('exit', function (code) {
console.log('child process exited with code ' + code);
});
};
module.exports = function (module) {
var config = this.config,
fs = require('fs'),
exec = require('child_process').exec;
exec(config.editorCommand + ' ' + config.yuiPath + '/src/' + module);
};
module.exports = function (path) {
var exec = require('child_process').exec,
linter = require("jslint/lib/linter"),
reporter = require("jslint/lib/reporter"),
config = this.config,
fs = require('fs'),
files = [],
stat;
if (!fs.existsSync(path)) {
path = config.yuiPath + 'src/' + path + '/js';
}
stat = fs.statSync(path, 'utf-8');
if (stat.isDirectory()) {
fs.readdirSync(path).forEach(function(file){
if (file.match('.js')) {
files.push(path + file);
}
});
}
else {
files.push(path);
}
files.forEach(function (file) {
var code = fs.readFileSync(file, 'utf-8'),
result = linter.lint(code, config.jslintOptions);
reporter.report(file, result);
});
};
module.exports = function (module, action) {
if (!module) {
console.log("Please specify a module");
return;
}
var fs = require('fs'),
path = require('path'),
config = this.config,
modulePath = config.yuiPath + 'src/' + module,
history = fs.readFileSync(modulePath + '/HISTORY.md', 'utf-8'),
readme = fs.readFileSync(modulePath + '/README.md', 'utf-8'),
jsFiles = fs.existsSync(modulePath + '/js') && fs.readdirSync(modulePath + '/js'),
cssFiles = fs.existsSync(modulePath + '/css') && fs.readdirSync(modulePath + '/css'),
meta = require(modulePath + '/meta/' + module);
switch(action) {
case "files":
console.log();
console.log('modulePath: ' + modulePath);
if (jsFiles) {
console.log();
console.log('JS');
jsFiles.forEach(function(file) { console.log(path.normalize(modulePath + '/js/' + file)); });
}
if (cssFiles) {
console.log();
console.log('CSS');
cssFiles.forEach(function(file) { console.log(path.normalize(modulePath + '/css/' + file)); });
}
console.log();
break;
case "history":
console.log();
console.log(history);
break;
case "meta":
console.log('\nMeta\n--------');
console.log(meta);
console.log();
break;
default:
console.log();
console.log(readme);
break;
}
};
YUI.add('{{{name}}}', function(Y){
{{{body}}}
}, '', {{{config}}});
// todo: support gallery modules as well
module.exports = function (foo) {
var fs = require('fs'),
config = this.config,
modules = fs.readdirSync(config.yuiPath + '/build');
modules.forEach(function (module) {
console.log(module);
});
};
var yql = require('yql');
function getTweets (user) {
var tweets;
yql.exec("select * from twitter.user.timeline where (id = @id)", function(response) {
if (response.error) {
// console.log(require('util').inspect(error));
console.log("Error: " + response.error.description);
}
else {
tweets = response.query.results.statuses.status;
tweets.reverse();
tweets.forEach(function (tweet) {
console.log(tweet.created_at + ": " + tweet.text);
});
}
}, {id:user});
}
function getVideos () {
var videos;
yql.exec("select * from youtube.user.videos where id='yuilibrary'", function(results) {
videos = results.query.results.video;
videos.reverse();
videos.forEach(function(video){
console.log(video.title.toUpperCase());
// console.log(video.content);
console.log(video.url + '\n\n--');
});
});
}
function getHeadlines () {
var posts;
yql.exec("select * from rss where url = 'http://feeds.yuiblog.com/YahooUserInterfaceBlog'", function(results) {
posts = results.query.results.item;
posts.reverse();
posts.forEach(function(post){
console.log(post.title);
console.log(post.pubDate);
console.log(post.description + '\n\n');
});
});
}
module.exports = function (type) {
switch(type) {
case 'tweets':
getTweets('yuilibrary');
break;
case 'relay':
getTweets('yuirelay');
break;
case 'headlines':
getHeadlines();
break;
case 'videos':
getVideos();
break;
default:
console.log('milo media tweets');
console.log('milo media headlines');
console.log('milo media relay');
console.log('milo media videos');
break;
}
};
module.exports = function () {
var yql = require('yql').exec,
config = this.config,
flags = this.flags,
url = 'http://yuilibrary.com/projects/yui3/query?col[]=id&col[]=type&col[]=priority&col[]=owner&col[]=milestone&col[]=status&col[]=summary&col[]=estimated&col[]=completed&col[]=remaining&col[]=sprint';
url += '&owner=' + config.yuilibrary.user;
if (flags.milestone) {
url += '&sprint=' + flags.milestone;
if (flags.sprint) {
url += '%3A%3Asprint+' + flags.sprint;
}
}
if (flags.component) {
url += '&component=' + flags.component;
}
yql('select * from html where url=@url and xpath=@xpath', function (response) {
var results = response.query.results,
rows, tickets = [];
if (!results) {
console.log("No results found");
return;
}
rows = response.query.results.tr;
// If the result is only 1, it's an object, so turn it into an array.
if (!rows.length) {
rows = [rows];
}
rows.forEach(function (row) {
var ticket = {};
row.td.forEach(function (field) {
ticket[field.name] = (field.a && field.a.content) || (field.p);
});
tickets.push(ticket);
});
console.log(tickets);
}, {
url: url,
xpath: '//table[@class="listing tickets"]/tbody/tr'
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment