diff --git a/.travis.yml b/.travis.yml index cbf971f..e440b12 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,11 @@ - language: node_js - node_js: - - "0.10" +language: node_js +node_js: + - "0.10" +services: + - mongodb +before_script: + - "npm run server > server_log &" + - "sleep 3" +after_script: + - "echo 'Server Log:'" + - "cat server_log" diff --git a/package.json b/package.json index 8769c4d..6dcddd9 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "resumes ======= http://microformats.org/wiki/hresume", "main": "index.js", "scripts": { - "test": "node ./test/index.js | tap-spec" + "test": "node ./test/index.js | tap-spec", + "server": "MONGOHQ_URL='mongodb://localhost/test' ROOT_URL='http://localhost:5000/' node server.js" }, "repository": { "type": "git", @@ -29,6 +30,8 @@ "resume-to-html": "0.0.21", "resume-to-markdown": "latest", "resume-to-text": "latest", + "resume-to-jsonld": "git://github.com/bollwyvl/resumeToJSONLD", + "resume-schema": "git://github.com/bollwyvl/resume-schema#jsonld", "superagent": "^0.18.1" }, "devDependencies": { diff --git a/server.js b/server.js index eaeb0ad..0f3227e 100644 --- a/server.js +++ b/server.js @@ -4,6 +4,7 @@ var resumeToText = require('resume-to-text'); var path = require('path'); var resumeToHTML = require('resume-to-html'); var resumeToMarkdown = require('resume-to-markdown'); +var resumeToJSONLD = require('resume-to-jsonld'); var bodyParser = require('body-parser'); var bcrypt = require('bcrypt-nodejs'); var gravatar = require('gravatar'); @@ -14,6 +15,9 @@ var mongo = require('mongodb'); var templateHelper = require('./template-helper'); var pdf = require('pdfcrowd'); var request = require('superagent'); +var schema = require('resume-schema'); + +var urlRoot = process.env.URL_ROOT || 'http://registry.jsonresume.org/'; var client = new pdf.Pdfcrowd('thomasdavis', '7d2352eade77858f102032829a2ac64e'); app.use(bodyParser()); @@ -44,6 +48,9 @@ MongoClient.connect(process.env.MONGOHQ_URL, function(err, db) { }); var renderHomePage = function(req, res) { + if(/ld\+json/.test(req.headers.accept)){ + return renderContext(req, res); + } db.collection('users').find({}).toArray(function(err, docs) { var usernameArray = []; docs.forEach(function(doc) { @@ -64,6 +71,19 @@ MongoClient.connect(process.env.MONGOHQ_URL, function(err, db) { }; + var renderContext = function(req, res) { + var content = JSON.stringify(schema.context, undefined, 4); + + res.set({ + 'Content-Type': 'application/ld+json', + 'Content-Length': Buffer.byteLength(content, 'utf8'), + 'Cache-Control': 'public, max-age=43200', + 'Vary': 'Accept, Accept-Encoding' + }); + + res.send(content); + }; + var renderResume = function(req, res) { console.log('hello') var themeName = req.query.theme || 'modern'; @@ -91,6 +111,26 @@ MongoClient.connect(process.env.MONGOHQ_URL, function(err, db) { if (/json/.test(format)) { delete resume.jsonresume; // This removes our registry server config vars from the resume.json delete resume._id; // This removes the document id of mongo + + if(/jsonld/.test(format)){ + return resumeToJSONLD(resume, function(err, resumeLD){ + content = JSON.stringify(resumeLD, undefined, 4); + res.set({ + 'Content-Type': 'application/ld+json', + 'Content-Length': Buffer.byteLength(content, 'utf8') + }); + res.send(content); + }); + } + + if(/ld\+json/.test(req.headers.accept)){ + res.set({ + 'Link': '<'+ urlRoot + + '>; rel="http://www.w3.org/ns/json-ld#context";' + + 'type="application/ld+json"' + }); + } + content = JSON.stringify(resume, undefined, 4); res.set({ 'Content-Type': 'application/json', @@ -208,7 +248,7 @@ MongoClient.connect(process.env.MONGOHQ_URL, function(err, db) { safe: true }, function(err, resume) { res.send({ - url: 'http://registry.jsonresume.org/' + user.username + url: urlRoot + user.username }); }); } else { @@ -231,7 +271,7 @@ MongoClient.connect(process.env.MONGOHQ_URL, function(err, db) { safe: true }, function(err, resume) { res.send({ - url: 'http://registry.jsonresume.org/' + guestUsername + url: urlRoot + guestUsername }); }); } @@ -263,7 +303,7 @@ MongoClient.connect(process.env.MONGOHQ_URL, function(err, db) { safe: true }, function(err, resume) { res.send({ - url: 'http://registry.jsonresume.org/' + user.username + url: urlRoot + user.username }); }); } else { diff --git a/test/index.js b/test/index.js index 3729fc0..e074cc5 100644 --- a/test/index.js +++ b/test/index.js @@ -1,8 +1,67 @@ var test = require('tape'); +var request = require('superagent'); +var _ = require('lodash'); -test('Server blank test', function(t) { - t.plan(1); - t.ok(true, 'blank test'); +var schema = require('resume-schema'); + +var user = { + username: 'richardhendricks', + email: 'richardhendricks@example.com', + password: 'password' +}; + +test('JSON-LD context serving', function(t) { + t.plan(2); + request + .get('http://localhost:5000/') + .set('Accept', 'application/ld+json') + .buffer(true) + .end(function(err, res){ + t.notOk(err, 'no error'); + t.doesNotThrow(function(){ JSON.parse(res.text) }, "JSON"); + }); +}); + + +test('new user creation', function(t) { + t.plan(2); + request + .post('http://localhost:5000/user') + .send(user) + .end(function(err, res){ + t.notOk(err, 'no error'); + t.doesNotThrow(function(){ JSON.parse(res.text) }, "JSON"); + }); }); -// \ No newline at end of file +test('resume posting', function(t) { + t.plan(2); + request + .post('http://localhost:5000/resume') + .send(_.extend({resume: schema.resumeJson}, user)) + .end(function(err, res){ + t.notOk(err, 'no error'); + t.doesNotThrow(function(){ JSON.parse(res.text) }, "JSON"); + }); +}); + +test('resume fetching', function(t) { + t.plan(2); + request + .get('http://localhost:5000/richardhendricks.json') + .end(function(err, res){ + t.notOk(err, 'no error'); + t.doesNotThrow(function(){ JSON.parse(res.text); }, "JSON"); + }); +}); + +test('resume fetching (as json-ld)', function(t) { + t.plan(2); + request + .get('http://localhost:5000/richardhendricks.jsonld') + .buffer(true) + .end(function(err, res){ + t.notOk(err, 'no error'); + t.doesNotThrow(function(){ JSON.parse(res.text); }, "JSON"); + }); +});