mirror of
https://github.com/resume/resume.github.com.git
synced 2024-09-11 12:25:56 +03:00
The initial github resumes repository
This commit is contained in:
commit
47aba3b380
119
css/resume.css
Normal file
119
css/resume.css
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------------
|
||||||
|
STRIPPED DOWN RESUME TEMPLATE
|
||||||
|
html resume
|
||||||
|
|
||||||
|
v0.9: 5/28/09
|
||||||
|
|
||||||
|
design and code by: thingsthatarebrown.com
|
||||||
|
(matt brown)
|
||||||
|
---------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
.msg { padding: 10px; background: #222; position: relative; }
|
||||||
|
.msg h1 { color: #fff; }
|
||||||
|
.msg a { margin-left: 20px; background: #408814; color: white; padding: 4px 8px; text-decoration: none; }
|
||||||
|
.msg a:hover { background: #266400; }
|
||||||
|
|
||||||
|
/* //-- yui-grids style overrides -- */
|
||||||
|
body { font-family: Georgia; color: #444; }
|
||||||
|
#inner { padding: 10px 80px; margin: 80px auto; background: #f5f5f5; border: solid #666; border-width: 8px 0 2px 0; }
|
||||||
|
.yui-gf { margin-bottom: 2em; padding-bottom: 2em; border-bottom: 1px solid #ccc; }
|
||||||
|
|
||||||
|
/* //-- header, body, footer -- */
|
||||||
|
#hd { margin: 2.5em 0 3em 0; padding-bottom: 1.5em; border-bottom: 1px solid #ccc }
|
||||||
|
#hd h2 { text-transform: uppercase; letter-spacing: 2px; }
|
||||||
|
#bd, #ft { margin-bottom: 2em; }
|
||||||
|
|
||||||
|
/* //-- footer -- */
|
||||||
|
#ft { padding: 1em 0 5em 0; font-size: 92%; border-top: 1px solid #ccc; text-align: center; }
|
||||||
|
#ft p { margin-bottom: 0; text-align: center; }
|
||||||
|
|
||||||
|
/* //-- core typography and style -- */
|
||||||
|
#hd h1 { font-size: 48px; text-transform: uppercase; letter-spacing: 3px; }
|
||||||
|
h2 { font-size: 152% }
|
||||||
|
h3, h4 { font-size: 122%; }
|
||||||
|
h1, h2, h3, h4 { color: #333; }
|
||||||
|
p { font-size: 100%; line-height: 18px; padding-right: 3em; }
|
||||||
|
a { color: #990003 }
|
||||||
|
a:hover { text-decoration: none; }
|
||||||
|
strong { font-weight: bold; }
|
||||||
|
li { line-height: 24px; border-bottom: 1px solid #ccc; }
|
||||||
|
p.enlarge { font-size: 144%; padding-right: 6.5em; line-height: 24px; }
|
||||||
|
p.enlarge span { color: #000 }
|
||||||
|
.contact-info { margin-top: 7px; }
|
||||||
|
.first h2 { font-style: italic; }
|
||||||
|
.last { border-bottom: 0 }
|
||||||
|
|
||||||
|
|
||||||
|
/* //-- section styles -- */
|
||||||
|
|
||||||
|
a#pdf { display: block; float: left; background: #666; color: white; padding: 6px 50px 6px 12px; margin-bottom: 6px; text-decoration: none; }
|
||||||
|
a#pdf:hover { background: #222; }
|
||||||
|
|
||||||
|
.job { position: relative; margin-bottom: 1em; padding-bottom: 1em; border-bottom: 1px solid #ccc; }
|
||||||
|
.job h4 { position: absolute; top: 0.35em; right: 0 }
|
||||||
|
.job p { margin: 0.75em 0 3em 0; }
|
||||||
|
|
||||||
|
.last { border: none; }
|
||||||
|
.skills-list { }
|
||||||
|
.skills-list ul { margin: 0; }
|
||||||
|
.skills-list li { margin: 3px 0; padding: 3px 0; }
|
||||||
|
.skills-list li span { font-size: 152%; display: block; margin-bottom: -2px; padding: 0 }
|
||||||
|
.talent { width: 32%; float: left }
|
||||||
|
.talent h2 { margin-bottom: 6px; }
|
||||||
|
|
||||||
|
#srt-ttab { margin-bottom: 100px; text-align: center; }
|
||||||
|
#srt-ttab img.last { margin-top: 20px }
|
||||||
|
|
||||||
|
/* --// override to force 1/8th width grids -- */
|
||||||
|
.yui-gf .yui-u{width:80.2%;}
|
||||||
|
.yui-gf div.first{width:12.3%;}
|
||||||
|
|
||||||
|
input#username {
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
height: 30px;
|
||||||
|
width: 75%;
|
||||||
|
border: 2px solid #444;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: Georgia; color: #444;
|
||||||
|
font-size: 18px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button#gen {
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
margin-left: 10px;
|
||||||
|
width: 20%;
|
||||||
|
height: 44px;
|
||||||
|
font-family: Georgia; color: #444;
|
||||||
|
font-size: 18px;
|
||||||
|
color: white;
|
||||||
|
background-image: -webkit-gradient(
|
||||||
|
linear,
|
||||||
|
left bottom,
|
||||||
|
left top,
|
||||||
|
color-stop(0.21, rgb(31,31,31)),
|
||||||
|
color-stop(0.61, rgb(51,51,51))
|
||||||
|
);
|
||||||
|
background-image: -moz-linear-gradient(
|
||||||
|
center bottom,
|
||||||
|
rgb(31,31,31) 21%,
|
||||||
|
rgb(51,51,51) 61%
|
||||||
|
);
|
||||||
|
border: 1px solid #444;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button#gen:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
BIN
images/srt.png
Normal file
BIN
images/srt.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
BIN
images/ttab.png
Normal file
BIN
images/ttab.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
23
index.html
Normal file
23
index.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<title>Github Resume</title>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||||
|
|
||||||
|
<meta name="keywords" content="cv, resume, hResume, github, community, free, fun, nice, useful" />
|
||||||
|
<meta name="description" content="Github resumes, generated by the community, for the community." />
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.7.0/build/reset-fonts-grids/reset-fonts-grids.css" media="all" />
|
||||||
|
<link rel="stylesheet" type="text/css" href="css/resume.css" media="all" />
|
||||||
|
|
||||||
|
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
|
||||||
|
<script type="text/javascript" src="js/mustache.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="js/github.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="js/githubresume.js"></script>
|
||||||
|
</head>
|
||||||
|
<body id="resume">
|
||||||
|
</body>
|
||||||
|
</html>
|
667
js/github.js
Normal file
667
js/github.js
Normal file
@ -0,0 +1,667 @@
|
|||||||
|
// ## Client-side Javascript API wrapper for GitHub
|
||||||
|
//
|
||||||
|
// Tries to map one-to-one with the GitHub API V2, but in a Javascripty manner.
|
||||||
|
|
||||||
|
(function (globals) {
|
||||||
|
|
||||||
|
// Before we implement the API methods, we will define all of our private
|
||||||
|
// variables and helper functions with one `var` statement.
|
||||||
|
var
|
||||||
|
|
||||||
|
// The username and authentication token of the library's user.
|
||||||
|
authUsername,
|
||||||
|
authToken,
|
||||||
|
|
||||||
|
// To save keystrokes when we make JSONP calls to the HTTP API, we will keep
|
||||||
|
// track of the root from which all V2 urls extend.
|
||||||
|
apiRoot = "https://github.com/api/v2/json/",
|
||||||
|
|
||||||
|
// Send a JSONP request to the Github API that calls `callback` with
|
||||||
|
// the `context` argument as `this`.
|
||||||
|
//
|
||||||
|
// The `url` parameter is concatenated with the apiRoot, for the reasons
|
||||||
|
// mentioned above. The way that we are supporting non-global, anonymous
|
||||||
|
// functions is by sticking them in the globally exposed
|
||||||
|
// `gh.__jsonp_callbacks` object with a "unique" `id` that is the current
|
||||||
|
// time in milliseconds. Once the callback is called, it is deleted from the
|
||||||
|
// object to prevent memory leaks.
|
||||||
|
jsonp = function (url, callback, context) {
|
||||||
|
var id = +new Date,
|
||||||
|
script = document.createElement("script");
|
||||||
|
|
||||||
|
while (gh.__jsonp_callbacks[id] !== undefined)
|
||||||
|
id += Math.random(); // Avoid slight possibility of id clashes.
|
||||||
|
|
||||||
|
gh.__jsonp_callbacks[id] = function () {
|
||||||
|
delete gh.__jsonp_callbacks[id];
|
||||||
|
callback.apply(context, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
var prefix = "?";
|
||||||
|
if (url.indexOf("?") >= 0)
|
||||||
|
prefix = "&";
|
||||||
|
|
||||||
|
url += prefix + "callback=" + encodeURIComponent("gh.__jsonp_callbacks[" + id + "]");
|
||||||
|
if (authUsername && authToken) {
|
||||||
|
url += "&login=" + authUsername + "&authToken=" + authToken;
|
||||||
|
}
|
||||||
|
script.setAttribute("src", apiRoot + url);
|
||||||
|
|
||||||
|
document.getElementsByTagName('head')[0].appendChild(script);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Send an HTTP POST. Unfortunately, it isn't possible to support a callback
|
||||||
|
// with the resulting data. (Please prove me wrong if you can!)
|
||||||
|
//
|
||||||
|
// This is implemented with a hack to get around the cross-domain
|
||||||
|
// restrictions on ajax calls. Basically, a form is created that will POST
|
||||||
|
// to the GitHub API URL, stuck inside an iframe so that it won't redirect
|
||||||
|
// this page, and then submitted.
|
||||||
|
post = function (url, vals) {
|
||||||
|
var
|
||||||
|
form = document.createElement("form"),
|
||||||
|
iframe = document.createElement("iframe"),
|
||||||
|
doc = iframe.contentDocument !== undefined ?
|
||||||
|
iframe.contentDocument :
|
||||||
|
iframe.contentWindow.document,
|
||||||
|
key, field;
|
||||||
|
vals = vals || {};
|
||||||
|
|
||||||
|
form.setAttribute("method", "post");
|
||||||
|
form.setAttribute("action", apiRoot + url);
|
||||||
|
for (key in vals) {
|
||||||
|
if (vals.hasOwnProperty(key)) {
|
||||||
|
field = document.createElement("input");
|
||||||
|
field.type = "hidden";
|
||||||
|
field.value = encodeURIComponent(vals[key]);
|
||||||
|
form.appendChild(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe.setAttribute("style", "display: none;");
|
||||||
|
doc.body.appendChild(form);
|
||||||
|
document.body.appendChild(iframe);
|
||||||
|
form.submit();
|
||||||
|
},
|
||||||
|
|
||||||
|
// This helper function will throw a TypeError if the library user is not
|
||||||
|
// properly authenticated. Otherwise, it silently returns.
|
||||||
|
authRequired = function (username) {
|
||||||
|
if (!authUsername || !authToken || authUsername !== username) {
|
||||||
|
throw new TypeError("gh: Must be authenticated to do that.");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Convert an object to a url parameter string.
|
||||||
|
//
|
||||||
|
// paramify({foo:1, bar:3}) -> "foo=1&bar=3".
|
||||||
|
paramify = function (params) {
|
||||||
|
var str = "", key;
|
||||||
|
for (key in params) if (params.hasOwnProperty(key))
|
||||||
|
str += key + "=" + params[key] + "&";
|
||||||
|
return str.replace(/&$/, "");
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get around how the GH team haven't migrated all the API to version 2, and
|
||||||
|
// how gists use a different api root.
|
||||||
|
withTempApiRoot = function (tempApiRoot, fn) {
|
||||||
|
return function () {
|
||||||
|
var oldRoot = apiRoot;
|
||||||
|
apiRoot = tempApiRoot;
|
||||||
|
fn.apply(this, arguments);
|
||||||
|
apiRoot = oldRoot;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
// Expose the global `gh` variable, through which every API method is
|
||||||
|
// accessed, but keep a local variable around so we can reference it easily.
|
||||||
|
gh = globals.gh = {};
|
||||||
|
|
||||||
|
// Psuedo private home for JSONP callbacks (which are required to be global
|
||||||
|
// by the nature of JSONP, as discussed earlier).
|
||||||
|
gh.__jsonp_callbacks = {};
|
||||||
|
|
||||||
|
// Authenticate as a user. Does not try to validate at any point; that job
|
||||||
|
// is up to each individual method, which calls `authRequired` as needed.
|
||||||
|
gh.authenticate = function (username, token) {
|
||||||
|
authUsername = username;
|
||||||
|
authToken = token;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ### Users
|
||||||
|
|
||||||
|
// The constructor for user objects. Just creating an instance of a user
|
||||||
|
// doesn't fetch any data from GitHub, you need to get explicit about what
|
||||||
|
// you want to do that.
|
||||||
|
//
|
||||||
|
// var huddlej = gh.user("huddlej");
|
||||||
|
gh.user = function (username) {
|
||||||
|
if ( !(this instanceof gh.user)) {
|
||||||
|
return new gh.user(username);
|
||||||
|
}
|
||||||
|
this.username = username;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Show basic user info; you can get more info if you are authenticated as
|
||||||
|
// this user.
|
||||||
|
//
|
||||||
|
// gh.user("fitzgen").show(function (data) {
|
||||||
|
// console.log(data.user);
|
||||||
|
// });
|
||||||
|
gh.user.prototype.show = function (callback, context) {
|
||||||
|
jsonp("user/show/" + this.username, callback, context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update a user's info. You must be authenticated as this user for this to
|
||||||
|
// succeed.
|
||||||
|
//
|
||||||
|
// TODO: example
|
||||||
|
gh.user.prototype.update = function (params) {
|
||||||
|
authRequired(this.username);
|
||||||
|
var key, postData = {
|
||||||
|
login: authUsername,
|
||||||
|
token: authToken
|
||||||
|
};
|
||||||
|
for (key in params) {
|
||||||
|
if (params.hasOwnProperty(key)) {
|
||||||
|
postData["values["+key+"]"] = encodeURIComponent(params[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post("user/show/" + this.username, postData);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a list of who this user is following.
|
||||||
|
//
|
||||||
|
// TODO: example
|
||||||
|
gh.user.prototype.following = function (callback, context) {
|
||||||
|
jsonp("user/show/" + this.username + "/following", callback, context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find out what other users are following this user.
|
||||||
|
//
|
||||||
|
// TODO: example
|
||||||
|
gh.user.prototype.followers = function (callback, context) {
|
||||||
|
jsonp("user/show/" + this.username + "/followers", callback, context);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make this user follow some other user. You must be authenticated as this
|
||||||
|
// user for this to succeed.
|
||||||
|
//
|
||||||
|
// TODO: example
|
||||||
|
gh.user.prototype.follow = function (user) {
|
||||||
|
authRequired.call(this);
|
||||||
|
post("user/follow/" + user);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make this user quit following the given `user`. You must be authenticated
|
||||||
|
// as this user to succeed.
|
||||||
|
//
|
||||||
|
// TODO: example
|
||||||
|
gh.user.prototype.unfollow = function (user) {
|
||||||
|
authRequired.call(this);
|
||||||
|
post("user/unfollow/" + user);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a list of repositories that this user is watching.
|
||||||
|
//
|
||||||
|
// TODO: example
|
||||||
|
gh.user.prototype.watching = function (callback, context) {
|
||||||
|
jsonp("repos/watched/" + this.username, callback, context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a list of this user's repositories.
|
||||||
|
//
|
||||||
|
// gh.user("fitzgen").repos(function (data) {
|
||||||
|
// alert(data.repositories.length);
|
||||||
|
// });
|
||||||
|
gh.user.prototype.repos = function (callback, context) {
|
||||||
|
gh.repo.forUser(this.username, callback, context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make this user fork the repo that lives at
|
||||||
|
// http://github.com/user/repo. You must be authenticated as this user for
|
||||||
|
// this to succeed.
|
||||||
|
//
|
||||||
|
// gh.user("fitzgen").forkRepo("brianleroux", "wtfjs");
|
||||||
|
gh.user.prototype.forkRepo = function (user, repo) {
|
||||||
|
authRequired(this.username);
|
||||||
|
post("repos/fork/" + user + "/" + repo);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a list of all repos that this user can push to (including ones that
|
||||||
|
// they are just a collaborator on, and do not own). Must be authenticated
|
||||||
|
// as this user.
|
||||||
|
gh.user.prototype.pushable = function (callback, context) {
|
||||||
|
authRequired(authUsername);
|
||||||
|
jsonp("repos/pushable", callback, context);
|
||||||
|
};
|
||||||
|
|
||||||
|
gh.user.prototype.publicGists = withTempApiRoot(
|
||||||
|
"http://gist.github.com/api/v1/json/gists/",
|
||||||
|
function (callback, context) {
|
||||||
|
jsonp(this.username, callback, context);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Search users for `query`.
|
||||||
|
gh.user.search = function (query, callback, context) {
|
||||||
|
jsonp("user/search/" + query, callback, context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ### Repositories
|
||||||
|
|
||||||
|
// This is the base constructor for creating repo objects. Note that this
|
||||||
|
// won't actually hit the GitHub API until you specify what data you want,
|
||||||
|
// or what action you wish to take via a prototype method.
|
||||||
|
gh.repo = function (user, repo) {
|
||||||
|
if ( !(this instanceof gh.repo)) {
|
||||||
|
return new gh.repo(user, repo);
|
||||||
|
}
|
||||||
|
this.repo = repo;
|
||||||
|
this.user = user;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get basic information on this repo.
|
||||||
|
//
|
||||||
|
// gh.repo("schacon", "grit").show(function (data) {
|
||||||
|
// console.log(data.repository.description);
|
||||||
|
// });
|
||||||
|
gh.repo.prototype.show = function (callback, context) {
|
||||||
|
jsonp("repos/show/" + this.user + "/" + this.repo, callback, context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update the information for this repo. Must be authenticated as the
|
||||||
|
// repository owner. Params can include:
|
||||||
|
//
|
||||||
|
// * description
|
||||||
|
// * homepage
|
||||||
|
// * has_wiki
|
||||||
|
// * has_issues
|
||||||
|
// * has_downloads
|
||||||
|
gh.repo.prototype.update = function (params) {
|
||||||
|
authRequired(this.user);
|
||||||
|
var key, postData = {
|
||||||
|
login: authUsername,
|
||||||
|
token: authToken
|
||||||
|
};
|
||||||
|
for (key in params) {
|
||||||
|
if (params.hasOwnProperty(key)) {
|
||||||
|
postData["values["+key+"]"] = encodeURIComponent(params[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post("repos/show/" + this.user + "/" + this.repo, postData);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get all tags for this repo.
|
||||||
|
gh.repo.prototype.tags = function (callback, context) {
|
||||||
|
jsonp("repos/show/" + this.user + "/" + this.repo + "/tags",
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get all branches in this repo.
|
||||||
|
gh.repo.prototype.branches = function (callback, context) {
|
||||||
|
jsonp("repos/show/" + this.user + "/" + this.repo + "/branches",
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gather line count information on the language(s) used in this repo.
|
||||||
|
gh.repo.prototype.languages = function (callback, context) {
|
||||||
|
jsonp("/repos/show/" + this.user + "/" + this.repo + "/languages",
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gather data on all the forks of this repo.
|
||||||
|
gh.repo.prototype.network = function (callback, context) {
|
||||||
|
jsonp("repos/show/" + this.user + "/" + this.repo + "/network",
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// All users who have contributed to this repo. Pass `true` to showAnon if you
|
||||||
|
// want to see the non-github contributors.
|
||||||
|
gh.repo.prototype.contributors = function (callback, context, showAnon) {
|
||||||
|
var url = "repos/show/" + this.user + "/" + this.repo + "/contributors";
|
||||||
|
if (showAnon)
|
||||||
|
url += "/anon";
|
||||||
|
jsonp(url,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get all of the collaborators for this repo.
|
||||||
|
gh.repo.prototype.collaborators = function (callback, context) {
|
||||||
|
jsonp("repos/show/" + this.user + "/" + this.repo + "/collaborators",
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add a collaborator to this project. Must be authenticated.
|
||||||
|
gh.repo.prototype.addCollaborator = function (collaborator) {
|
||||||
|
authRequired(this.user);
|
||||||
|
post("repos/collaborators/" + this.repo + "/add/" + collaborator);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove a collaborator from this project. Must be authenticated.
|
||||||
|
gh.repo.prototype.removeCollaborator = function (collaborator) {
|
||||||
|
authRequired(this.user);
|
||||||
|
post("repos/collaborators/" + this.repo + "/remove/" + collaborator);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make this repository private. Authentication required.
|
||||||
|
gh.repo.prototype.setPrivate = function () {
|
||||||
|
authRequired(this.user);
|
||||||
|
post("repo/set/private/" + this.repo);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make this repository public. Authentication required.
|
||||||
|
gh.repo.prototype.setPublic = function () {
|
||||||
|
authRequired(this.user);
|
||||||
|
post("repo/set/public/" + this.repo);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Search for repositories. `opts` may include `start_page` or `language`,
|
||||||
|
// which must be capitalized.
|
||||||
|
gh.repo.search = function (query, opts, callback, context) {
|
||||||
|
var url = "repos/search/" + query.replace(" ", "+");
|
||||||
|
if (typeof opts === "function") {
|
||||||
|
opts = {};
|
||||||
|
callback = arguments[1];
|
||||||
|
context = arguments[2];
|
||||||
|
}
|
||||||
|
url += "?" + paramify(opts);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get all the repos that are owned by `user`.
|
||||||
|
gh.repo.forUser = function (user, callback, context) {
|
||||||
|
jsonp("repos/show/" + user, callback, context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a repository. Must be authenticated.
|
||||||
|
gh.repo.create = function (name, opts) {
|
||||||
|
authRequired(authUsername);
|
||||||
|
opts.name = name;
|
||||||
|
post("repos/create", opts);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Delete a repository. Must be authenticated.
|
||||||
|
gh.repo.del = function (name) {
|
||||||
|
authRequired(authUsername);
|
||||||
|
post("repos/delete/" + name);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ### Commits
|
||||||
|
|
||||||
|
gh.commit = function (user, repo, sha) {
|
||||||
|
if ( !(this instanceof gh.commit) )
|
||||||
|
return new gh.commit(user, repo, sha);
|
||||||
|
this.user = user;
|
||||||
|
this.repo = repo;
|
||||||
|
this.sha = sha;
|
||||||
|
};
|
||||||
|
|
||||||
|
gh.commit.prototype.show = function (callback, context) {
|
||||||
|
jsonp("commits/show/" + this.user + "/" + this.repo + "/" + this.sha,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a list of all commits on a repos branch.
|
||||||
|
gh.commit.forBranch = function (user, repo, branch, callback, context) {
|
||||||
|
jsonp("commits/list/" + user + "/" + repo + "/" + branch,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a list of all commits on this path (file or dir).
|
||||||
|
gh.commit.forPath = function (user, repo, branch, path, callback, context) {
|
||||||
|
jsonp("commits/list/" + user + "/" + repo + "/" + branch + "/" + path,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ### Issues
|
||||||
|
|
||||||
|
gh.issue = function (user, repo, number) {
|
||||||
|
if ( !(this instanceof gh.issue) )
|
||||||
|
return new gh.commit(user, repo, number);
|
||||||
|
this.user = user;
|
||||||
|
this.repo = repo;
|
||||||
|
this.number = number;
|
||||||
|
};
|
||||||
|
|
||||||
|
// View this issue's info.
|
||||||
|
gh.issue.prototype.show = function (callback, context) {
|
||||||
|
jsonp("issues/show/" + this.user + "/" + this.repo + "/" + this.number,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a list of all comments on this issue.
|
||||||
|
gh.issue.prototype.comments = function (callback, context) {
|
||||||
|
jsonp("issues/comments/" + this.user + "/" + this.repo + "/" + this.number,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Close this issue.
|
||||||
|
gh.issue.prototype.close = function () {
|
||||||
|
authRequired(this.user);
|
||||||
|
post("issues/close/" + this.user + "/" + this.repo + "/" + this.number);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reopen this issue.
|
||||||
|
gh.issue.prototype.reopen = function () {
|
||||||
|
authRequired(this.user);
|
||||||
|
post("issues/reopen/" + this.user + "/" + this.repo + "/" + this.number);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Reopen this issue.
|
||||||
|
gh.issue.prototype.update = function (title, body) {
|
||||||
|
authRequired(this.user);
|
||||||
|
post("issues/edit/" + this.user + "/" + this.repo + "/" + this.number, {
|
||||||
|
title: title,
|
||||||
|
body: body
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add `label` to this issue. If the label is not yet in the system, it will
|
||||||
|
// be created.
|
||||||
|
gh.issue.prototype.addLabel = function (label) {
|
||||||
|
post("issues/label/add/" + this.user + "/" + this.repo + "/" + label + "/" + this.number);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove a label from this issue.
|
||||||
|
gh.issue.prototype.removeLabel = function (label) {
|
||||||
|
post("issues/label/remove/" + this.user + "/" + this.repo + "/" + label + "/" + this.number);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Comment on this issue as the user that is authenticated.
|
||||||
|
gh.issue.prototype.comment = function (comment) {
|
||||||
|
authRequired(authUsername);
|
||||||
|
post("/issues/comment/" + user + "/" + repo + "/" + this.number, {
|
||||||
|
comment: comment
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get all issues' labels for the repo.
|
||||||
|
gh.issue.labels = function (user, repo) {
|
||||||
|
jsonp("issues/labels/" + user + "/" + repo,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Open an issue. Must be authenticated.
|
||||||
|
gh.issue.open = function (repo, title, body) {
|
||||||
|
authRequired(authUsername);
|
||||||
|
post("issues/open/" + authUsername + "/" + repo, {
|
||||||
|
title: title,
|
||||||
|
body: body
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Search a repository's issue tracker. `state` can be "open" or "closed".
|
||||||
|
gh.issue.search = function (user, repo, state, query, callback, context) {
|
||||||
|
jsonp("/issues/search/" + user + "/" + repo + "/" + state + "/" + query,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a list of issues for the given repo. `state` can be "open" or
|
||||||
|
// "closed".
|
||||||
|
gh.issue.list = function (user, repo, state, callback, context) {
|
||||||
|
jsonp("issues/list/" + user + "/" + repo + "/" + state,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ### Gists
|
||||||
|
|
||||||
|
gh.gist = function (id) {
|
||||||
|
if ( !(this instanceof gh.gist) ) {
|
||||||
|
return new gh.gist(id);
|
||||||
|
}
|
||||||
|
this.id = id;
|
||||||
|
};
|
||||||
|
|
||||||
|
gh.gist.prototype.show = withTempApiRoot(
|
||||||
|
"http://gist.github.com/api/v1/json/",
|
||||||
|
function (callback, context) {
|
||||||
|
jsonp(this.id, callback, cont);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
gh.gist.prototype.file = withTempApiRoot(
|
||||||
|
"http://gist.github.com/raw/v1/json/",
|
||||||
|
function (filename, callback, context) {
|
||||||
|
jsonp(this.id + "/" + filename, callback, cont);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// ### Objects
|
||||||
|
|
||||||
|
gh.object = function (user, repo) {
|
||||||
|
if (!(this instanceof gh.object)) {
|
||||||
|
return new gh.object(user, repo);
|
||||||
|
}
|
||||||
|
this.user = user;
|
||||||
|
this.repo = repo;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the contents of a tree by tree SHA
|
||||||
|
gh.object.prototype.tree = function (sha, callback, context) {
|
||||||
|
jsonp("tree/show/" + this.user + "/" + this.repo + "/" + sha,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the data about a blob by tree SHA and path
|
||||||
|
gh.object.prototype.blob = function (path, sha, callback, context) {
|
||||||
|
jsonp("blob/show/" + this.user + "/" + this.repo + "/" + sha + "/" + path,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get only blob meta
|
||||||
|
gh.object.prototype.blobMeta = function (path, sha, callback, context) {
|
||||||
|
jsonp("blob/show/" + this.user + "/" + this.repo + "/" + sha + "/" + path + "?meta=1",
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get list of blobs
|
||||||
|
gh.object.prototype.blobAll = function (branch, callback, context) {
|
||||||
|
jsonp("blob/all/" + this.user + "/" + this.repo + "/" + branch,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get meta of each blob in tree
|
||||||
|
gh.object.prototype.blobFull = function (sha, callback, context) {
|
||||||
|
jsonp("blob/full/" + this.user + "/" + this.repo + "/" + sha,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ### Network
|
||||||
|
|
||||||
|
gh.network = function(user, repo) {
|
||||||
|
if (!(this instanceof gh.network)) {
|
||||||
|
return new gh.network(user, repo);
|
||||||
|
}
|
||||||
|
this.user = user;
|
||||||
|
this.repo = repo;
|
||||||
|
};
|
||||||
|
|
||||||
|
gh.network.prototype.data = withTempApiRoot(
|
||||||
|
"http://github.com/",
|
||||||
|
function (nethash, start, end, callback, context) {
|
||||||
|
jsonp(this.user + "/" + this.repo + "/network_data_chunk?"
|
||||||
|
+ nethash + "&" + start + "&" + end,
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
gh.network.prototype.meta = withTempApiRoot(
|
||||||
|
"http://github.com/",
|
||||||
|
function (callback, context) {
|
||||||
|
jsonp(this.user + "/" + this.repo + "/network_meta",
|
||||||
|
callback,
|
||||||
|
context);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}(window));
|
140
js/githubresume.js
Normal file
140
js/githubresume.js
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
var urlParams = {};
|
||||||
|
(function () {
|
||||||
|
var e,
|
||||||
|
a = /\+/g, // Regex for replacing addition symbol with a space
|
||||||
|
r = /([^&=]+)=?([^&]*)/g,
|
||||||
|
d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
|
||||||
|
q = window.location.search.substring(1);
|
||||||
|
|
||||||
|
while (e = r.exec(q))
|
||||||
|
urlParams[0] = d(e[1]);
|
||||||
|
})();
|
||||||
|
|
||||||
|
var username;
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
try {
|
||||||
|
if (urlParams[0] !== undefined) {
|
||||||
|
username = urlParams[0];
|
||||||
|
run();
|
||||||
|
} else {
|
||||||
|
home();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var error = function() {
|
||||||
|
$.ajax({
|
||||||
|
url: 'views/error.html',
|
||||||
|
dataType: 'html',
|
||||||
|
success: function(data) {
|
||||||
|
var template = data;
|
||||||
|
$('#resume').html(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var home = function() {
|
||||||
|
$.ajax({
|
||||||
|
url: 'views/index.html',
|
||||||
|
dataType: 'html',
|
||||||
|
success: function(data) {
|
||||||
|
var template = data;
|
||||||
|
$('#resume').html(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var run = function() {
|
||||||
|
|
||||||
|
var gh_user = gh.user(username);
|
||||||
|
var itemCount = 0, maxItems = 5;
|
||||||
|
|
||||||
|
var res = gh_user.show(function(data) {
|
||||||
|
gh_user.repos(function(data) {
|
||||||
|
repos = data;
|
||||||
|
});
|
||||||
|
|
||||||
|
var since = new Date(data.user.created_at);
|
||||||
|
since = since.getFullYear();
|
||||||
|
|
||||||
|
var view = {
|
||||||
|
name: data.user.name,
|
||||||
|
email: data.user.email,
|
||||||
|
created_at: data.user.created_at,
|
||||||
|
blog: data.user.blog,
|
||||||
|
location: data.user.location,
|
||||||
|
repos: data.user.public_repo_count,
|
||||||
|
plural: data.user.public_repo_count > 1 ? 'repositories' : 'repository',
|
||||||
|
username: username,
|
||||||
|
since: since
|
||||||
|
};
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: 'views/resume.html',
|
||||||
|
dataType: 'html',
|
||||||
|
success: function(data) {
|
||||||
|
var template = data;
|
||||||
|
var html = Mustache.to_html(template, view);
|
||||||
|
$('#resume').html(html);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
gh_user.repos(function(data) {
|
||||||
|
var repos = data.repositories;
|
||||||
|
|
||||||
|
var sorted = [];
|
||||||
|
var languages = [];
|
||||||
|
|
||||||
|
repos.forEach(function(elm, i, arr) {
|
||||||
|
if (arr[i].fork !== false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var popularity = arr[i].watchers + arr[i].forks;
|
||||||
|
sorted.push({position: i, popularity: popularity, info: arr[i]});
|
||||||
|
});
|
||||||
|
|
||||||
|
function sortByPopularity(a, b) {
|
||||||
|
return b.popularity - a.popularity;
|
||||||
|
};
|
||||||
|
|
||||||
|
sorted.sort(sortByPopularity);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: 'views/job.html',
|
||||||
|
dataType: 'html',
|
||||||
|
success: function(response) {
|
||||||
|
var now = new Date().getFullYear();
|
||||||
|
|
||||||
|
sorted.forEach(function(elm, index, arr) {
|
||||||
|
if (itemCount >= maxItems) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var since = new Date(arr[index].info.created_at);
|
||||||
|
since = since.getFullYear();
|
||||||
|
var view = {
|
||||||
|
name: arr[index].info.name,
|
||||||
|
since: since,
|
||||||
|
now: now,
|
||||||
|
description: arr[index].info.description,
|
||||||
|
username: username,
|
||||||
|
watchers: arr[index].info.watchers,
|
||||||
|
forks: arr[index].info.forks
|
||||||
|
};
|
||||||
|
|
||||||
|
var template = response;
|
||||||
|
var html = Mustache.to_html(template, view);
|
||||||
|
|
||||||
|
$('#jobs').append($(html));
|
||||||
|
++itemCount;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$(window).bind('error', error);
|
298
js/mustache.js
Normal file
298
js/mustache.js
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
/*
|
||||||
|
Shameless port of http://github.com/defunkt/mustache
|
||||||
|
by Jan Lehnardt <jan@apache.org>,
|
||||||
|
Alexander Lang <alex@upstream-berlin.com>,
|
||||||
|
Sebastian Cohnen <sebastian.cohnen@googlemail.com>
|
||||||
|
|
||||||
|
Thanks @defunkt for the awesome code.
|
||||||
|
|
||||||
|
See http://github.com/defunkt/mustache for more info.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Mustache = function() {
|
||||||
|
var Renderer = function() {};
|
||||||
|
|
||||||
|
Renderer.prototype = {
|
||||||
|
otag: "{{",
|
||||||
|
ctag: "}}",
|
||||||
|
pragmas: {},
|
||||||
|
buffer: [],
|
||||||
|
pragmas_parsed: false,
|
||||||
|
|
||||||
|
render: function(template, context, partials, in_recursion) {
|
||||||
|
// fail fast
|
||||||
|
if(template.indexOf(this.otag) == -1) {
|
||||||
|
if(in_recursion) {
|
||||||
|
return template;
|
||||||
|
} else {
|
||||||
|
this.send(template);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!in_recursion) {
|
||||||
|
this.buffer = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this.pragmas_parsed) {
|
||||||
|
template = this.render_pragmas(template);
|
||||||
|
}
|
||||||
|
var html = this.render_section(template, context, partials);
|
||||||
|
if(in_recursion) {
|
||||||
|
return this.render_tags(html, context, partials, in_recursion);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.render_tags(html, context, partials, in_recursion);
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sends parsed lines
|
||||||
|
*/
|
||||||
|
send: function(line) {
|
||||||
|
if(line != "") {
|
||||||
|
this.buffer.push(line);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
Looks for %PRAGMAS
|
||||||
|
*/
|
||||||
|
render_pragmas: function(template) {
|
||||||
|
this.pragmas_parsed = true;
|
||||||
|
// no pragmas
|
||||||
|
if(template.indexOf(this.otag + "%") == -1) {
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
var that = this;
|
||||||
|
var regex = new RegExp(this.otag + "%([\\w_-]+) ?([\\w]+=[\\w]+)?"
|
||||||
|
+ this.ctag);
|
||||||
|
return template.replace(regex, function(match, pragma, options) {
|
||||||
|
that.pragmas[pragma] = {};
|
||||||
|
if(options) {
|
||||||
|
var opts = options.split("=");
|
||||||
|
that.pragmas[pragma][opts[0]] = opts[1];
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
// ignore unknown pragmas silently
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
Tries to find a partial in the global scope and render it
|
||||||
|
*/
|
||||||
|
render_partial: function(name, context, partials) {
|
||||||
|
if(typeof(context[name]) != "object") {
|
||||||
|
throw({message: "subcontext for '" + name + "' is not an object"});
|
||||||
|
}
|
||||||
|
if(!partials || !partials[name]) {
|
||||||
|
throw({message: "unknown_partial '" + name + "'"});
|
||||||
|
}
|
||||||
|
return this.render(partials[name], context[name], partials, true);
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
Renders boolean and enumerable sections
|
||||||
|
*/
|
||||||
|
render_section: function(template, context, partials) {
|
||||||
|
if(template.indexOf(this.otag + "#") == -1) {
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
var that = this;
|
||||||
|
// CSW - Added "+?" so it finds the tighest bound, not the widest
|
||||||
|
var regex = new RegExp(this.otag + "\\#(.+)" + this.ctag +
|
||||||
|
"\\s*([\\s\\S]+?)" + this.otag + "\\/\\1" + this.ctag + "\\s*", "mg");
|
||||||
|
|
||||||
|
// for each {{#foo}}{{/foo}} section do...
|
||||||
|
return template.replace(regex, function(match, name, content) {
|
||||||
|
var value = that.find(name, context);
|
||||||
|
if(that.is_array(value)) { // Enumerable, Let's loop!
|
||||||
|
return that.map(value, function(row) {
|
||||||
|
return that.render(content, that.merge(context,
|
||||||
|
that.create_context(row)), partials, true);
|
||||||
|
}).join("");
|
||||||
|
} else if(value) { // boolean section
|
||||||
|
return that.render(content, context, partials, true);
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
Replace {{foo}} and friends with values from our view
|
||||||
|
*/
|
||||||
|
render_tags: function(template, context, partials, in_recursion) {
|
||||||
|
// tit for tat
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
var new_regex = function() {
|
||||||
|
return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\/#]+?)\\1?" +
|
||||||
|
that.ctag + "+", "g");
|
||||||
|
};
|
||||||
|
|
||||||
|
var regex = new_regex();
|
||||||
|
var lines = template.split("\n");
|
||||||
|
for (var i=0; i < lines.length; i++) {
|
||||||
|
lines[i] = lines[i].replace(regex, function(match, operator, name) {
|
||||||
|
switch(operator) {
|
||||||
|
case "!": // ignore comments
|
||||||
|
return match;
|
||||||
|
case "=": // set new delimiters, rebuild the replace regexp
|
||||||
|
that.set_delimiters(name);
|
||||||
|
regex = new_regex();
|
||||||
|
return "";
|
||||||
|
case ">": // render partial
|
||||||
|
return that.render_partial(name, context, partials);
|
||||||
|
case "{": // the triple mustache is unescaped
|
||||||
|
return that.find(name, context);
|
||||||
|
default: // escape the value
|
||||||
|
return that.escape(that.find(name, context));
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
if(!in_recursion) {
|
||||||
|
this.send(lines[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(in_recursion) {
|
||||||
|
return lines.join("\n");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
set_delimiters: function(delimiters) {
|
||||||
|
var dels = delimiters.split(" ");
|
||||||
|
this.otag = this.escape_regex(dels[0]);
|
||||||
|
this.ctag = this.escape_regex(dels[1]);
|
||||||
|
},
|
||||||
|
|
||||||
|
escape_regex: function(text) {
|
||||||
|
// thank you Simon Willison
|
||||||
|
if(!arguments.callee.sRE) {
|
||||||
|
var specials = [
|
||||||
|
'/', '.', '*', '+', '?', '|',
|
||||||
|
'(', ')', '[', ']', '{', '}', '\\'
|
||||||
|
];
|
||||||
|
arguments.callee.sRE = new RegExp(
|
||||||
|
'(\\' + specials.join('|\\') + ')', 'g'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return text.replace(arguments.callee.sRE, '\\$1');
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
find `name` in current `context`. That is find me a value
|
||||||
|
from the view object
|
||||||
|
*/
|
||||||
|
find: function(name, context) {
|
||||||
|
name = this.trim(name);
|
||||||
|
if(typeof context[name] === "function") {
|
||||||
|
return context[name].apply(context);
|
||||||
|
}
|
||||||
|
if(context[name] !== undefined) {
|
||||||
|
return context[name];
|
||||||
|
}
|
||||||
|
// silently ignore unkown variables
|
||||||
|
return "";
|
||||||
|
},
|
||||||
|
|
||||||
|
// Utility methods
|
||||||
|
|
||||||
|
/*
|
||||||
|
Does away with nasty characters
|
||||||
|
*/
|
||||||
|
escape: function(s) {
|
||||||
|
return ((s == null) ? "" : s).toString().replace(/[&"<>\\]/g, function(s) {
|
||||||
|
switch(s) {
|
||||||
|
case "&": return "&";
|
||||||
|
case "\\": return "\\\\";;
|
||||||
|
case '"': return '\"';;
|
||||||
|
case "<": return "<";
|
||||||
|
case ">": return ">";
|
||||||
|
default: return s;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
Merges all properties of object `b` into object `a`.
|
||||||
|
`b.property` overwrites a.property`
|
||||||
|
*/
|
||||||
|
merge: function(a, b) {
|
||||||
|
var _new = {};
|
||||||
|
for(var name in a) {
|
||||||
|
if(a.hasOwnProperty(name)) {
|
||||||
|
_new[name] = a[name];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for(var name in b) {
|
||||||
|
if(b.hasOwnProperty(name)) {
|
||||||
|
_new[name] = b[name];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return _new;
|
||||||
|
},
|
||||||
|
|
||||||
|
// by @langalex, support for arrays of strings
|
||||||
|
create_context: function(_context) {
|
||||||
|
if(this.is_object(_context)) {
|
||||||
|
return _context;
|
||||||
|
} else if(this.pragmas["IMPLICIT-ITERATOR"]) {
|
||||||
|
var iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator || ".";
|
||||||
|
var ctx = {};
|
||||||
|
ctx[iterator] = _context
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
is_object: function(a) {
|
||||||
|
return a && typeof a == "object";
|
||||||
|
},
|
||||||
|
|
||||||
|
is_array: function(a) {
|
||||||
|
return Object.prototype.toString.call(a) === '[object Array]';
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
Gets rid of leading and trailing whitespace
|
||||||
|
*/
|
||||||
|
trim: function(s) {
|
||||||
|
return s.replace(/^\s*|\s*$/g, "");
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
Why, why, why? Because IE. Cry, cry cry.
|
||||||
|
*/
|
||||||
|
map: function(array, fn) {
|
||||||
|
if (typeof array.map == "function") {
|
||||||
|
return array.map(fn)
|
||||||
|
} else {
|
||||||
|
var r = [];
|
||||||
|
var l = array.length;
|
||||||
|
for(i=0;i<l;i++) {
|
||||||
|
r.push(fn(array[i]));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return({
|
||||||
|
name: "mustache.js",
|
||||||
|
version: "0.2.3-dev",
|
||||||
|
|
||||||
|
/*
|
||||||
|
Turns a template and view into HTML
|
||||||
|
*/
|
||||||
|
to_html: function(template, view, partials, send_fun) {
|
||||||
|
var renderer = new Renderer();
|
||||||
|
if(send_fun) {
|
||||||
|
renderer.send = send_fun;
|
||||||
|
}
|
||||||
|
renderer.render(template, view, partials);
|
||||||
|
if(!send_fun) {
|
||||||
|
return renderer.buffer.join("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}();
|
12
views/error.html
Normal file
12
views/error.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<div id="doc" class="yui-t7">
|
||||||
|
<div id="hd" role="banner"><h1>Uh oh :(</h1></div>
|
||||||
|
<div id="bd" role="main">
|
||||||
|
<div class="yui-g">
|
||||||
|
<p>
|
||||||
|
We couldn't find enough to build a resume from. Make sure this is the good username :-). <a href="/" title="Home">Try again with another username?</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="ft" role="contentinfo"><p>Brought to your by the brilliant mind of <a href="http://twitter.com/davidcoallier">@davidcoallier</a> </modesty></p></div>
|
||||||
|
</div>
|
42
views/index.html
Normal file
42
views/index.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<div id="doc" class="yui-t7">
|
||||||
|
<div id="hd" role="banner"><h1>My Github Resume</h1></div>
|
||||||
|
<div id="bd" role="main">
|
||||||
|
<div class="yui-g">
|
||||||
|
<p>
|
||||||
|
As a software startup owner I really enjoy when people send us their
|
||||||
|
resumes and they include their github account so we can see tangible work they have done.
|
||||||
|
</p>
|
||||||
|
<p><br /></p>
|
||||||
|
<p>
|
||||||
|
After a <a href="https://twitter.com/#!/jeresig/status/33968704983138304">tweet by John Resig</a>
|
||||||
|
I imagined that it may be nice for people to be able to generate their <a href="https://github.com" title="Github">Github</a> resumes.
|
||||||
|
</p>
|
||||||
|
<p><br /></p>
|
||||||
|
<p>
|
||||||
|
<input id="username" type="text" value="Enter your github username and click on generate" />
|
||||||
|
<button type="button" id="gen">Generate</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="ft" role="contentinfo"><p>Brought to your by the brilliant mind of <a href="http://twitter.com/davidcoallier">@davidcoallier</a> </modesty></p></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('input#username').live('click', function() {
|
||||||
|
$(this).val('');
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).keyup(function(e) {
|
||||||
|
if (e.keyCode == 13) {
|
||||||
|
var genUser = $('#username').val();
|
||||||
|
document.location.href = "/?" + genUser;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#gen').live('click', function() {
|
||||||
|
var genUser = $('#username').val();
|
||||||
|
document.location.href = "/?" + genUser;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
9
views/job.html
Normal file
9
views/job.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<div class="job">
|
||||||
|
<h2>{{name}}</h2>
|
||||||
|
<h3>Creator & Owner</h3>
|
||||||
|
<h4>{{since}} - {{now}}</h4>
|
||||||
|
<p>{{description}}.</p>
|
||||||
|
<p>This repository has {{watchers}} watcher(s) and {{forks}} fork(s). If you would like more information about this repository and my contributed code, please visit <a href="https://github.com/{{username}}/{{name}}">the repo</a> on Github.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
4
views/repo.html
Normal file
4
views/repo.html
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{{#repo}}
|
||||||
|
<h1>{{repo}}</h1>
|
||||||
|
<p>{{description}}</p>
|
||||||
|
{{/repo}}
|
76
views/resume.html
Normal file
76
views/resume.html
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<div id="doc2" class="yui-t7">
|
||||||
|
<div id="inner">
|
||||||
|
|
||||||
|
<div id="hd">
|
||||||
|
<div class="yui-gc">
|
||||||
|
<div class="yui-u first">
|
||||||
|
<h1>{{name}}</h1>
|
||||||
|
<h2>Passionate github user</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="yui-u">
|
||||||
|
<div class="contact-info">
|
||||||
|
<h3><a href="mailto:{{email}}">{{email}}</a></h3>
|
||||||
|
</div><!--// .contact-info -->
|
||||||
|
</div>
|
||||||
|
</div><!--// .yui-gc -->
|
||||||
|
</div><!--// hd -->
|
||||||
|
|
||||||
|
<div id="bd">
|
||||||
|
<div id="yui-main">
|
||||||
|
<div class="yui-b">
|
||||||
|
|
||||||
|
<div class="yui-gf">
|
||||||
|
<div class="yui-u first">
|
||||||
|
<h2>Github Profile</h2>
|
||||||
|
</div>
|
||||||
|
<div class="yui-u">
|
||||||
|
<p class="enlarge">
|
||||||
|
I'm a developer
|
||||||
|
{{#location}}
|
||||||
|
based in {{location}}
|
||||||
|
{{/location}}
|
||||||
|
with {{repos}} public {{plural}}. I've been using github.com since {{since}}
|
||||||
|
{{#blog}}
|
||||||
|
and sometimes I blog at <a href="{{blog}}" title="my blog">{{blog}}</a>
|
||||||
|
{{/blog}}.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div><!--// .yui-gf -->
|
||||||
|
|
||||||
|
|
||||||
|
<div class="yui-gf">
|
||||||
|
<div class="yui-u first">
|
||||||
|
<h2>My Popular Repositories</h2>
|
||||||
|
</div><!--// .yui-u -->
|
||||||
|
|
||||||
|
<div class="yui-u" id="jobs">
|
||||||
|
|
||||||
|
</div><!--// .yui-u -->
|
||||||
|
</div><!--// .yui-gf -->
|
||||||
|
|
||||||
|
<div class="yui-gf last">
|
||||||
|
<div class="yui-u first">
|
||||||
|
<h2>About This Resume</h2>
|
||||||
|
</div>
|
||||||
|
<div class="yui-u">
|
||||||
|
<p class="enlarge">
|
||||||
|
This resume is generated automatically using information from my github account. The repositories are
|
||||||
|
ordered by popularity based on a very simple popularity heuristic that defines the popularity of a repository
|
||||||
|
by it's sum of watchers and forks. Do not hesitate to visit <a href="https://github.com/{{{username}}}" title="My Github page">my github page</a>
|
||||||
|
for more information about my repositories and work.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div><!--// .yui-gf -->
|
||||||
|
</div><!--// .yui-b -->
|
||||||
|
</div><!--// yui-main -->
|
||||||
|
</div><!--// bd -->
|
||||||
|
|
||||||
|
<div id="ft">
|
||||||
|
<p>{{name}} — <a href="mailto:{{email}}">{{email}}</a> — <a href="https://github.com/{{username}}" title="Github profile">https://github.com/{{username}}</a></p>
|
||||||
|
</div><!--// footer -->
|
||||||
|
|
||||||
|
</div><!-- // inner -->
|
||||||
|
|
||||||
|
|
||||||
|
</div><!--// doc -->
|
2
views/user.html
Normal file
2
views/user.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<h1>{{full_name}}</h1>
|
||||||
|
<p>Information about this user</p>
|
Loading…
Reference in New Issue
Block a user