Permalink
Browse files

Initial Commit

  • Loading branch information...
0 parents commit 1e36b10d0dae98dd7002d41cc6d0854b8256762f @davglass committed Jan 31, 2012
Showing with 241 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +53 −0 README.md
  3. +13 −0 package.json
  4. +105 −0 server.js
  5. +20 −0 test/index.html
  6. +49 −0 util.js
1 .gitignore
@@ -0,0 +1 @@
+node_modules
53 README.md
@@ -0,0 +1,53 @@
+YUI Master Combo Handler
+========================
+
+Need to test YUI against master and need a combo handler?
+
+Well, here's an example that pulls the JS & CSS from Github and combo's them.
+
+The requests are cached in memory for 5 minutes to make sure we don't explode Github's rate limit.
+
+I've hosted this over at [http://jitsu.com](Nodejitsu) in case you wanted to give it a shot.
+
+How it works
+------------
+
+It's basically a caching proxy to https://raw.github.com/yui/yui3/*
+
+It only supports js & css, no images.
+
+It also supports `?filter=raw|debug|min` on the seed file to allow fo debugging.
+
+When the seed file is served a small chunk of JS is appended to it to dynamically configure
+the combo server for you:
+
+```javascript
+YUI.applyConfig({
+ root: "",
+ filter: "min",
+ comboBase: "http://yui-master-combo.nodejitsu.com/combo?"
+});
+YUI.version = "yui-master-combo";
+```
+
+This tells the YUI seed to use `http://yui-master-combo.nodejitsu.com/combo?` as it's combo base
+and set's the default filter to 'min' as well as modify the version stamp of the JS files.
+
+All files that are passed through this 'proxy' will also have `@VERSION@` replaced with the same stamp.
+
+Usage
+-----
+
+```html
+<script src="http://yui-master-combo.nodejitsu.com/"></script>
+<script src="http://yui-master-combo.nodejitsu.com/?filter=debug"></script>
+<script src="http://yui-master-combo.nodejitsu.com/?filter=raw"></script>
+```
+
+```javascript
+
+YUI().use('node', function(Y) {
+ //Good To Go!
+});
+```
+
13 package.json
@@ -0,0 +1,13 @@
+{
+ "name": "yui-master-combo",
+ "description": "Live combo server backed by Github Master",
+ "version": "0.0.1-2",
+ "dependencies": {
+ "express": "*"
+ },
+ "main": "./server.js",
+ "subdomain": "yui-master-combo",
+ "scripts": {
+ "start": "server.js"
+ }
+}
105 server.js
@@ -0,0 +1,105 @@
+#!/usr/bin/env node
+
+var express = require('express'),
+ app = express.createServer(),
+ util = require('./util'),
+ https = require('https');
+
+var cache = {
+};
+
+var getRemote = function(url, cb) {
+ console.log('Fetching Remote Resource', url);
+ https.get({
+ host: 'raw.github.com',
+ path: '/yui/yui3/master/build/' + url
+ }, function(res) {
+ var d = '';
+ res.on('data', function(chunk) {
+ d += chunk;
+ });
+ res.on('end', function() {
+ cb(d);
+ });
+ });
+};
+
+setInterval(function() {
+ console.log('Clearing Cache');
+ cache = {};
+}, (5 * 60 * 1000));
+
+var get = function(urls, cb) {
+ if (typeof urls === 'string') {
+ urls = [urls];
+ }
+ var stack = new util.Stack(),
+ data = [];
+
+ urls.forEach(function(u, k) {
+ if (cache[u]) {
+ data[k] = cache[u].data;
+ } else {
+ getRemote(u, stack.add(function(d) {
+ cache[u] = {
+ data: d
+ };
+ data[k] = d;
+ }));
+ }
+ });
+
+ stack.done(function() {
+ cb(data.join('\n'));
+ });
+};
+
+var stamp = function(str) {
+ return str.replace(/@VERSION@/g, 'yui-master-combo');
+};
+
+app.get('/', function(req, res) {
+ var filter = req.query.filter || 'min',
+ url = 'yui/yui-min.js';
+
+ switch (filter) {
+ case 'raw':
+ url = 'yui/yui.js';
+ break;
+ case 'debug':
+ url = 'yui/yui-debug.js';
+ break;
+ }
+
+ get(url, function(data) {
+ res.contentType('.js');
+ var host = req.headers.host;
+ var append = '\n/* Adding global config */\n\n';
+ append += 'YUI.applyConfig({\n';
+ append += ' root: "",\n';
+ append += ' filter: "' + filter + '",\n';
+ append += ' comboBase: "http:/'+'/' + host + '/combo?"\n';
+ append += '});\n';
+ append += 'YUI.version = "yui-master-combo";\n';
+
+ data += append;
+ data = stamp(data);
+ res.send(data);
+ });
+});
+
+app.get('/combo', function(req, res) {
+ var urls = Object.keys(req.query);
+ console.log('Fetching', urls);
+ get(urls, function(data) {
+ res.contentType(urls[0]);
+ data = stamp(data);
+ res.send(data);
+ });
+});
+
+app.get('*', function(req, res) {
+ res.send(404);
+});
+
+app.listen(5000);
20 test/index.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html>
+<head>
+ <title>Test</title>
+</head>
+<body class="yui3-skin-sam">
+
+<span class="horiz_slider"></span>
+
+<!--script src="http://localhost:5000/"></script-->
+<script src="http://yui-master-combo.nodejitsu.com/"></script>
+<script>
+YUI().use('slider', function(Y) {
+ console.log(Y);
+ var xSlider = new Y.Slider();
+ xSlider.render( ".horiz_slider" );
+});
+</script>
+</body>
+</html>
49 util.js
@@ -0,0 +1,49 @@
+function each(obj, callback) {
+ if (Array.isArray(obj)) {
+ obj.forEach(callback);
+ } else {
+ Object.keys(obj).forEach(function (key) {
+ callback(obj[key], key);
+ });
+ }
+}
+exports.each = each;
+
+var Stack = function () {
+ this.errors = [];
+ this.finished = 0;
+ this.results = [];
+ this.total = 0;
+};
+
+Stack.prototype = {
+ add: function (fn) {
+ var self = this,
+ index = self.total;
+
+ self.total += 1;
+
+ return function (err) {
+ if (err) { self.errors[index] = err; }
+
+ self.finished += 1;
+ self.results[index] = fn.apply(null, arguments);
+ self.test();
+ };
+ },
+
+ test: function () {
+ if (this.finished >= this.total && this.callback) {
+ this.callback.call(null, this.errors.length ? this.errors : null,
+ this.results, this.data);
+ }
+ },
+
+ done: function (callback, data) {
+ this.callback = callback;
+ this.data = data;
+ this.test();
+ }
+};
+
+exports.Stack = Stack;

0 comments on commit 1e36b10

Please sign in to comment.