From 1dac6cfb19aef8ae4fe21778db4d958cf8c67a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20de=20Metz?= Date: Tue, 1 Nov 2011 21:59:31 +0100 Subject: [PATCH] Add utils/meetups.js to parse and write the list of meetups. --- README.md | 14 +++ index.html | 18 ++-- package.json | 15 ++++ utils/meetups.js | 177 +++++++++++++++++++++++++++++++++++++ utils/template_meetup.html | 14 +++ 5 files changed, 229 insertions(+), 9 deletions(-) create mode 100644 package.json create mode 100755 utils/meetups.js create mode 100644 utils/template_meetup.html diff --git a/README.md b/README.md index 1a4c53941..c53fe1d72 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,20 @@ This is the source of the parisjs.org website. +## Utils + +Before everything else: + + npm install + +### Parsing all meetups and talks + + node utils/meetups.js parse + +### Writing all meetups + + node utils/meetups.js update + ## License DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE diff --git a/index.html b/index.html index 1363c2838..6d8eb9b8b 100644 --- a/index.html +++ b/index.html @@ -66,12 +66,12 @@

We'll be there!

Seen and heard in the meetups

@@ -173,7 +173,7 @@

Seen and heard in the meetups

  • RxJS
  • By: @jbrwk
  • -
  • Here are the Slides!
  • +
  • Here are the Slides!
  • @@ -449,7 +449,7 @@

    Seen and heard in the meetups

    @@ -458,7 +458,7 @@

    Seen and heard in the meetups

  • twitter avatar
  • CouchDB user feedback
  • By: @challet
  • -
  • Here are the Slides!
  • +
  • Here are the Slides!
  • diff --git a/package.json b/package.json new file mode 100644 index 000000000..2c2060eae --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "parisjs-website", + "description": "The website of parisjs.org", + "version": "0.0.1", + "homepage": "http://parisjs.org/", + "repository": { + "type": "git", + "url": "git://github.com/parisjs/parisjs-website.git" + }, + "dependencies": { + "jsdom": "", + "underscore": "" + }, + "devDependencies": {} +} diff --git a/utils/meetups.js b/utils/meetups.js new file mode 100755 index 000000000..351aec1b1 --- /dev/null +++ b/utils/meetups.js @@ -0,0 +1,177 @@ +#!/usr/bin/env node +/** + * You don't want to manage the list of events/talks/people by hands? This script can help you. + * + * It's a two way parser: + * - read index.html and extract the list of events/talks/people and output JSON on stdout + * - read a JSON from stdin and update index.html + * + * Why JSON? + * Because there is no good yaml parser in javascript, and it was out of the scope for now + * + * How to use it? + * node utils/meetups.js parse > meetup.json + * node utils/meetups.js update < meetup.json + */ + +var jsdom = require('jsdom') + , fs = require('fs') + , _ = require('underscore') +; + +if (process.argv.length == 3) { + if (process.argv[2] == 'parse') { + return parseMeetups(); + } else if (process.argv[2] == 'update') { + return updateMeetups(); + } +} +console.log('usage'); +console.log('node utils/meetups.js parse'); +console.log('node utils/meetups.js update'); +return; + +function readStdin(callback) { + var data = ""; + process.stdin.resume(); + process.stdin.setEncoding('utf8'); + + process.stdin.on('data', function (chunk) { + data += chunk; + }); + process.stdin.on('end', function () { + callback(data); + }); +} + +function updateMeetups() { + readStdin(function(data) { + var meetups = JSON.parse(data); + var html = generateHTMLFor(meetups); + var website = fs.readFileSync(__dirname + '/../index.html', 'utf8'); + + var jquery = 'http://code.jquery.com/jquery-1.5.min.js'; + jsdom.env(website, [jquery], + function(errors, window) { + if (errors) { + return console.error('jsdom error', errors) + } + var $ = window.$; + var $meetups = $('#meetups > ul').empty().append("\n ").append($(html)).append("\n "); + var document = window.document; + // remove the jquery inserted by jsdom + $('script:last', document).remove(); + var output = document.doctype + document.innerHTML; + console.log(output.trim()); + }); + }); +} + +function generateHTMLFor(meetups) { + var template = _.template(fs.readFileSync(__dirname +'/template_meetup.html', 'utf8')); + var html = meetups.map(function(meetup) { + return template(meetup); + }); + return "\n"+ html.join('')+"\n\n"; +} + +// + +function parseMeetups() { + var website = fs.readFileSync(__dirname + '/../index.html', 'utf8'); + + var jquery = 'http://code.jquery.com/jquery-1.5.min.js'; + jsdom.env(website, [jquery], + function(errors, window) { + if (errors) { + return console.error('jsdom error', errors) + } + var $ = window.$; + var meetups = extractMeetups($); + console.log(JSON.stringify(meetups)); + //var normalization = normalizeMeetups(meetups); + //console.log(JSON.stringify(normalization)); + }); +} + +/** + * The hard part + * find same authors to have a ref to each ones + */ +function normalizeMeetups(meetups) { + var authors = {}; + // don't worry, this is only the first level of indentation + meetups.forEach(function(meetup) { + // don't worry, this is only the second level of indentation + meetup.talks.forEach(function(talk) { + // don't worry, this is only the last level of indentation + talk.authors = talk.authors.map(function(author) { + if (authors[author.name]) { + var previous = authors[author.name]; + ['url', 'avatar'].forEach(function(property) { + if (author[property] != previous[property]) + console.error('grrrr! '+ property +' mismatch for '+ author.name); + }); + } + authors[author.name] = author; + return author.name; + }); + }) + }); + return { + meetups: meetups, + authors: authors + } +} + +/** + * Return a raw object of all events and talks + */ +function extractMeetups($) { + var $meetups = $('#meetups li.meetup'); + var meetups = []; + $meetups.each(function() { + var $meetup = $(this); + var meetup = { + title: $(this).text(), + talks: [] + }; + var $talks = $meetup.next('.meetup-content').find('> ul'); + meetup.talks = extractTalks($, $talks); + meetups.push(meetup); + }); + return meetups; +} + +function extractTalks($, $talks) { + return $talks.toArray().map(function(talk) { + var $talk = $(talk); + + function getLinks(regexp) { + return $talk.find('.descTalk a').filter(function() { + return $(this).text().match(regexp); + }).map(function() { + return $(this).attr('href'); + }).toArray(); + } + + var slides = getLinks(/slide/i); + var videos = getLinks(/(video|part)/i); + var projects = getLinks(/project/i); + + return { + title: $talk.find('.titleTalk').text().trim(), + slides: slides, + videos: videos, + projects: projects, + authors: $talk.find('.authorTalk a').map(function() { + return { + name: $(this).text(), + url: $(this).attr('href'), + // sorry boy, in case of multiple authors, we have only one avatar + avatar: $talk.find('.avatar img').attr('src') + } + }).toArray() + } + }); +} diff --git a/utils/template_meetup.html b/utils/template_meetup.html new file mode 100644 index 000000000..83b36595f --- /dev/null +++ b/utils/template_meetup.html @@ -0,0 +1,14 @@ +
  • <%= title %>
  • + +
  • <% talks.forEach(function(talk) { %> + +
      +
    • <% if (talk.authors[0].avatar) { %>twitter avatar<% } %>
    • +
    • <%= talk.title %>
    • +
    • By: <% for (var i=0; i<%= author.name %><% if (!end) print(" and "); } %>
    • +
    • Here are the <% if (talk.projects.length == 1) { %>project<% } %><% if (talk.slides.length == 1) { if (talk.slides[0] == "#") print(''); %>Slides<%if (talk.slides[0] == "#") print(''); } %><% if (talk.videos.length > 0) { %> + and the <% for (var j=0; jvideo<% if (talk.videos.length > 1) print(' part.'+ (j+1)); %><% } }%>!
    • +
    <% }) %> + +
  • +