Commits

benoitc  committed 05febe6 Merge

hg merge couchdb010

  • Participants
  • Parent commits a324254, 1ce062d

Comments (0)

Files changed (47)

 .couchapprc
-.DS_Store
+.DS_Store
+.swp

File _attachments/js/blog.js

   });
 }
 
+function parseUri(sourceUri){
+   /* parseUri by Steven Levithan (http://badassery.blogspot.com) */
+    var uriPartNames = ["source","protocol","authority","domain","port","path","directoryPath","fileName","query","anchor"];
+    var uriParts = new RegExp("^(?:([^:/?#.]+):)?(?://)?(([^:/?#]*)(?::(\\d*))?)?((/(?:[^?#](?![^?#/]*\\.[^?#/.]+(?:[\\?#]|$)))*/?)?([^?#/]*))?(?:\\?([^#]*))?(?:#(.*))?").exec(sourceUri);
+    var uri = {};
+    
+    for(var i = 0; i < 10; i++){
+        uri[uriPartNames[i]] = (uriParts[i] ? uriParts[i] : "");
+    }
+    
+    // Always end directoryPath with a trailing backslash if a path was present in the source URI
+    // Note that a trailing backslash is NOT automatically inserted within or appended to the "path" key
+    if(uri.directoryPath.length > 0){
+        uri.directoryPath = uri.directoryPath.replace(/\/?$/, "/");
+    }
+    
+    return uri;
+}
 
+function Login(app, options) {
+  var app = app;
+  var options = options || {};
+
+  function login(username, password) {
+    app.login({
+      userdb: "users",
+      username: username,
+      password: password,
+      success: function() {
+        if (options.success) options.success();
+      },
+      error: function() {
+        alert("An error occurred logging in: " + r);
+        if (options.error) options.error();
+      }
+    });
+  }
+
+ $("#flogin").submit(function(e) {
+    e.preventDefault();
+    login($("#username").val(), $("#password").val())
+    return false;
+ });
+}
+    
 function Blog(app) {
 
     function stripScripts(s) {

File _attachments/login.html

+<!DOCTYPE html>
+<html lang="fr">
+<head>
+    <meta charset="utf-8"/>
+    <title>benoît chesneau web - login</title>
+    <!--[if IE]>
+
+    <script>
+        // allow IE to recognize HTMl5 elements
+        document.createElement('section');
+        document.createElement('article');
+        document.createElement('aside');
+        document.createElement('footer');
+        document.createElement('header');
+        document.createElement('nav');
+        document.createElement('time');
+
+    </script>
+    <![endif]-->
+    <link rel="openid.server" href="http://www.myopenid.com/server">
+    <link rel="openid.delegate" href="http://bchesneau.myopenid.com/">
+    <link rel="home index" href="http://benoitc.org" type="text/html">
+    <link rel="me author" href="http://benoitc.org/static/benoitc.html" type="text/html">
+
+    <link rel="stylesheet" href="css/benoitc.css" type="text/css" media="screen, projection" />
+
+
+</head>
+
+
+<body>
+    <div id="container">
+        <form name="flogin" id="flogin" action="/_session" method="post">
+            <ul>
+                <li><label for="username">username</label><input type="text" id="username" name="username" value=""></li>
+                <li><label for="password">password</label><input type="password" id="password" name="password" value=""></li>
+            </ul>
+            <p><input type="submit" id="bsubmit" value="Continue"></p>
+        </form>
+    </div>
+
+    <script src="/_utils/script/json2.js"></script>
+    <script src="/_utils/script/jquery.js"></script>
+    <script src="/_utils/script/jquery.couch.js"></script>
+    <script src="/_utils/script/jquery.cookies.js"></script>
+    <script src="vendor/inditeweb/jquery.couchapp.js"></script>
+    <script src="js/strftime.js"></script>
+    <script src="js/showdown.js"></script>
+
+    <script src="js/blog.js"></script>
+    <script>
+        $(document).ready(function() {       
+            $.CouchApp(function(app) {  
+                var href = document.location;
+                var uri = parseUri(document.location.href);
+                var query = {};
+                if (uri.query) {
+                    query_parts = uri.query.split("&");
+                    for (var i=0; i<query_parts.length; i++) {
+                        p = query_parts[i].split("=");
+                        query[p[0]] = p[1] || "";
+                    }
+                }     
+                new Login(app, {
+                    success: function() {
+                        document.location.href = query["next"];
+                    },
+                    error: function() {
+                        document.location = href;
+                    }
+                });
+            });
+        });
+
+    </script>    
+</body>
+
+
+</html>

File lib/helpers/ejs/ejs.js

-/*--------------------------------------------------------------------------
- *  EJS - Embedded JavaScript, version 0.1.0
- *  Copyright (c) 2007 Edward Benson
- *  http://www.edwardbenson.com/projects/ejs
- *  ------------------------------------------------------------------------
- *
- *  EJS is freely distributable under the terms of an MIT-style license.
- *
- *  EJS is a client-side preprocessing engine written in and for JavaScript.
- *  If you have used PHP, ASP, JSP, or ERB then you get the idea: code embedded
- *  in <% // Code here %> tags will be executed, and code embedded in <%= .. %> 
- *  tags will be evaluated and appended to the output. 
- * 
- *  This is essentially a direct JavaScript port of Masatoshi Seki's erb.rb 
- *  from the Ruby Core, though it contains a subset of ERB's functionality. 
- * 
- *  Requirements:
- *      prototype.js
- * 
- *  Usage:
- *      // source should be either a string or a DOM node whose innerHTML
- *      // contains EJB source.
- *  	var source = "<% var ejb="EJB"; %><h1>Hello, <%= ejb %>!</h1>"; 
- *      var compiler = new EjsCompiler(source);		
- *	    compiler.compile();	
- *	    var output = eval(compiler.out);
- *      alert(output); // -> "<h1>Hello, EJB!</h1>"
- *       
- *  For a demo:      see demo.html
- *  For the license: see license.txt
- *
- *--------------------------------------------------------------------------*/
-
-/* Make a split function like Ruby's: "abc".split(/b/) -> ['a', 'b', 'c'] */
-String.prototype.rsplit = function(regex) {
-	var item = this;
-	var result = regex.exec(item);
-	var retArr = new Array();
-	while (result != null)
-	{
-		var first_idx = result.index;
-		var last_idx = regex.lastIndex;
-		if ((first_idx) != 0)
-		{
-			var first_bit = item.substring(0,first_idx);
-			retArr.push(item.substring(0,first_idx));
-			item = item.slice(first_idx);
-		}		
-		retArr.push(result[0]);
-		item = item.slice(result[0].length);
-		result = regex.exec(item);	
-	}
-	if (! item == '')
-	{
-		retArr.push(item);
-	}
-	return retArr;
-};
-
-/* Chop is nice to have too */
-String.prototype.chop = function() {
-	return this.substr(0, this.length - 1);
-}
-
-/* Adaptation from the Scanner of erb.rb  */
-var EjsScanner = function(source, left, right) {
-	this.left_delimiter = 	left +'%'	//<%
-	this.right_delimiter = 	'%'+right	//>
-	this.double_left = 		left+'%%'
-	this.double_right = 	'%%'+right
-	this.left_equal = 		left+'%='
-	this.left_comment = 	left+'%#'
-	if(left=='[')
-		this.SplitRegexp = /(\[%%)|(%%\])|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/;
-	else
-		this.SplitRegexp = new RegExp('('+this.double_left+')|(%%'+this.double_right+')|('+this.left_equal+')|('+this.left_comment+')|('+this.left_delimiter+')|('+this.right_delimiter+'\n)|('+this.right_delimiter+')|(\n)') 
-	
-	this.source = source;
-	this.stag = null;
-	this.lines = 0;
-};
-EjsView = function(data){
-	this.data = data
-}
-EjsView.prototype.partial = function(options, data){
-	if(!data) data = this.data;
-	return new EJS(options).render(data);
-}
-
-EjsScanner.to_text = function(input){
-	if(input == null || input === undefined)
-        return '';
-    if(input instanceof Date)
-		return input.toDateString();
-	if(input.toString) 
-        return input.toString()
-	return '';
-}
-
-EjsScanner.prototype = {
-
-  /* For each line, scan! */
-  scan: function(block) {
-     scanline = this.scanline;
-	 regex = this.SplitRegexp;
-	 if (! this.source == '')
-	 {
-	 	 var source_split = this.source.rsplit(/\n/);
-	 	 for(var i=0; i<source_split.length; i++) {
-		 	 var item = source_split[i];
-			 this.scanline(item, regex, block);
-		 }
-	 }
-  },
-  
-  /* For each token, block! */
-  scanline: function(line, regex, block) {
-	 this.lines++
-	 var line_split = line.rsplit(regex);
- 	 for(var i=0; i<line_split.length; i++) {
-	   var token = line_split[i];
-       if (token != null) {
-		   	try{
-	         	block(token, this);
-		 	}catch(e){
-				throw {type: 'EjsScanner', line: this.lines}
-			}
-       }
-	 }
-  }
-};
-
-/* Adaptation from the Buffer of erb.rb  */
-var EjsBuffer = function(pre_cmd, post_cmd) {
-	this.line = new Array();
-	this.script = "";
-	this.pre_cmd = pre_cmd;
-	this.post_cmd = post_cmd;
-	
-	for (var i=0; i<this.pre_cmd.length; i++)
-	{
-		this.push(pre_cmd[i]);
-	}
-}
-EjsBuffer.prototype = {
-	
-  push: function(cmd) {
-	this.line.push(cmd);
-  },
-
-  cr: function() {
-	this.script = this.script + this.line.join('; ');
-	this.line = new Array();
-	this.script = this.script + "\n";
-  },
-
-  close: function() {
-	if (this.line.length > 0)
-	{
-		for (var i=0; i<this.post_cmd.length; i++)
-		{
-			this.push(pre_cmd[i]);
-		}
-		this.script = this.script + this.line.join('; ');
-		line = null;
-	}
-  }
- 	
-};
-
-/* Adaptation from the Compiler of erb.rb  */
-EjsCompiler = function(source, left) {
-	this.pre_cmd = ['___ejsO = "";'];
-	this.post_cmd = new Array();
-	this.source = ' ';	
-	if (source != null)
-	{
-		if (typeof source == 'string')
-		{
-		    source = source.replace(/\r\n/g, "\n");
-            source = source.replace(/\r/g,   "\n");
-			this.source = source;
-		}
-		else if (source.innerHTML)
-		{
-			this.source = source.innerHTML;
-		} 
-		if (typeof this.source != 'string')
-		{
-			this.source = "";
-		}
-	}
-	left = left || '<'
-	var right = '>'
-	switch(left) {
-		case '[':
-			right = ']'
-			break;
-		case '<':
-			break;
-		default:
-			throw left+' is not a supported deliminator'
-			break;
-	}
-	this.scanner = new EjsScanner(this.source, left, right);
-	this.out = '';
-}
-EjsCompiler.prototype = {
-  compile: function(options) {
-  	options = options || {};
-	this.out = '';
-	var put_cmd = "___ejsO += ";
-	var insert_cmd = put_cmd;
-	var buff = new EjsBuffer(this.pre_cmd, this.post_cmd);		
-	var content = '';
-	var clean = function(content)
-	{
-	    content = content.replace(/\\/g, '\\\\');
-        content = content.replace(/\n/g, '\\n');
-        content = content.replace(/"/g,  '\\"');
-        return content;
-	} 
-	this.scanner.scan(function(token, scanner) {
-		if (scanner.stag == null)
-		{
-			//alert(token+'|'+(token == "\n"))
-			switch(token) {
-				case '\n':
-					content = content + "\n";
-					buff.push(put_cmd + '"' + clean(content) + '";');
-					buff.cr()
-					content = '';
-					break;
-				case scanner.left_delimiter:
-				case scanner.left_equal:
-				case scanner.left_comment:
-					scanner.stag = token;
-					if (content.length > 0)
-					{
-						// Chould be content.dump in Ruby
-						
-						buff.push(put_cmd + '"' + clean(content) + '"');
-					}
-					content = '';
-					break;
-				case scanner.double_left:
-					content = content + scanner.left_delimiter;
-					break;
-				default:
-					content = content + token;
-					break;
-			}
-		}
-		else {
-			switch(token) {
-				case scanner.right_delimiter:
-					switch(scanner.stag) {
-						case scanner.left_delimiter:
-							if (content[content.length - 1] == '\n')
-							{
-								content = content.chop();
-								buff.push(content);
-								buff.cr();
-							}
-							else {
-								buff.push(content);
-							}
-							break;
-						case scanner.left_equal:
-							buff.push(insert_cmd + "(EjsScanner.to_text(" + content + "))");
-							break;
-					}
-					scanner.stag = null;
-					content = '';
-					break;
-				case scanner.double_right:
-					content = content + scanner.right_delimiter;
-					break;
-				default:
-					content = content + token;
-					break;
-			}
-		}
-	});
-	if (content.length > 0)
-	{
-		// Chould be content.dump in Ruby
-		buff.push(put_cmd + '"' + clean(content) + '"');
-	}
-	buff.close();
-	this.out = buff.script + ";";
-	var to_be_evaled = 'this.process = function(_CONTEXT,_VIEW) { try { with(_VIEW) { with (_CONTEXT) {'+this.out+" return ___ejsO;}}}catch(e){e.lineNumber=null;throw e;}};";
-	
-	try{
-		eval(to_be_evaled);
-	}catch(e){
-		if(typeof JSLINT != 'undefined'){
-			JSLINT(this.out)
-			for(var i = 0; i < JSLINT.errors.length; i++){
-				var error = JSLINT.errors[i];
-				if(error.reason != "Unnecessary semicolon."){
-					error.line++;
-					var e = new Error();
-					e.lineNumber = error.line;
-					e.message = error.reason;
-					if(options.url)
-						e.fileName = options.url;
-					throw e;
-				}
-			}
-		}else{
-			throw e;
-		}
-	}
-  }
-}
-
-
-//type, cache, folder
-EJS = function( options ){
-	this.set_options(options)
-	
-	if(options.url){
-		var template = EJS.get(options.url, this.cache)
-		if (template) return template;
-	    if (template == EJS.INVALID_PATH) return null;
-		this.text = EJS.request(options.url)
-		if(this.text == null){
-			//EJS.update(options.url, this.INVALID_PATH);
-			throw 'There is no template at '+options.url
-		}
-		this.name = options.url
-	}else if(options.element)
-	{
-		if(typeof options.element == 'string'){
-			var name = options.element
-			options.element = document.getElementById(  options.element )
-			if(options.element == null) throw name+'does not exist!'
-		}
-		if(options.element.value){
-			this.text = options.element.value
-		}else{
-			this.text = options.element.innerHTML
-		}
-		this.name = options.element.id
-		this.type = '['
-	}
-	var template = new EjsCompiler(this.text, this.type);
-
-	template.compile(options);
-
-	
-	EJS.update(this.name, this);
-	this.template = template
-}
-EJS.config = function(options){
-	EJS.cache = options.cache != null ? options.cache : EJS.cache
-	EJS.type = options.type != null ? options.type : EJS.type
-	var templates_directory = {} //nice and private container
-	
-	EJS.get = function(path, cache){
-		if(cache == false) return null;
-		if(templates_directory[path]) return templates_directory[path];
-  		return null;
-	}
-	
-	EJS.update = function(path, template) { 
-		if(path == null) return;
-		templates_directory[path] = template 
-	}
-	
-	EJS.INVALID_PATH =  -1;
-	
-	
-}
-EJS.config( {cache: true, type: '<' } )
-
-EJS.prototype = {
-	render : function(object){
-		var v = new EjsView(object);
-		return this.template.process.call(v, object,v);
-	},
-	out : function(){
-		return this.template.out
-	},
-	set_options : function(options){
-		this.type = options.type != null ? options.type : EJS.type
-		this.cache = options.cache != null ? options.cache : EJS.cache
-		this.text = options.text != null ? options.text : null
-		this.name = options.name != null ? options.name : null
-	},
-	// called without options, returns a function that takes the object
-	// called with options being a string, uses that as a url
-	// called with options as an object
-	update : function(element, options){
-		if(typeof element == 'string'){
-			element = document.getElementById(element)
-		}
-		if(options == null){
-			_template = this;
-			return function(object){
-				EJS.prototype.update.call(_template, element, object)
-			}
-		}
-		if(typeof options == 'string'){
-			params = {}
-			params.url = options
-			_template = this;
-			params.onComplete = function(request){
-				var object = eval( request.responseText )
-				EJS.prototype.update.call(_template, element, object)
-			}
-			EJS.ajax_request(params)
-		}else
-		{
-			element.innerHTML = this.render(options)
-		}
-	}
-}
-
-	EJS.newRequest = function(){
-	   var factories = [function() { return new ActiveXObject("Msxml2.XMLHTTP"); },function() { return new XMLHttpRequest(); },function() { return new ActiveXObject("Microsoft.XMLHTTP"); }];
-	   for(var i = 0; i < factories.length; i++) {
-	        try {
-	            var request = factories[i]();
-	            if (request != null)  return request;
-	        }
-	        catch(e) { continue;}
-	   }
-	}
-	
-	EJS.request = function(path){
-	   var request = new EJS.newRequest()
-	   request.open("GET", path, false);
-	   
-	   try{request.send(null);}
-	   catch(e){return null;}
-	   
-	   if ( request.status == 404 || request.status == 2 ||(request.status == 0 && request.responseText == '') ) return null;
-	   
-	   return request.responseText
-	}
-	EJS.ajax_request = function(params){
-		params.method = ( params.method ? params.method : 'GET')
-		
-		var request = new EJS.newRequest();
-		request.onreadystatechange = function(){
-			if(request.readyState == 4){
-				if(request.status == 200){
-					params.onComplete(request)
-				}else
-				{
-					params.onComplete(request)
-				}
-			}
-		}
-		request.open(params.method, params.url)
-		request.send(null)
-	}
-//}
-
-

File lib/helpers/ejs/view.js

-EjsView.prototype.date_tag = function(name, value , html_options) {
-    if(! (value instanceof Date))
-		value = new Date()
-	
-	var month_names = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
-	var years = [], months = [], days =[];
-	var year = value.getFullYear();
-	var month = value.getMonth();
-	var day = value.getDate();
-	for(var y = year - 15; y < year+15 ; y++)
-	{
-		years.push({value: y, text: y})
-	}
-	for(var m = 0; m < 12; m++)
-	{
-		months.push({value: (m), text: month_names[m]})
-	}
-	for(var d = 0; d < 31; d++)
-	{
-		days.push({value: (d+1), text: (d+1)})
-	}
-	var year_select = this.select_tag(name+'[year]', year, years, {id: name+'[year]'} )
-	var month_select = this.select_tag(name+'[month]', month, months, {id: name+'[month]'})
-	var day_select = this.select_tag(name+'[day]', day, days, {id: name+'[day]'})
-	
-    return year_select+month_select+day_select;
-}
-
-EjsView.prototype.form_tag = function(action, html_options) {
-                 
-    
-    html_options     = html_options                     || {};
-	html_options.action = action
-    if(html_options.multipart == true) {
-        html_options.method = 'post';
-        html_options.enctype = 'multipart/form-data';
-    }
-    
-    return this.start_tag_for('form', html_options)
-}
-
-EjsView.prototype.form_tag_end = function() { return this.tag_end('form'); }
-
-EjsView.prototype.hidden_field_tag   = function(name, value, html_options) { 
-    return this.input_field_tag(name, value, 'hidden', html_options); 
-}
-
-EjsView.prototype.input_field_tag = function(name, value , inputType, html_options) {
-    
-    html_options = html_options || {};
-    html_options.id  = html_options.id  || name;
-    html_options.value = value || '';
-    html_options.type = inputType || 'text';
-    html_options.name = name;
-    
-    return this.single_tag_for('input', html_options)
-}
-
-EjsView.prototype.is_current_page = function(url) {
-	return (window.location.href == url || window.location.pathname == url ? true : false);
-}
-
-EjsView.prototype.link_to = function(name, url, html_options) {
-    if(!name) var name = 'null';
-    if(!html_options) var html_options = {}
-	
-	if(html_options.confirm){
-		html_options.onclick = 
-		" var ret_confirm = confirm(\""+html_options.confirm+"\"); if(!ret_confirm){ return false;} "
-		html_options.confirm = null;
-	}
-    html_options.href=url
-    return this.start_tag_for('a', html_options)+name+ this.tag_end('a');
-}
-
-EjsView.prototype.submit_link_to = function(name, url, html_options){
-	if(!name) var name = 'null';
-    if(!html_options) var html_options = {}
-    html_options.onclick = html_options.onclick  || '' ;
-	
-	if(html_options.confirm){
-		html_options.onclick = 
-		" var ret_confirm = confirm(\""+html_options.confirm+"\"); if(!ret_confirm){ return false;} "
-		html_options.confirm = null;
-	}
-	
-    html_options.value = name;
-	html_options.type = 'submit'
-    html_options.onclick=html_options.onclick+
-		(url ? this.url_for(url) : '')+'return false;';
-    //html_options.href='#'+(options ? Routes.url_for(options) : '')
-	return this.start_tag_for('input', html_options)
-}
-
-EjsView.prototype.link_to_if = function(condition, name, url, html_options, post, block) {
-	return this.link_to_unless((condition == false), name, url, html_options, post, block);
-}
-
-EjsView.prototype.link_to_unless = function(condition, name, url, html_options, block) {
-	html_options = html_options || {};
-	if(condition) {
-		if(block && typeof block == 'function') {
-			return block(name, url, html_options, block);
-		} else {
-			return name;
-		}
-	} else
-		return this.link_to(name, url, html_options);
-}
-
-EjsView.prototype.link_to_unless_current = function(name, url, html_options, block) {
-	html_options = html_options || {};
-	return this.link_to_unless(this.is_current_page(url), name, url, html_options, block)
-}
-
-
-EjsView.prototype.password_field_tag = function(name, value, html_options) { return this.input_field_tag(name, value, 'password', html_options); }
-
-EjsView.prototype.select_tag = function(name, value, choices, html_options) {     
-    html_options = html_options || {};
-    html_options.id  = html_options.id  || name;
-    html_options.value = value;
-	html_options.name = name;
-    
-    var txt = ''
-    txt += this.start_tag_for('select', html_options)
-    
-    for(var i = 0; i < choices.length; i++)
-    {
-        var choice = choices[i];
-        var optionOptions = {value: choice.value}
-        if(choice.value == value)
-            optionOptions.selected ='selected'
-        txt += this.start_tag_for('option', optionOptions )+choice.text+this.tag_end('option')
-    }
-    txt += this.tag_end('select');
-    return txt;
-}
-
-EjsView.prototype.single_tag_for = function(tag, html_options) { return this.tag(tag, html_options, '/>');}
-
-EjsView.prototype.start_tag_for = function(tag, html_options)  { return this.tag(tag, html_options); }
-
-EjsView.prototype.submit_tag = function(name, html_options) {  
-    html_options = html_options || {};
-    //html_options.name  = html_options.id  || 'commit';
-    html_options.type = html_options.type  || 'submit';
-    html_options.value = name || 'Submit';
-    return this.single_tag_for('input', html_options);
-}
-
-EjsView.prototype.tag = function(tag, html_options, end) {
-    if(!end) var end = '>'
-    var txt = ' '
-    for(var attr in html_options) { 
-	   if(html_options[attr] != null)
-        var value = html_options[attr].toString();
-       else
-        var value=''
-       if(attr == "Class") // special case because "class" is a reserved word in IE
-        attr = "class";
-       if( value.indexOf("'") != -1 )
-            txt += attr+'=\"'+value+'\" ' 
-       else
-            txt += attr+"='"+value+"' " 
-    }
-    return '<'+tag+txt+end;
-}
-
-EjsView.prototype.tag_end = function(tag)             { return '</'+tag+'>'; }
-
-EjsView.prototype.text_area_tag = function(name, value, html_options) { 
-    html_options = html_options || {};
-    html_options.id  = html_options.id  || name;
-    html_options.name  = html_options.name  || name;
-	value = value || ''
-    if(html_options.size) {
-        html_options.cols = html_options.size.split('x')[0]
-        html_options.rows = html_options.size.split('x')[1]
-        delete html_options.size
-    }
-    
-    html_options.cols = html_options.cols  || 50;
-    html_options.rows = html_options.rows  || 4;
-    
-    return  this.start_tag_for('textarea', html_options)+value+this.tag_end('textarea')
-}
-EjsView.prototype.text_tag = EjsView.prototype.text_area_tag
-
-EjsView.prototype.text_field_tag     = function(name, value, html_options) { return this.input_field_tag(name, value, 'text', html_options); }
-
-EjsView.prototype.url_for = function(url) {
-        return 'window.location="'+url+'";'
-}
-EjsView.prototype.img_tag = function(image_location, alt, options){
-	options = options || {};
-	options.src = image_location
-	options.alt = alt
-	return this.single_tag_for('img', options)
-}

File lib/helpers/md5.js

-/*
- * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
- * Digest Algorithm, as defined in RFC 1321.
- * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
- * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
- * Distributed under the BSD License
- * See http://pajhome.org.uk/crypt/md5 for more info.
- */
-
-/*
- * Configurable variables. You may need to tweak these to be compatible with
- * the server-side, but the defaults work in most cases.
- */
-var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
-var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
-var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
-
-/*
- * These are the functions you'll usually want to call
- * They take string arguments and return either hex or base-64 encoded strings
- */
-function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
-function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
-function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
-function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
-function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
-function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
-
-/*
- * Perform a simple self-test to see if the VM is working
- */
-function md5_vm_test()
-{
-  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
-}
-
-/*
- * Calculate the MD5 of an array of little-endian words, and a bit length
- keep
- */
-function core_md5(x, len)
-{
-  /* append padding */
-  x[len >> 5] |= 0x80 << ((len) % 32);
-  x[(((len + 64) >>> 9) << 4) + 14] = len;
-
-  var a =  1732584193;
-  var b = -271733879;
-  var c = -1732584194;
-  var d =  271733878;
-
-  for(var i = 0; i < x.length; i += 16)
-  {
-    var olda = a;
-    var oldb = b;
-    var oldc = c;
-    var oldd = d;
-
-    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
-    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
-    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
-    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
-    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
-    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
-    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
-    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
-    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
-    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
-    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
-    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
-    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
-    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
-    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
-    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
-
-    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
-    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
-    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
-    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
-    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
-    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
-    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
-    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
-    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
-    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
-    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
-    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
-    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
-    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
-    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
-    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
-
-    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
-    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
-    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
-    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
-    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
-    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
-    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
-    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
-    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
-    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
-    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
-    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
-    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
-    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
-    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
-    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
-
-    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
-    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
-    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
-    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
-    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
-    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
-    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
-    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
-    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
-    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
-    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
-    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
-    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
-    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
-    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
-    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
-
-    a = safe_add(a, olda);
-    b = safe_add(b, oldb);
-    c = safe_add(c, oldc);
-    d = safe_add(d, oldd);
-  }
-  return Array(a, b, c, d);
-
-}
-
-/*
- * These functions implement the four basic operations the algorithm uses.
- */
-function md5_cmn(q, a, b, x, s, t)
-{
-  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
-}
-function md5_ff(a, b, c, d, x, s, t)
-{
-  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
-}
-function md5_gg(a, b, c, d, x, s, t)
-{
-  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
-}
-function md5_hh(a, b, c, d, x, s, t)
-{
-  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
-}
-function md5_ii(a, b, c, d, x, s, t)
-{
-  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
-}
-
-/*
- * Calculate the HMAC-MD5, of a key and some data
- */
-function core_hmac_md5(key, data)
-{
-  var bkey = str2binl(key);
-  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
-
-  var ipad = Array(16), opad = Array(16);
-  for(var i = 0; i < 16; i++)
-  {
-    ipad[i] = bkey[i] ^ 0x36363636;
-    opad[i] = bkey[i] ^ 0x5C5C5C5C;
-  }
-
-  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
-  return core_md5(opad.concat(hash), 512 + 128);
-}
-
-/*
- * Add integers, wrapping at 2^32. This uses 16-bit operations internally
- * to work around bugs in some JS interpreters.
- */
-function safe_add(x, y)
-{
-  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
-  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
-  return (msw << 16) | (lsw & 0xFFFF);
-}
-
-/*
- * Bitwise rotate a 32-bit number to the left.
- */
-function bit_rol(num, cnt)
-{
-  return (num << cnt) | (num >>> (32 - cnt));
-}
-
-/*
- * Convert a string to an array of little-endian words
- * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
- keep
- */
-function str2binl(str)
-{
-  var bin = Array();
-  var mask = (1 << chrsz) - 1;
-  for(var i = 0; i < str.length * chrsz; i += chrsz)
-    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
-  return bin;
-}
-
-/*
- * Convert an array of little-endian words to a string
- */
-function binl2str(bin)
-{
-  var str = "";
-  var mask = (1 << chrsz) - 1;
-  for(var i = 0; i < bin.length * 32; i += chrsz)
-    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
-  return str;
-}
-
-/*
- * Convert an array of little-endian words to a hex string.
- keep
- */
-function binl2hex(binarray)
-{
-  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
-  var str = "";
-  for(var i = 0; i < binarray.length * 4; i++)
-  {
-    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
-           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
-  }
-  return str;
-}
-
-/*
- * Convert an array of little-endian words to a base-64 string
- */
-function binl2b64(binarray)
-{
-  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-  var str = "";
-  for(var i = 0; i < binarray.length * 4; i += 3)
-  {
-    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
-                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
-                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
-    for(var j = 0; j < 4; j++)
-    {
-      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
-      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
-    }
-  }
-  return str;
-}

File lib/helpers/template.js

-// simple helper to reder template from ejs
-//
-
-function template(str, data) {
-    html = new EJS({text: str}).render(data);
-    return html;
-}
-
-

File lib/templates/edit.html

-<!DOCTYPE html>
-<html lang="fr">
-<head>
-    <meta charset="utf-8"/>
-    <title>benoît chesneau web - edit</title>
-
-    <!--[if IE]>
-
-    <script>
-        // allow IE to recognize HTMl5 elements
-        document.createElement('section');
-        document.createElement('article');
-        document.createElement('aside');
-        document.createElement('footer');
-        document.createElement('header');
-        document.createElement('nav');
-        document.createElement('time');
-
-    </script>
-    <![endif]-->
-    <link rel="openid.server" href="http://www.myopenid.com/server">
-    <link rel="openid.delegate" href="http://bchesneau.myopenid.com/">
-    <link rel="home index" href="http://benoitc.org/" type="text/html">
-    <link rel="me author" href="http://benoitc.org/static/benoitc.html" type="text/html">
-
-    <link rel="stylesheet" href="../../css/benoitc.css" type="text/css" media="screen, projection" />
-    
-
-
-</head>
-
-
-<body>
-        <header>
-        <h1>
-            <a rel="me author" href="../../benoitc.html">Benoît Chesneau</a>
-        </h1>
-        </header>
-        <div id="edit">
-            <h2>Nouvel article</h2>
-            <form id="fedit" name="fedit" action="new.html"
-                method="post">
-                        
-                <textarea name="body" id="body" cols="80"
-                    rows="20"></textarea>
-                
-                <ol>
-                    <li><label for="title">Titre<label><input type="text"
-                            name="title" id="title" value=""></li>
-
-                    <li><label for="labels">Libellés</label><input type="text"
-                name="labels" id="labels" value=""></li>
-                </ol>
-                
-                <p><input type="submit" name="save" id="save" value="Save">
-                or <a href="<%= index %>">Cancel</a> <span id="saved" style="display:none;">Saved</span></p>
-            </form>
-            <div id="mdpreview"></div>
-        </div>
-
-        <footer id="main-footer">
-        <p>2009 (c) <a href="../../benoitc.html">Benoît Chesneau</a> - <a rel="license" href="http://creativecommons.org/licenses/by/2.0/fr/">Certains droits reservés</a>.</p>
-        </footer> 
-
-    
-</body>
-
-    <script src="/_utils/script/json2.js"></script>
-    <script src="/_utils/script/jquery.js"></script>
-    <script src="/_utils/script/jquery.cookies.js"></script>
-    <script src="/_utils/script/jquery.couch.js"></script>
-    <script src="../../js/showdown.js"></script>
-    <script src="../../js/textarea.jquery.js"></script>
-    <script src="../../js/jquery.couchapp.js"></script>
-    <script src="../../js/editor.js"></script>
-    <script src="../../js/strftime.js"></script>
-    <script src="../../js/blog.js"></script>
-    <script src="../../js/urlify.js"></script>
-
-    <script>
-        $(document).ready(function() {
-
-            $.CouchApp(function(app) {
-                app.loggedInNow(function(login) {
-                    $("header").prepend('<span id="login">'+login+'</span>');
-                    
-                    var B = new Blog(app);
-
-                    var postForm = app.docForm("form#fedit", {
-                        id : <%= docid %>,
-                        fields : ["title", "body", "labels"],
-                        template : {
-                            doc_type : "post",
-                            format : "markdown",
-                            author : login
-                        },
-                        onLoad : function(doc) {
-                            if (doc._id) {
-                                $("#edit h2").html('Édition de ' + B.link_for(doc._id));
-                            } 
-                        },
-                        beforeSave : function(doc) {
-                            if (doc.body)
-                                doc.html = B.formatBody(doc.body);
-
-                            if (!doc.created_at) {
-                                doc.created_at = new Date().rfc3339();
-                            }
-
-                            if (!doc.slug && doc.title) {
-                                doc.slug = doc.created_at.slice(0, 10).replace(/\-*/g, '') 
-                                + "_" + URLify(doc.title, 255);
-                                doc._id = doc.slug;
-                            }
-
-                            doc.updated = new Date().rfc3339();
-                            if(doc.labels) {
-                                doc.labels = doc.labels.split(",");
-                                for(var idx in doc.labels) {
-                                    doc.labels[idx] = $.trim(doc.labels[idx]);
-                                }
-                            } 
-                        },
-                        success : function(resp) {
-                           $("#saved").text("Enregistré _rev: "+resp.rev).fadeIn(500).fadeOut(3000);
-                           $("#edit h2").html('Édition de ' + B.link_for(resp.id));
-                        }
-                    });  
-
-                    new Editor(); 
-                    }, function() {
-                    // callback
-                    $('body').append('<a href="../../account.html#'+document.location+'">redirect</a>');
-                    var absurl = $('body a:last')[0].href;
-                    document.location = absurl;
-                });
-            });
-        
-        });
-    </script>
-</html>

File lib/templates/index/head.html

-<!DOCTYPE html>
-<html lang="fr">
-<head>
-    <meta charset="utf-8"/>
-    <title>benoît chesneau web, artisan web.</title>
-
-    <!--[if IE]>
-
-    <script>
-        // allow IE to recognize HTMl5 elements
-        document.createElement('section');
-        document.createElement('article');
-        document.createElement('aside');
-        document.createElement('footer');
-        document.createElement('header');
-        document.createElement('nav');
-        document.createElement('time');
-
-    </script>
-    <![endif]-->
-    <link rel="openid.server" href="http://www.myopenid.com/server">
-    <link rel="openid.delegate" href="http://bchesneau.myopenid.com/">
-    <link rel="home index" href="http://benoitc.org/" type="text/html">
-    <link rel="me author" href="http://benoitc.org/static/benoitc.html" type="text/html">
-    <link type='application/atom+xml' href='<%= feedPath %>' rel='alternate' title='Writings'>
-
-    <link rel="stylesheet" href="../../css/benoitc.css" type="text/css" media="screen, projection" />
-</head>
-
-
-<body class="index">
-    <div id="container">
-        <header class="page">
-            <nav id="mainav">
-                <ul>
-                    <li><a href="<%= archivesPath %>">archives</a></li>
-                    <li><a href="<%= feedPath %>" type='application/atom+xml' class="atom">suivre</a></li>
-                </ul>
-            </nav>
-            <h1>
-                <a rel="me author" href="../../benoitc.html">Benoît Chesneau</a>
-            </h1>
-            <h2>artisan web</h2>
-
-            
-        </header>

File lib/templates/index/row.html

-<article class="entry article">
-    <header class="meta">
-        <p><time title="GMT" datetime="<%= post.created_at %>"
-        class="caps"><%= fcreated_at %></time></p>
-    </header>
-    <h3>
-        <a href="<%= link %>"><%= post.title %></a>
-    </h3>
-    <p><%= post.summary %></p>
-</article>

File lib/templates/index/tail.html

-        <p class="next"><a href="<%= nextPath %>">articles suivants »</a></p>
-
-        <footer id="main-footer">
-            <p>2009 (c) <a href="../../benoitc.html">Benoît Chesneau</a> - <a rel="license" href="http://creativecommons.org/licenses/by/2.0/fr/">Certains droits reservés</a>.</p>
-        </footer>
-    </div>
-</body>
-    <script src="/_utils/script/json2.js"></script>
-    <script src="/_utils/script/jquery.js"></script>
-    <script src="/_utils/script/jquery.couch.js"></script>
-    <script src="../../js/jquery.couchapp.js"></script>
-    <script src="../../js/strftime.js"></script>
-    <script src="../../js/blog.js"></script>
-    <script>
-        $(document).ready(function() {
-            localizeDates();
-        });
-
-    </script>
-</html>

File lib/templates/post.html

-<!DOCTYPE html>
-<html lang="fr">
-<head>
-    <meta charset="utf-8"/>
-    <title>benoît chesneau web - <%= doc.title %></title>
-
-    <!--[if IE]>
-
-    <script>
-        // allow IE to recognize HTMl5 elements
-        document.createElement('section');
-        document.createElement('article');
-        document.createElement('aside');
-        document.createElement('footer');
-        document.createElement('header');
-        document.createElement('nav');
-        document.createElement('time');
-
-    </script>
-    <![endif]-->
-    <link rel="openid.server" href="http://www.myopenid.com/server">
-    <link rel="openid.delegate" href="http://bchesneau.myopenid.com/">
-    <link rel="home index" href="http://benoitc.org" type="text/html">
-    <link rel="me author" href="http://benoitc.org/static/benoitc.html" type="text/html">
-
-    <link rel="stylesheet" href="../../css/benoitc.css" type="text/css" media="screen, projection" />
-
-
-</head>
-
-
-<body>
-    <div id="container">
-        <header id="adminheader"></header>
-        <section id="maincontent"> 
-        <article class="article content">
-            <header>
-                <h1><%= doc.title %></h1>
-                <time title="GMT" datetime="<%= doc.created_at %>" class="caps"><%= fcreated_at %></time>     
-                <p><a rel="me author" href="../../benoitc.html">Benoît Chesneau</a></p>       
-            </header>    
-            <%= doc.html %>
-            <% if (labels) { %>
-            <footer>
-            <p>Cette entrée a été marquée <%= labels %> — Suivez un des libellés pour obtenir d'autres articles ou essais en relation.</p>
-            </footer>
-            <% } %>
-        </article>
-        </section>
-        <section id="comments">
-            <h2>Discutez</h2>
-            <ol></ol>
-            <h2>Laissez un commentaire</h2>
-            <form id="new-comment" action="post.html" class="leave" method="post">
-                <div>
-
-                    <label for="commenter-name">Nom</label>
-                    <br>
-                    <input name="commenter-name" type="text">
-                    <br>
-                    <label for="commenter-url">URL (optionnel)</label>
-                    <br>
-                    <input name="commenter-url" type="text" value="">
-                    <br>
-                    <label for="commenter-email">Courriel</label>
-                    <small>(pour <a href="http://gravatar.com">Gravatar</a>)</small>
-                    <br />
-                    <input type="text" name="commenter-email" value="">
-                    <br />
-                    <label for="comment">Commentaire</label>
-                    <small>(syntaxe: <a href="http://daringfireball.net/projects/markdown/syntax" title="Markdown Syntax Reference">markdown</a>)</small>
-                    <br>
-                    <textarea id="comment" name="comment" rows="8" style="width: 100%;"></textarea>
-                    <input type="button" id="preview" value="Prévisualiser">&nbsp;<input value="Laissez un commentaire" type="submit">
-                </div>
-                <div id="comment-preview"></div>
-            </form>
-            
-        </section>
-
-        <footer id="main-footer">
-            <p>2009 (c) <a href="../../benoitc.html">Benoît Chesneau</a> - <a rel="license" href="http://creativecommons.org/licenses/by/2.0/fr/">Certains droits reservés</a>.</p>
-        </footer> 
-    </div>
-</body>
-    <script src="/_utils/script/json2.js"></script>
-    <script src="/_utils/script/jquery.js"></script>
-    <script src="/_utils/script/jquery.couch.js"></script>
-    <script src="/_utils/script/jquery.cookies.js"></script>
-    <script src="../../js/jquery.couchapp.js"></script>
-    <script src="../../js/strftime.js"></script>
-    <script src="../../js/showdown.js"></script>
-    <script src="../../js/blog.js"></script>
-    <script src="../../js/md5.js"></script>  
-    <script>
-        $(document).ready(function() {
-            localizeDates();
-
-            $.CouchApp(function(app) {
-                if (app.is_logged()) {
-                    $("#adminheader").html('<p><a href="<%= editPath %>">Edit</a>'
-                    +'</p>');
-                }
-                var docid = document.location.pathname.split('/').pop();
-                var B = new Blog(app);
-                function displayComments() {
-                    app.design.view("comments", {
-                    startkey: [docid],
-                    endkey: [docid, {}],
-                    reduce : false,
-                    success: function(json) {
-                        var ol = $("#comments ol");
-                        for (var i=0; i < json.rows.length; i++) {
-                            var c = json.rows[i].value;
-                        ol.append(B.commentListing(c));
-                        }
-                        $('#comments').fadeIn(2000);      
-                    }
-                    });
-                };
-              
-              displayComments();
-              localizeDates();
-
-              var commentForm = app.docForm("form#new-comment", {
-                fields : [
-                  "commenter-name", 
-                  "commenter-email", 
-                  "commenter-url", 
-                  "comment"
-                ],
-                template : {
-                  doc_type : "comment",
-                  post_id : docid,
-                  format : "markdown"
-                },
-                beforeSave : function(doc) {
-                    if (doc.comment)
-                        doc.html = B.formatBody(doc.comment);
-                  doc.created_at = new Date().rfc3339();
-                },
-                success : function(resp, doc) {
-                  if (doc.commenter.email) { 
-                        doc.commenter.gravatar = hex_md5(doc.commenter.email);
-                  } else {
-                    doc.commenter.gravatar = null;
-                  }
-                  $("#new-comment").html("<h3>votre commentaire vient d'être ajouté.</h3>");
-                  $("#comments ol").append(B.commentListing(doc));
-                  $("#comments ol li:last").hide().fadeIn(2000);
-                }
-              });
-              
-              $("#preview").click(function() {
-                var doc = commentForm.localDoc();
-                if (typeof doc.comment != "undefined" && doc.comment) {
-                    var html = B.formatBody(doc.comment);
-                    $('#comment-preview').html(html);
-                }
-              });
-            });
-        });
-
-    </script>
-</html>

File lib/templates/search/head.html

-<!DOCTYPE html>
-<html lang="fr">
-<head>
-    <meta charset="utf-8"/>
-    <title>benoît chesneau web - search</title>
-
-    <!--[if IE]>
-
-    <script>
-        // allow IE to recognize HTMl5 elements
-        document.createElement('section');
-        document.createElement('article');
-        document.createElement('aside');
-        document.createElement('footer');
-        document.createElement('header');
-        document.createElement('nav');
-        document.createElement('time');
-
-    </script>
-    <![endif]-->
-    <link rel="openid.server" href="http://www.myopenid.com/server">
-    <link rel="openid.delegate" href="http://bchesneau.myopenid.com/">
-    <link rel="home index" href="http://benoitc.org/" type="text/html">
-    <link rel="me author" href="http://benoitc.org/static/benoitc.html" type="text/html">
-    <link type='application/atom+xml' href='<%= feedPath %>' rel='alternate' title='Writings'>
-
-    <link rel="stylesheet" href="../../css/benoitc.css" type="text/css" media="screen, projection" />
-</head>
-
-
-<body class="index">
-    <div id="container">
-        <header class="page">
-            <nav id="mainav">
-                <ul>
-                    <li><a href="<%= archivesPath %>">archives</a></li>
-                    <li><a href="<%= feedPath %>" type='application/atom+xml' class="atom">suivre</a></li>
-
-                </ul>
-            </nav>
-            <h1>
-                <a rel="me author" href="../../benoitc.html">Benoît Chesneau</a>
-            </h1>
-            <h2>artisan web</h2>
-
-            
-        </header>

File lib/templates/search/row.html

-<article class="entry article">
-    <header class="meta">
-        <p><time title="GMT" datetime="<%= post.created_at %>"
-        class="caps"><%= fcreated_at %></time></p>
-    </header>
-    <h3>
-        <a href="<%= link %>"><%= post.title %></a>
-    </h3>
-    <p><%= post.summary %></p>
-</article>

File lib/templates/search/tail.html

-        <footer id="main-footer">
-            <p>2009 (c) <a href="../../benoitc.html">Benoît Chesneau</a> - <a rel="license" href="http://creativecommons.org/licenses/by/2.0/fr/">Certains droits reservés</a>.</p>
-        </footer>
-    </div>
-</body>
-    <script src="/_utils/script/json2.js"></script>
-    <script src="/_utils/script/jquery.js"></script>
-    <script src="/_utils/script/jquery.couch.js"></script>
-    <script src="../../js/jquery.couchapp.js"></script>
-    <script src="../../js/strftime.js"></script>
-    <script src="../../js/blog.js"></script>
-    <script>
-        $(document).ready(function() {
-            localizeDates();
-        });
-
-    </script>
-</html>

File lists/index.js

-function(head, row, req, row_info) {
-  // !json lib.templates.index
+function(head, req) {
+  // !json templates.index
   // !json blog
-  // !code lib/helpers/ejs/*.js
-  // !code lib/helpers/template.js
-  // !code vendor/couchapp/date.js
-  // !code vendor/couchapp/path.js
+  // !code vendor/inditeweb/ejs/*.js
+  // !code vendor/inditeweb/template.js
+  // !code vendor/inditeweb/date.js
+  // !code vendor/inditeweb/path.js
     
   var indexPath = listPath('index','recent-posts',{descending:true, limit:8});
   var feedPath = listPath('index','recent-posts',{descending:true, limit:8, format:"atom"});
   
   registerType("sitemap", "application/x-xml");
   
-  return respondWith(req, {
-    html: function() {
-        if (head) {
-            return template(lib.templates.index.head, {
-                assets: assetPath(),
-                archivesPath: archivesPath,
-                feedPath: feedPath
-            });
-        } else if (row) {
-            if (!req.query.limit && row_info.row_number == 7)
-                return {stop: true};
-                
-            var fcreated_at = new Date().setRFC3339(row.value.created_at).toLocaleString();
-            return template(lib.templates.index.row, {
+  provides("html", function() {
+    // display head
+    send(template(templates.index.head, {
+          assets: assetPath(),
+          archivesPath: archivesPath,
+          feedPath: feedPath
+    }));
+    
+    // display lines
+    var row, key, first_key,
+  	i = 0;
+    while (row =getRow()) {
+      // limit number of displayed lines to 8
+      if (!req.query.limit && i > 7)
+        break;
+      
+      var fcreated_at = new Date().setRFC3339(row.value.created_at).toLocaleString();
+      send(template(templates.index.row, {
                     post: row.value,
                     fcreated_at: fcreated_at,
                     link: showPath('post', row.id),
                     assets: assetPath(),
                     feedPath: feedPath
+      }));
+      if (i == 0)
+        first_key = row.key;
+      i = i + 1;
+      key = row.key;
+    }
+            
+    var nextPath = listPath('index','recent-posts', {
+      startkey: (key || "#"), 
+      descending:true, 
+      limit:25 });
+
+    return template(templates.index.tail, {
+              nextPath: nextPath,
+              assets: assetPath()
             });
-        } else {
-            var nextPath = listPath('index','recent-posts', {
-                    startkey: ((row_info &&row_info.prev_key) || "#"), 
-                    descending:true, 
-                    limit:25 });
+  });
 
-            return template(lib.templates.index.tail, {
-                nextPath: nextPath,
-                assets: assetPath()
-            });
-        }
-    },
-    atom: function() {
-      // with first row in head you can do updated.
-      if (head) {
-        var f = <feed xmlns="http://www.w3.org/2005/Atom"/>;
-        f.title = blog.title;
-        f.id = makeAbsolute(req, indexPath);
-        f.link.@href = makeAbsolute(req, feedPath);
-        f.link.@rel = "self";
-        f.generator = 'benoitc.org';
-        f.updated = new Date().rfc3339();
-        return {body:'<?xml version="1.0" encoding="UTF-8"?>\n'+
-                f.toXMLString().replace(/\<\/feed\>/,'')};
-      } else if (row) {
-        var entry = <entry/>;
-        entry.id = makeAbsolute(req, '/'+encodeURIComponent(req.info.db_name)+'/'+encodeURIComponent(row.id));
-        entry.title = row.value.title;
-        entry.content = row.value.summary;
-        entry.content.@type = 'html';
-        entry.updated = row.value.created_at;
-        entry.author = <author><name>{row.value.author}</name></author>;
-        entry.link.@href = makeAbsolute(req, showPath('post', row.id));
-        entry.link.@rel = "alternate";
-        return {body:entry};
-      } else {
-        return {body: "</feed>"};
-      }
-    },
-    sitemap: function() {
-      //sitemap
-       if (head) {
-        return {body:'<?xml version="1.0" encoding="UTF-8"?>\n'+
-            '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"/>'};
-      } else if (row) {
-        var url = <url/>;
-        url.loc = makeAbsolute(req, showPath('post', row.id));
-        url.lastmod = row.value.created_at;
-        url.changefreq = "daily";
-        url.priority = "0.5";
-        return {body:url};
-      } else {
-        return {body: "</urlset>"};
-      }
+  provides("atom", function() {
+    // with first row in head you can do updated.
+    var f = <feed xmlns="http://www.w3.org/2005/Atom"/>;
+    f.title = blog.title;
+    f.id = makeAbsolute(req, indexPath);
+    f.link.@href = makeAbsolute(req, feedPath);
+    f.link.@rel = "self";
+    f.generator = 'benoitc.org';
+    f.updated = new Date().rfc3339();
+    send('<?xml version="1.0" encoding="UTF-8"?>\n'+
+      f.toXMLString().replace(/\<\/feed\>/,''));
+    
+    while (row=getRow()) {
+      var entry = <entry/>;
+      entry.id = makeAbsolute(req, '/'+encodeURIComponent(req.info.db_name)+'/'+encodeURIComponent(row.id));
+      entry.title = row.value.title;
+      entry.content = row.value.summary;
+      entry.content.@type = 'html';
+      entry.updated = row.value.created_at;
+      entry.author = <author><name>{row.value.author}</name></author>;
+      entry.link.@href = makeAbsolute(req, showPath('post', row.id));
+      entry.link.@rel = "alternate";
+      send(entry);
+    }
+    return "</feed>";
+  });
 
+  provides("sitemap", function() {
+    //sitemap
+    send('<?xml version="1.0" encoding="UTF-8"?>\n'+
+      '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"/>');
+    while (row=getRow()) {
+      var url = <url/>;
+      url.loc = makeAbsolute(req, showPath('post', row.id));
+      url.lastmod = row.value.created_at;
+      url.changefreq = "daily";
+      url.priority = "0.5";
+      send (url);
     }
-  })
+    return "</urlset>";
+
+  });
+
 };

File lists/search.js

-function(head, row, req, row_info) {
-  // !json lib.templates.search
+function(head, req) {
+  // !json templates.search
   // !json blog
-  // !code lib/helpers/ejs/*
-  // !code lib/helpers/template.js
-  // !code vendor/couchapp/date.js
-  // !code vendor/couchapp/path.js
-    
+  // !code vendor/inditeweb/ejs/*.js
+  // !code vendor/inditeweb/template.js
+  // !code vendor/inditeweb/date.js
+  // !code vendor/inditeweb/path.js
+
   var indexPath = listPath('index','recent-posts',{descending:true, limit:8});
   var feedPath = listPath('search','topics',{descending:true, limit:8, format:"atom"});
   var archivesPath = listPath('index','recent-posts',{descending:true, limit:25});
-  return respondWith(req, {
-    html: function() {
-        if (head) {
-            return template(lib.templates.search.head, {
-                assets: assetPath(),
-                archivesPath: archivesPath,
-                feedPath: feedPath
-
-            });
-        } else if (row) {
-
-            var fcreated_at = new Date().setRFC3339(row.value.created_at).toLocaleString();
-            return template(lib.templates.search.row, {
-                    post: row.value,
-                    fcreated_at: fcreated_at,
-                    link: showPath('post', row.id),
-                    assets: assetPath()
-            });
-        } else {
-            return template(lib.templates.search.tail, {
-                archivesPath: archivesPath,
+  provides("html", function() {
+	  // send head
+  	send(template(templates.search.head, {
+  		assets: assetPath(),
+  		archivesPath: archivesPath,
+  		feedPath: feedPath
+  	}));
+      
+      // send rows
+  	var row, key, first_key,
+  	i = 0;
+  	while (row = getRow()) {
+        var fcreated_at = new Date().setRFC3339(row.value.created_at).toLocaleString();
+        send(template(templates.search.row, {
+                post: row.value,
+                fcreated_at: fcreated_at,
+                link: showPath('post', row.id),
                 assets: assetPath()
-            });
-        }
-    },
-    atom: function() {
+        }));
+  	}
+    
+      // send footer
+    return template(templates.search.tail, {
+  		archivesPath: archivesPath,
+  		assets: assetPath()
+  	});
+  });
+  
+  provides("atom", function() {
       // with first row in head you can do updated.
-      if (head) {
-        var f = <feed xmlns="http://www.w3.org/2005/Atom"/>;
-        f.title = blog.title;
-        f.id = makeAbsolute(req, indexPath);
-        f.link.@href = makeAbsolute(req, feedPath);
-        f.link.@rel = "self";
-        f.generator = 'benoitc.org';
-        f.updated = new Date().rfc3339();
-        return {body:'<?xml version="1.0" encoding="UTF-8"?>\n'+
-                f.toXMLString().replace(/\<\/feed\>/,'')};
-      } else if (row) {
+    var f = <feed xmlns="http://www.w3.org/2005/Atom"/>;
+	f.title = blog.title; 
+	f.id = makeAbsolute(req, indexPath);
+	f.link.@href = makeAbsolute(req, feedPath);
+    f.link.@rel = "self";
+    f.generator = 'benoitc.org';
+    f.updated = new Date().rfc3339();
+    send('<?xml version="1.0" encoding="UTF-8"?>\n'+
+                f.toXMLString().replace(/\<\/feed\>/,''));
+                
+    while (row = getRow()) {
         var entry = <entry/>;
         entry.id = makeAbsolute(req, '/'+encodeURIComponent(req.info.db_name)+'/'+encodeURIComponent(row.id));
         entry.title = row.value.title;
         entry.author = <author><name>{row.value.author}</name></author>;
         entry.link.@href = makeAbsolute(req, showPath('post', row.id));
         entry.link.@rel = "alternate";
-        return {body:entry};
-      } else {
-        return {body: "</feed>"};
-      }
+        send(entry);
     }
-  })
+    
+    return "</feed>";
+  });
 };

File shows/edit.js

-function(doc, req) {  
-  // !json lib.templates.edit
-  // !json blog
-  // !code lib/helpers/ejs/*
-  // !code lib/helpers/template.js
-  // !code vendor/couchapp/date.js
-  // !code vendor/couchapp/path.js
-
-  // we only show html
-  //
-
-  return template(lib.templates.edit, {
-    doc : doc,
-    docid : toJSON((doc && doc._id) || null), 
-    assets : assetPath(),
-    index : listPath('index','recent-posts',{descending:true,limit:8})
-    });
-}

File shows/post.js

 function(doc, req) {  
-  // !json lib.templates.post
+  // !json templates
   // !json blog
-  // !code lib/helpers/ejs/*
-  // !code lib/helpers/template.js
-  // !code vendor/couchapp/date.js
-  // !code vendor/couchapp/path.js
+  // !code vendor/inditeweb/ejs/*.js
+  // !code vendor/inditeweb/template.js
+  // !code vendor/inditeweb/date.js
+  // !code vendor/inditeweb/path.js
+ 
+  var is_edit = (!doc || req.query.edit); 
+  var path_level = "../";
+  if (doc)
+      path_level += "../";
 
+  
+  // so want to create/edit a post but isn't logged
+  // we redirect him to login page
+  if (is_edit && !req.userCtx.name) {
+    redirect_url = path_level + "login.html?next=/" + currentPath();
+    return {
+      code: 302,
+      headers: {
+        "Location": redirect_url
+      }
+    }
+  }
+
+  // if we edit/ create a doc display edit page  
+  if (is_edit)
+    return template(templates.edit, {
+        doc : doc,
+        docid : toJSON((doc && doc._id) || null), 
+        assets : assetPath(),
+        path_level: path_level,
+        index : listPath('index','recent-posts',{descending:true,limit:8})
+    });
+ 
+  // else show the post
   var fcreated_at = new Date().setRFC3339(doc.created_at).toLocaleString();
 
   var labels = [];
       }
   }
 
-  var editPath = showPath("edit", doc._id);
-  // we only show html
-  return template(lib.templates.post, {
+  var editPath = showPath("show", doc._id, {edit:true});
+  return template(templates.post, {
     doc: doc,
     fcreated_at: fcreated_at,
     assets : assetPath(),
-    editPostPath : showPath('edit', doc._id),
+    editPostPath : editPath,  
     labels: labels.join(', '),
     index : listPath('index','recent-posts',{descending:true, limit:8}),
     editPath: editPath

File templates/edit.html

+<!DOCTYPE html>
+<html lang="fr">
+<head>
+    <meta charset="utf-8"/>
+    <title>benoît chesneau web - edit</title>
+
+    <!--[if IE]>
+
+    <script>
+        // allow IE to recognize HTMl5 elements
+        document.createElement('section');
+        document.createElement('article');
+        document.createElement('aside');
+        document.createElement('footer');
+        document.createElement('header');
+        document.createElement('nav');
+        document.createElement('time');
+
+    </script>
+    <![endif]-->
+    <link rel="openid.server" href="http://www.myopenid.com/server">
+    <link rel="openid.delegate" href="http://bchesneau.myopenid.com/">
+    <link rel="home index" href="http://benoitc.org/" type="text/html">
+    <link rel="me author" href="http://benoitc.org/static/benoitc.html" type="text/html">
+
+    <link rel="stylesheet" href="<%= path_level %>css/benoitc.css" type="text/css" media="screen, projection" />
+    
+
+
+</head>
+
+
+<body>
+        <header>
+        <h1>
+            <a rel="me author" href="../../benoitc.html">Benoît Chesneau</a>
+        </h1>
+        </header>
+        <div id="edit">
+            <h2>Nouvel article</h2>
+            <form id="fedit" name="fedit" action="new.html"
+                method="post">
+                        
+                <textarea name="body" id="body" cols="80"
+                    rows="20"></textarea>
+                
+                <ol>
+                    <li><label for="title">Titre<label><input type="text"
+                            name="title" id="title" value=""></li>
+
+                    <li><label for="labels">Libellés</label><input type="text"
+                name="labels" id="labels" value=""></li>
+                </ol>
+                
+                <p><input type="submit" name="save" id="save" value="Save">
+                or <a href="<%= index %>">Cancel</a> <span id="saved" style="display:none;">Saved</span></p>
+            </form>
+            <div id="mdpreview"></div>
+        </div>
+
+        <footer id="main-footer">
+        <p>2009 (c) <a href="<%= path_level %>benoitc.html">Benoît Chesneau</a> - <a rel="license" href="http://creativecommons.org/licenses/by/2.0/fr/">Certains droits reservés</a>.</p>
+        </footer> 
+
+    
+</body>
+
+    <script src="/_utils/script/json2.js"></script>
+    <script src="/_utils/script/jquery.js"></script>
+    <script src="/_utils/script/jquery.cookies.js"></script>
+    <script src="/_utils/script/jquery.couch.js"></script>
+    <script src="<%= path_level %>js/showdown.js"></script>
+    <script src="<%= path_level %>js/textarea.jquery.js"></script>
+    <script src="<%= path_level %>vendor/inditeweb/jquery.couchapp.js"></script>
+    <script src="<%= path_level %>js/editor.js"></script>
+    <script src="<%= path_level %>js/strftime.js"></script>
+    <script src="<%= path_level %>js/blog.js"></script>
+    <script src="<%= path_level %>js/urlify.js"></script>
+
+    <script>
+        $(document).ready(function() {
+
+            $.CouchApp(function(app) {
+
+                    var session = app.get_session();
+                    
+                    var B = new Blog(app);
+
+                    var postForm = app.docForm("form#fedit", {
+                        id : <%= docid %>,
+                        fields : ["title", "body", "labels"],
+                        template : {
+                            doc_type : "post",
+                            format : "markdown",
+                            author : session.name
+                        },
+                        onLoad : function(doc) {
+                            if (doc._id) {
+                                $("#edit h2").html('Édition de ' + B.link_for(doc._id));
+                            } 
+                        },
+                        beforeSave : function(doc) {
+                            if (doc.body)
+                                doc.html = B.formatBody(doc.body);
+
+                            if (!doc.created_at) {
+                                doc.created_at = new Date().rfc3339();
+                            }
+
+                            if (!doc.slug && doc.title) {
+                                doc.slug = doc.created_at.slice(0, 10).replace(/\-*/g, '') 
+                                + "_" + URLify(doc.title, 255);
+                                doc._id = doc.slug;
+                            }
+
+                            doc.updated = new Date().rfc3339();
+                            if(doc.labels) {
+                                doc.labels = doc.labels.split(",");
+                                for(var idx in doc.labels) {
+                                    doc.labels[idx] = $.trim(doc.labels[idx]);
+                                }
+                            } 
+                        },
+                        success : function(resp) {
+                           $("#saved").text("Enregistré _rev: "+resp.rev).fadeIn(500).fadeOut(3000);
+                           $("#edit h2").html('Édition de ' + B.link_for(resp.id));
+                        }
+                    });  
+
+                    new Editor(); 
+                    
+            });
+        
+        });
+    </script>
+</html>