diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8a0bdc1..d0fb3d1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,6 +18,9 @@ Prerequisites: familiarity with [GitHub PRs](https://help.github.com/articles/us Knowledge of Markdown for editing `.md` documents - Discuss proposed changes in an Issue. +- If submitting a Speaker Page, please follow the template + closely. You can verify that you have filled out your markdown file + properly by running `node index.js | python -mjson.tool`. - Submit changes in a Pull Request, fixing one thing. If a pull request is too broad, we may ask that you split it up so that each change may be addressed individually. - Pull requests can be merged by contributers with commit access once all open questions have been diff --git a/README.md b/README.md index db31d5e..3aadb1f 100644 --- a/README.md +++ b/README.md @@ -11,5 +11,3 @@ and send a pull request. Please refrain from submitting a speaker page for other This repository's intended audience is organizers and prospective speakers at node meetups. The intent is to enable communication among organizers and speakers: It should help match organizers with speakers, and provide a platform on which speakers might publish their talks and swap notes between themselves about what worked well and what did not. - - diff --git a/index.js b/index.js new file mode 100644 index 0000000..ab890f2 --- /dev/null +++ b/index.js @@ -0,0 +1,78 @@ +module.exports = main + +var toMetadata = require('./lib/mk') + , path = require('path') + , fs = require('fs') + +var through = require('through') + , ls = require('ls-stream') + +if(require.main === module) { + main() + .pipe(require('JSONStream').stringify()) + .pipe(process.stdout) +} + +function main() { + return ls(__dirname) + .pipe(filter()) + .pipe(annotateContent()) + .pipe(toMetadata()) +} + +// only emit entries that look like meetup markdown files. +function filter() { + var stream = through(write) + + return stream + + function write(entry) { + if(!/^(.+)\-(.+)(\-(.+))?/g.test(entry.path.replace(__dirname))) { + entry.ignore() + + return + } + + if(entry.stat.isFile() && path.extname(entry.path) === '.md') { + stream.queue(entry) + } + } +} + +// staple the file contents onto the meetup markdown files. +function annotateContent() { + var stream = through(write, end) + , pending = 0 + , ended + + return stream + + function write(entry) { + ++pending + fs.readFile(entry.path, 'utf8', onread) + + function onread(err, data) { + if(err) { + return stream.emit('error', err) + } + + stream.queue({ + entry: entry + , data: data + }) + --pending + check() + } + } + + function end() { + ended = true + check() + } + + function check() { + if(ended && !pending) { + stream.queue(null) + } + } +} diff --git a/lib/mk.js b/lib/mk.js new file mode 100644 index 0000000..bf35449 --- /dev/null +++ b/lib/mk.js @@ -0,0 +1,97 @@ +var through = require('through') + , marked = require('marked') + +/* + * turn the meetup {data: filedata, entry: entry} data into metadata + * about the meetups. + */ +function toMetadata() { + var stream = through(write) + + return stream + + function write(data) { + + var lexed = marked.lexer(data.data) + , plural = { + 'urls': true + , 'organizers': true + } + , formats = [] + , format + , meta = {} + + function parseTable(obj) { + return [obj.header].concat(obj.cells).reduce(function(lhs, rhs) { + var key = slugify(rhs[0].slice(2, -3)) + + lhs[key] = plural[key] ? rhs[1].split(/,\s*/) : rhs[1] + + return lhs + }, {}) + } + + meta.name = lexed[0].text + meta.avatar = lexed[1].text + + var list = [] + , lastKey + , listing + + for(var i = 2; i < lexed.length; i++) { + var obj = lexed[i] + + if (obj.type === 'list_start') { + listing = true; + } + + if (obj.type === 'list_end') { + meta[lastKey] = list + list = [] + listing = false + } + + if (listing && obj.type === 'text') { + list.push(obj.text) + } + + if (obj.type === 'table') { + if (lastKey !== undefined) { + meta[lastKey] = parseTable(obj) + } else { + meta.attributes = parseTable(obj) + } + } + + if (obj.type === 'heading') { + lastKey = obj.text + meta[lastKey] = {} + } + + if (obj.type === 'paragraph') { + meta[lastKey].body = obj.text + } + } + + meta.process = lexed.map(function(xs) { + return xs.text || '' + }).join('\n') + + stream.queue(meta) + } +} + +// TODO(dj): get rid of this prolly +// simple in this case: +function slugify(input) { + input = input.toString() + + return input + .replace(/[^\w\s\d\-]/g, '') + .replace(/^\s*/, '') + .replace(/\s*$/, '') + .replace(/[\-\s]+/g, '-') + .toLowerCase() +} + +module.exports = toMetadata diff --git a/package.json b/package.json new file mode 100644 index 0000000..5df77d6 --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "name": "knode-speakers", + "version": "0.0.0", + "description": "knode.io catalogue of speakers", + "main": "index.js", + "scripts": { + "test": "node test.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/knode/speakers.git" + }, + "keywords": [ + "knode", + "speakers", + "organizer", + "user", + "group" + ], + "author": "Knode.io ", + "license": "MIT", + "bugs": { + "url": "https://github.com/knode/speakers/issues" + }, + "dependencies": { + "marked": "~0.3.0", + "through": "~2.3.4", + "ls-stream": "~1.0.0", + "JSONStream": "~0.7.1" + }, + "devDependencies": { + "tape": "~2.3.2" + } +} diff --git a/portland-or-usa/justin-abrahms.md b/portland-or-usa/justin-abrahms.md index 713cf46..ff359c5 100644 --- a/portland-or-usa/justin-abrahms.md +++ b/portland-or-usa/justin-abrahms.md @@ -15,12 +15,12 @@ I'm Justin. I've been programming for many years. I'm self-taught. I dig talking because it provides me an excuse to dig deeper into a topic, as well as a method of share my findings with others. As for formats, I'm happy with a tour of code, if there's a particular repo of mine that catches your eye, standard speaker + slides or round table discussion things. -For topics, I'm into a bunch of stuff, including: +## Topics -- static analysis -- writing testable code -- playing with irc bots -- application structure and architecture -- technical paper discussion -- computer science (and education thereof) -- tooling as a general concept +* static analysis +* writing testable code +* playing with irc bots +* application structure and architecture +* technical paper discussion +* computer science (and education thereof) +* tooling as a general concept diff --git a/portland-or-usa/your-name.md b/portland-or-usa/your-name.md new file mode 100644 index 0000000..9dbe95a --- /dev/null +++ b/portland-or-usa/your-name.md @@ -0,0 +1,42 @@ +# Your Name Here + +![an avatar, if you'd like to include one](https://1.gravatar.com/avatar/8310c4341b623f781babb080cd2c5d4f?r=x&s=200) + +| **location**: | city, state, country | +|:--------------|---------------------:| +| **twitter**: | @therealgarybusey | +| **github**: | your-gh-username | +| **urls**: | urls | +| **travel availability**: | if comp'd / regionally / locally / none | +| **preferred audience size**: | large / small / N/A | + +## About me + +A brief introduction. What are you into? What do you like to talk about / work on? +Why do you enjoy talking? Are there any particular formats you enjoy? + +## Talks / Workshops (optional) + +### Something about JavaScript + +| **location**: | event, city, state, country | +|:--------------|----------------------------:| +| **when**: | YYYY-MM-DD | +| **materials**: | link to speakerdeck, etc | +| **duration**: | 45-min / 30 min | +| **audience size**: | large / small / ??? | + +A brief synopsis of what you talked about. E.G., I talked about XYZ at ABC. +The audience seemed to really like it. There were a few questions and they +lead me to add some feature to the thing. + +### Bleep Bloop + +| **location**: | event, city, state, country | +|:--------------|----------------------------:| +| **when**: | YYYY-MM-DD | +| **materials**: | link to speakerdeck, etc | +| **duration**: | 3 months | +| **audience size**: | large / small / ??? | + +I taught robots to make squid noises using [workshopper](http://npm.im/workshopper). diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..d57a50d --- /dev/null +++ b/test/index.js @@ -0,0 +1,11 @@ +var test = require('tape') + , mkdToJson = require('../index.js') + + +test('JSON formatting', function(t) { + mkdToJson().on('data' ,function(data) { + if (data) { + t.assert(data.name.length > 1) + } + }) +})