Commits

Anonymous committed a23fb18

lot of fixes for bugs that appeared online...

Comments (0)

Files changed (16)

 
     def save(self, session):
         """ save session in couchdb database """
-        s = None
         expire = datetime.now() + timedelta(seconds=settings.SESSION_COOKIE_AGE)
         try:
-            s = local.db["session/%s" % session.sid]
-        except ResourceNotFound:
-            pass
-        
-        if s is not None:
-            s['session_data'] = _encode_session_data(dict(session))
-            s['expire_date'] = datetime_tojson(expire)
-        else:
-            s = {
+            local.db["session/%s" % session.sid] = {
                     'session_key':session.sid, 
                     'session_data': _encode_session_data(dict(session)),
                     'expire_date': datetime_tojson(expire)            
-                    }
-        local.db['session/%s' % session.sid] = s
-
+            }
+        except:
+            s = local.db["session/%s" % session.sid]
+            s['session_data'] = _encode_session_data(dict(session))
+            s['expire_date'] = datetime_tojson(expire)
+            local.db['session/%s' % session.sid] = s
+       
     def delete(self, session):
         """ delete session """
         try:

couchit/models.py

         else:
             old_data = db.get(self.id)
             self.created = datetime.utcnow()
-            old_hash = make_hash(old_data['content'])
-            new_hash = make_hash(self.content)
+            old_hash = make_hash(old_data['title'], old_data['content'])
+            new_hash = make_hash(self.title, self.content)
             if old_hash != new_hash:
                 del old_data['_id']
                 del old_data['_rev']

couchit/settings.py

 
 SERVER_NAME = 'couchit.net'
 if DEBUG:
-    SERVER_NAME = 'couch.test'
+    SERVER_NAME = 'couch.test:5000'
 
 
 # database

couchit/template.py

     if local.site_url:
         base_url = local.site_url + '/'
     else:
-        base_url = '/'
+        base_url = ''
     md = markdown.Markdown(
             extensions = ['codehilite', 'wikilink', 'footnotes'],
             extension_configs = {'wikilink': [
                                         ('base_url', base_url),
-                                        ('html_class', '') ]},
+                                        ('html_class', ''),
+                                        ('end_url', '') ]},
             safe_mode = 'escape')
     
     return md.convert(value)
 from time import asctime, gmtime, time
 import urllib2
 import uuid
-from jinja2.filters import do_truncate, do_striptags
+from jinja2.filters import do_truncate, do_striptags, escape
 from werkzeug import redirect
 from werkzeug.contrib.atom import AtomFeed
 from werkzeug.routing import NotFound
     request.session['createid'] = createid
     request.session['spamid'] = spamid
     request.session['spaminput'] = spaminput
-    print "1 %s" % createid
+
     return render_response('home.html', cname=cname, alias=alias,
                 b1=b1, b2=b2, spamid=spamid, spaminput=spaminput, createid=createid)
   
         redirect_url = url_for('show_page', pagename=pagename)
         return redirect(redirect_url)
     
-    return render_response('page/edit.html', page=page)
+    return redirect(url_for('show_page'))
 
 @can_edit  
 def delete_page(request, pagename):
     # get all pages
     pages = all_pages(local.db, request.site.id)
     
-
     return render_response('page/show.html', page=revision, pages=pages)
- 
    
 def diff_page(request=None, pagename=None):
     if pagename is None:
             return send_json({'ok': False, 'reason': 'not found'})
         return NotFound
     
+    diff = ''
+    rev1 = rev2 = page
     revisions = request.values.getlist('r')
-    diff, rev1, rev2 = get_diff(local.db, page, revisions[0], revisions[1])
+    if revisions:
+        diff, rev1, rev2 = get_diff(local.db, page, revisions[0], revisions[1])
     
     if request.is_xhr:
          return send_json({
                     title="%s: Latest revisions of %s" % (request.site.cname, page.title),
                     subtitle=request.site.subtitle,
                     updated = page.updated,
-                    id = page.title.replace(" ", "_")
+                    feed_url = request.url
         )
         for rev in all_revisions:
+            title = ''
+            _url="%s%s" % (request.host_url, url_for("revision_page", 
+                cname=request.site.cname, pagename=pagename, 
+                nb_revision=rev.nb_revision
+            ))
             for change in rev.changes:
                 if change['type'] != "unmod":
                     title = "\n".join(change['changed']['lines'])
                     title = do_truncate(do_striptags(title), 60)
             title = title and title or "Edited."
-            feed.add(title, rev.content, 
+            feed.add(title, escape(rev.content), 
                 updated=rev.updated,
-                url=url_for("revision_page", 
-                    cname=request.site.cname, pagename=pagename, 
-                    nb_revision=rev.nb_revision
-                ),
-                id=str(rev.nb_revision)
+                url=_url,
+                id=_url,
+                author=rev.title.replace(' ', '_')
             )
         return feed.get_response()
     else:
             'title': "%s: Latest revisions of %s" % (request.site.cname, page.title),
             'subtitle': request.site.subtitle,
             'updated':datetime_tojson(page.updated),
+            'feed_url': request.url,
             'revisions': []
         }
         for rev in all_revisions:
                     title = do_truncate(do_striptags(title), 60)
                     
             title = title and title or "Edited."
-            url = url_for("revision_page", 
+            url = "%s%s" % (request.host_url, url_for("revision_page", 
                         cname=request.site.cname, pagename=pagename, 
                         nb_revision=rev.nb_revision
-            )
+            ))
             json['revisions'].append({
                 'title': title,
                 'content': rev.content,
     changes = get_changes(local.db, request.site.id)
 
     if feedtype == "atom":
+        
         feed = AtomFeed(
                     title="%s: Latest changes" % request.site.title and request.site.title or request.site.cname,
                     subtitle=request.site.subtitle,
                     updated = changes[0].updated,
-                    id = request.site.cname
+                    feed_url = request.url
         )
         for rev in changes:
-            feed.add(rev.title, rev.content, 
+            _url = "%s%s" % (request.host_url, url_for("show_page", pagename=rev.title.replace(' ', '_')))
+            feed.add(rev.title, escape(rev.content), 
                 updated=rev.updated,
-                url=url_for("show_page",pagename=rev.title.replace(' ', '_')
-                ),
-                id=rev.title.replace(' ', '_')
+                url=_url,
+                id=_url,
+                author=rev.title.replace(' ', '_')
             )
         return feed.get_response()
     elif feedtype == 'json':
                 'title': "%s: Latest changes" % request.site.title and request.site.title or request.site.cname,
                 'subtitle': request.site.subtitle,
                 'updated':datetime_tojson(changes[0].updated),
+                'feed_url': request.url,
                 'pages': []
             }
         for rev in changes:
-            url = url_for("show_page", pagename=rev.title.replace(' ', '_')
-            )
+            url = "%s%s" % (request.host_url, url_for("show_page", pagename=rev.title.replace(' ', '_')))
             json['pages'].append({
                 'title': rev.title,
                 'content': rev.content,
             title="%s: Latest changes" % request.site.title and request.site.title or request.site.cname,
             subtitle=request.site.subtitle,
             updated = pages[0].updated,
-            id = request.site.cname
+            feed_url = request.url
         )
         for page in pages:
-            feed.add(page.title, page.content,
+            _url = "%s%s" % (request.host_url, url_for("show_page", pagename=page.title.replace(' ', '_')))
+            feed.add(page.title, escape(page.content),
             updated=page.updated, 
-            url=url_for("show_page", pagename=page.title.replace(' ', '_')),
-            id=page.title.replace(' ', '_')
+            url=_url,
+            id=_url,
+            author=page.title.replace(' ', '_')
         )
         return feed.get_response()
     json = {
 @not_logged    
 def site_login(request):
     error = None
+    notify = None
     back = ''
     if request.method == "GET":
         back=request.values.get('back', '')
         
     return render_response('site/change_password_authenticated.html', error=error)
 
-@not_logged    
 def site_forgot_password(request):
     back=request.values.get('back', '')
     if request.method == 'POST':
-        back = request.form['back']
+        back = request.form.get('back', '')
         
         # create token
         otoken = PasswordToken(site=request.site.id)

static/css/screen.css

 header h1,header h2 {padding:0px;}
 header h1 {padding-top:5px;}
 header h2 {padding-bottom:10px;}
+header h1 a {text-decoration:none;}
 #page article,#pedit #pedit_wrapper {display:block;padding:10px;border-right:4px solid;border-left:4px solid;border-bottom:4px solid;-moz-border-radius-bottomleft:5px;-moz-border-radius-bottomright:5px;-khtml-border-bottom-left-radius:5px;-webkit-border-bottom-left-radius:5px;-khtml-border-bottom-right-radius:5px;-webkit-border-bottom-right-radius:5px;border-bottom-left-radius:5px;border-bottom-right-radius:5px;min-height:350px;}
 #phistory, #pdiff,#pdesign,#psettings,#pgeneric {display:block;padding:10px;border:4px solid;-moz-border-radius:5px;-khtml-border-radius:5px;-webkit-radius:5px;border-radius:5px;min-height:350px;}
-#pgeneric {text-align:left;}
+#pgeneric {text-align:left;margin-top:10px;}
 #pdiff h4 {border-bottom:1px solid;}
 ul.subsection_tabs {list-style:none;height:23px;-moz-border-radius-topleft:5px;-moz-border-radius-topright:5px;-khtml-border-top-left-radius:5px;-webkit-border-top-left-radius:5px;-khtml-border-top-right-radius:5px;-webkit-border-top-right-radius:5px;border-top-left-radius:5px;border-top-right-radius:5px;margin:0;padding:0;}
 ul.subsection_tabs li.tab {float:left;margin:0;}
 #fedit textarea {position:relative;width:99%;height:100%;}
 #pedit_wrapper #preview {display:block;position:relative;width:48%;float:right;height:100%;}
 #page-content {display:block;background:#fff repeat;height:100%;}
-.footer_wrapper {display:block;position:relative;clear:both;width:100%;padding-top:25px;}
+.footer_wrapper {display:block;position:relative;clear:both;width:100%;padding-top:25px;padding-bottom:10px;}
 footer ul.menu {list-style:none;text-align:center;padding-bottom:15px;}
 footer ul.menu li {display:inline;padding:0 5px 0 5px;}
 p.powered {text-align:center;}

static/css/src/layout.css

     padding-bottom: 10px;
 }
 
+
+header h1 a { text-decoration: none; }
+
 #page article,
 #pedit #pedit_wrapper {
     display: block;
 
 #pgeneric {
     text-align: left;
+    margin-top: 10px;
 }
 
 
     clear: both;
     width: 100%;
     padding-top: 25px;
+    padding-bottom: 10px;
 }
 
 footer ul.menu {

static/css/src/slate.css

     color: #14456e;
 }
 
+header h1 a {
+    color: #000;
+}
+
 #page article {
     color: #000;
     background-color: #fff;

static/css/theme.css

 body {background-color:#e7e7e7;color:#000;}
 a {color:#14456e;}
+header h1 a {color:#000;}
 #page article {color:#000;background-color:#fff;border-right-color:#d4d4d4;border-left-color:#d4d4d4;border-bottom-color:#d4d4d4;}
 #phistory,#pdiff,#pdesign,#claim_wrapper,#psettings,#pgeneric {background-color:#fff;border-color:#d4d4d4;color:#000;}
 #pdiff h4 {border-bottom-color:#ccc;}

static/js/couchit-application.js

-if(!document.createElementNS){document.createElement("section");document.createElement("audio");document.createElement("video");document.createElement("article");document.createElement("aside");document.createElement("footer");document.createElement("header");document.createElement("nav");document.createElement("time")}Date.parseRFC3339=function(C){var B=new Date(0);var A=C.match(/(\d{4})-(\d\d)-(\d\d)\s*(?:[\sT]\s*(\d\d):(\d\d)(?::(\d\d))?(\.\d*)?\s*(Z|([-+])(\d\d):(\d\d))?)?/);if(!A){return }if(A[2]){A[2]--}if(A[7]){A[7]=(A[7]+"000").substring(1,4)}var E=[null,"FullYear","Month","Date","Hours","Minutes","Seconds","Milliseconds"];for(var D=1;D<=7;D++){if(A[D]){B["setUTC"+E[D]](A[D])}}if(A[9]){B.setTime(B.getTime()+(A[9]=="-"?1:-1)*(A[10]*3600000+A[11]*60000))}return B.getTime()};function localizeDates(){var B="";var A=new Date();$$("time").each(function(E,D){if(E.getAttribute("title")=="GMT"){var C=new Date(Date.parseRFC3339(E.getAttribute("datetime")));if(!C.getTime()){return }diff=((A.getTime()-C.getTime())/1000),day_diff=Math.floor(diff/86400);if(isNaN(day_diff)||day_diff<0||day_diff>=31){return }var G=C.toLocaleString();var F=C.toLocaleString();if(day_diff==0){G=(diff<60&&"Just Now"||diff<120&&"1 minute ago"||diff<3600&&Math.floor(diff/60)+" minutes ago"||diff<7200&&"1 hour ago"||diff<86400&&Math.floor(diff/3600)+" hours ago");F=C.toLocaleTimeString()}else{G=(day_diff=1&&"Yesterday"||day_diff<7&&day_diff+" days ago");F=C.toLocaleString()}E.setAttribute("title",F);E.textContent="posted "+G}})}var Page={};var Site={url:"",name:""};var FORBIDDEN_PAGES=["site","delete","edit","create","history","changes"];var Create=Class.create({initialize:function(){var A=this;this.Form=$("fnewpage");this.doCreate=$("doCreate");this.Form.addClassName("hidden");Event.observe(this.doCreate,"click",function(B){Event.stop(B);A.show();return false},false);Event.observe($$("a.cancelCreate")[0],"click",function(B){Event.stop(B);A.cancel();return false},false);$("screate").observe("click",function(B){Event.stop(B);A.submit();return false},false)},show:function(){this.doCreate.addClassName("hidden");this.Form.removeClassName("hidden")},cancel:function(){this.Form.addClassName("hidden");this.doCreate.removeClassName("hidden")},submit:function(){var B=$("title");if(!B.value.match(/^[ \w\u00A1-\uFFFF]+$/i)||FORBIDDEN_PAGES.indexOf(B.value)>=0){alert("Page title invalid");return false}var A=B.value.replace(/ /g,"_");document.location.href=Site.url+"/"+A+"#pedit"},});var Compare=Class.create({nb_selected:0,selected:false,initialize:function(){var A=this;this.Form=$("fhistory");$$("input.c").each(function(B){B.observe("click",function(C){A.check(this)},false)})},check:function(A){row=A.parentNode.parentNode;row.toggleClassName("rselected");if(!A.checked){this.nb_selected-=1;A.removeClassName("selected")}else{this.nb_selected+=1;A.addClassName("selected")}if(this.nb_selected==2){$$("input.c").each(function(B){if(!B.hasClassName("selected")){B.disabled="disabled"}});this.selected=true}else{if(this.selected){$$("input.c").each(function(B){if(!B.hasClassName("selected")){B.disabled=null}});this.selected=false}}}});var Diff=Class.create({initialize:function(){var A=this;this.rev_from=$("rev_from");this.rev_to=$("rev_to");$("scompare").observe("click",function(B){Event.stop(B);A.get_diff();return false})},get_diff:function(){var B=this.rev_from.getValue();var A=this.rev_to.getValue();if(B==A){alert("Why would you want compare same version ...");return }url=$("fdiff").action+"?r="+B+"&r="+A;new Ajax.Request(url,{method:"get",contentType:"application/json",requestHeaders:{Accept:"application/json"},onSuccess:function(C){data=C.responseText.evalJSON(true);if(data.ok){Element.remove($("tableDiff"));$("pdiff").insert(data.diff)}}})}});var Settings=Class.create({initialize:function(){var A=this;this.observer=null;this.title=$("site_header").getElementsBySelector("h1")[0];this.subtitle=$("site_header").getElementsBySelector("h2")[0];$$("input").each(function(B){new Form.Element.Observer(B,0.2,function(C,D){if(C.id=="site_title"){A.title.update(D)}if(C.id=="site_subtitle"){A.subtitle.update(D)}if(A.observer){clearTimeout(A.observer)}A.observer=setTimeout(A.save.bind(A),400)})})},save:function(){var A={};try{A={title:$("site_title").getValue(),subtitle:$("site_subtitle").getValue(),email:$("email").getValue(),privacy:$$('input:checked[type="radio"][name="privacy"]').pluck("value")[0]}}catch(B){A={title:$("site_title").getValue(),subtitle:$("site_subtitle").getValue()}}url=$("fsettings").action;new Ajax.Request(url,{method:"post",postBody:Object.toJSON(A),contentType:"application/json",requestHeaders:{Accept:"application/json"},onSuccess:function(C){A=C.responseText.evalJSON(true)}})}});var SiteAddress=Class.create({initialize:function(){var A=this;if(!$("error").innerHTML){$("error").hide()}new Form.Element.Observer("alias",0.2,function(B,C){if(C.length>3&&!C.match(/^(\w+)$/)){$("error").update("<strong>Error:</strong> "+$("alias").value+" is invalid, only use letters and numbers.");$("error").show()}else{$("error").hide()}});$("faddress").observe("submit",function(D){Event.stop(D);var B=null;var C=$("alias").getValue();if(C.length<=3){B="length < 3"}else{if(!C.match(/^(\w+)$/)){B=C+" is invalid, only use letters and numbers."}}if(B){$("error").update("<strong>Error:</strong> "+B);$("error").show();return false}else{A.valid_name()}},false)},valid_name:function(){url=$("faddress").action;new Ajax.Request(url,{method:"get",contentType:"application/json",parameters:{alias:$("alias").getValue()},requestHeaders:{Accept:"application/json"},onSuccess:function(A){data=A.responseText.evalJSON(true);if(data.ok){$("faddress").submit()}else{$("error").update("<strong>Error:</strong> "+data.error);$("error").show()}}})}});var Claim=Class.create({initialize:function(){var A=this;this.email=$("email");this.password=$("password");$("fclaim").observe("submit",function(B){Event.stop(B);if(A.validate()){this.submit()}},false)},validate:function(){$$(".help_error").each(function(B){B.remove()});$$(".errors").each(function(B){B.removeClassName("errors")});nb_errors=0;if(!this.email.value.match(/(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*")@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$/i)){var A=new Element("div",{"class":"help_error"}).update("Invalid email address.");this.email.parentNode.insert(A);$("row_email").addClassName("errors");nb_errors+=1}if(this.password.value.length<=0){var A=new Element("div",{"class":"help_error"}).update("You should set a password.");this.password.parentNode.insert(A);$("row_password").addClassName("errors");nb_errors+=1}if(nb_errors>0){return false}return true}});document.observe("dom:loaded",function(){localizeDates()});
+if(!document.createElementNS){document.createElement("section");document.createElement("audio");document.createElement("video");document.createElement("article");document.createElement("aside");document.createElement("footer");document.createElement("header");document.createElement("nav");document.createElement("time")}Date.parseRFC3339=function(C){var B=new Date(0);var A=C.match(/(\d{4})-(\d\d)-(\d\d)\s*(?:[\sT]\s*(\d\d):(\d\d)(?::(\d\d))?(\.\d*)?\s*(Z|([-+])(\d\d):(\d\d))?)?/);if(!A){return }if(A[2]){A[2]--}if(A[7]){A[7]=(A[7]+"000").substring(1,4)}var E=[null,"FullYear","Month","Date","Hours","Minutes","Seconds","Milliseconds"];for(var D=1;D<=7;D++){if(A[D]){B["setUTC"+E[D]](A[D])}}if(A[9]){B.setTime(B.getTime()+(A[9]=="-"?1:-1)*(A[10]*3600000+A[11]*60000))}return B.getTime()};function localizeDates(){var B="";var A=new Date();$$("time").each(function(E,D){if(E.getAttribute("title")=="GMT"){var C=new Date(Date.parseRFC3339(E.getAttribute("datetime")));if(!C.getTime()){return }diff=((A.getTime()-C.getTime())/1000),day_diff=Math.floor(diff/86400);if(isNaN(day_diff)||day_diff<0||day_diff>=31){return }var G=C.toLocaleString();var F=C.toLocaleString();if(day_diff==0){G=(diff<60&&"Just Now"||diff<120&&"1 minute ago"||diff<3600&&Math.floor(diff/60)+" minutes ago"||diff<7200&&"1 hour ago"||diff<86400&&Math.floor(diff/3600)+" hours ago");F=C.toLocaleTimeString()}else{G=(day_diff=1&&"Yesterday"||day_diff<7&&day_diff+" days ago");F=C.toLocaleString()}E.setAttribute("title",F);E.textContent="posted "+G}})}var Page={};var Site={url:"",name:""};var FORBIDDEN_PAGES=["site","delete","edit","create","history","changes"];var Create=Class.create({initialize:function(){var A=this;this.Form=$("fnewpage");this.doCreate=$("doCreate");this.Form.addClassName("hidden");Event.observe(this.doCreate,"click",function(B){Event.stop(B);A.show();return false},false);Event.observe($$("a.cancelCreate")[0],"click",function(B){Event.stop(B);A.cancel();return false},false);$("screate").observe("click",function(B){Event.stop(B);A.submit();return false},false)},show:function(){this.doCreate.addClassName("hidden");this.Form.removeClassName("hidden")},cancel:function(){this.Form.addClassName("hidden");this.doCreate.removeClassName("hidden")},submit:function(){var B=$("title");if(!B.value.match(/^[ \w\u00A1-\uFFFF]+$/i)||FORBIDDEN_PAGES.indexOf(B.value)>=0){alert("Page title invalid");return false}var A=B.value.replace(/ /g,"_");document.location.href=Site.url+"/"+A+"#pedit"},});var Compare=Class.create({nb_selected:0,selected:false,initialize:function(){var A=this;this.Form=$("fhistory");$$("input.c").each(function(B){B.observe("click",function(C){A.check(this)},false)})},check:function(A){row=A.parentNode.parentNode;row.toggleClassName("rselected");if(!A.checked){this.nb_selected-=1;A.removeClassName("selected")}else{this.nb_selected+=1;A.addClassName("selected")}if(this.nb_selected==2){$$("input.c").each(function(B){if(!B.hasClassName("selected")){B.disabled="disabled"}});this.selected=true}else{if(this.selected){$$("input.c").each(function(B){if(!B.hasClassName("selected")){B.disabled=null}});this.selected=false}}}});var Diff=Class.create({initialize:function(){var A=this;this.rev_from=$("rev_from");this.rev_to=$("rev_to");$("scompare").observe("click",function(B){Event.stop(B);A.get_diff();return false})},get_diff:function(){var B=this.rev_from.getValue();var A=this.rev_to.getValue();if(B==A){alert("Why would you want compare same version ...");return }url=$("fdiff").action+"?r="+B+"&r="+A;new Ajax.Request(url,{method:"get",contentType:"application/json",requestHeaders:{Accept:"application/json"},onSuccess:function(C){data=C.responseText.evalJSON(true);if(data.ok){Element.remove($("tableDiff"));$("pdiff").insert(data.diff)}}})}});var Settings=Class.create({initialize:function(){var A=this;this.observer=null;this.title=$("site_header").select("h1 a")[0];this.subtitle=$("site_header").select("h2")[0];$$("input").each(function(B){new Form.Element.Observer(B,0.2,function(C,D){if(C.id=="site_title"){A.title.update(D);document.title=D+" - settings"}if(C.id=="site_subtitle"){A.subtitle.update(D)}if(A.observer){clearTimeout(A.observer)}A.observer=setTimeout(A.save.bind(A),400)})})},save:function(){var A={};try{A={title:$("site_title").getValue(),subtitle:$("site_subtitle").getValue(),email:$("email").getValue(),privacy:$$('input:checked[type="radio"][name="privacy"]').pluck("value")[0]}}catch(B){A={title:$("site_title").getValue(),subtitle:$("site_subtitle").getValue()}}url=$("fsettings").action;new Ajax.Request(url,{method:"post",postBody:Object.toJSON(A),contentType:"application/json",requestHeaders:{Accept:"application/json"},onSuccess:function(C){A=C.responseText.evalJSON(true)}})}});var SiteAddress=Class.create({initialize:function(){var A=this;if(!$("error").innerHTML){$("error").hide()}new Form.Element.Observer("alias",0.2,function(B,C){if(C.length>3&&!C.match(/^(\w+)$/)){$("error").update("<strong>Error:</strong> "+$("alias").value+" is invalid, only use letters and numbers.");$("error").show()}else{$("error").hide()}});$("faddress").observe("submit",function(D){Event.stop(D);var B=null;var C=$("alias").getValue();if(C.length<=3){B="length < 3"}else{if(!C.match(/^(\w+)$/)){B=C+" is invalid, only use letters and numbers."}}if(B){$("error").update("<strong>Error:</strong> "+B);$("error").show();return false}else{A.valid_name()}},false)},valid_name:function(){url=$("faddress").action;new Ajax.Request(url,{method:"get",contentType:"application/json",parameters:{alias:$("alias").getValue()},requestHeaders:{Accept:"application/json"},onSuccess:function(A){data=A.responseText.evalJSON(true);if(data.ok){$("faddress").submit()}else{$("error").update("<strong>Error:</strong> "+data.error);$("error").show()}}})}});var Claim=Class.create({initialize:function(){var A=this;this.email=$("email");this.password=$("password");$("fclaim").observe("submit",function(B){Event.stop(B);if(A.validate()){this.submit()}},false)},validate:function(){$$(".help_error").each(function(B){B.remove()});$$(".errors").each(function(B){B.removeClassName("errors")});nb_errors=0;if(!this.email.value.match(/(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*")@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$/i)){var A=new Element("div",{"class":"help_error"}).update("Invalid email address.");this.email.parentNode.insert(A);$("row_email").addClassName("errors");nb_errors+=1}if(this.password.value.length<=0){var A=new Element("div",{"class":"help_error"}).update("You should set a password.");this.password.parentNode.insert(A);$("row_password").addClassName("errors");nb_errors+=1}if(nb_errors>0){return false}return true}});document.observe("dom:loaded",function(){localizeDates()});

static/js/src/application.js

    initialize: function() {
        var self = this;
        this.observer = null;
-       this.title = $('site_header').getElementsBySelector("h1")[0];
-       this.subtitle = $('site_header').getElementsBySelector("h2")[0];
-       
+       this.title = $('site_header').select("h1 a")[0];
+       this.subtitle = $('site_header').select("h2")[0];
        $$('input').each(function(el) {
           new Form.Element.Observer(
               el,
               0.2, 
               function(el, value) {
-                  if (el.id == "site_title") 
-                    self.title.update(value); 
+                  if (el.id == "site_title") {
+                      self.title.update(value);
+                      document.title = value + " - settings";
+                  }
+                    
                   if (el.id == "site_subtitle")
                     self.subtitle.update(value);
                     

static/js/src/page.js

                 }
                 document.location.href=this.href;
             }, false);
-        
     },
     
     init: function() {
         /* init size of textarea */
         var new_height = document.viewport.getHeight() - 250;
         $('content').setStyle({'height': new_height + 'px'});
+        
     },
     
     update_tabs: function(new_container) {

templates/about.html

 <header><h1></h1></header>
 <div id="home_wrapper"> 
 <section id="pgeneric">
-    <h1>About Couchit</h1>
+    <h1>About</h1>
     <p>Couchit allow you <strong>to easily build and maintain your website.</strong></p> 
-    <p>Post your content and let's go.</p>
-    <p>Couchit is for now in beta, but already propose you:</p>
+    <p>Add your content and get started right away.</p>
+    <p>Couchit is still a beta release, but you already have:</p>
         <ul>
             <li>a simple and intuitive user interface</li>
-            <li>the possibility to create and edit page</li>
-            <li>the possibility to choose your site url</li>
-            <li>an easyway to choose your website colorscheme</li>
-            <li>an easy integration of paste from <a href="http://www.friendpaste.com">Friendpaste</a></li>
+            <li>the possibility to create and edit pages</li>
+            <li>the possibility to choose your site URI</li>
+            <li>an easy way to choose your website color scheme</li>
+            <li>a nice integration with <a href="http://www.friendpaste.com">Friendpaste</a></li>
             <li>...</li>
         </ul>
-    <p>An the best is coming...</p>
+    <p>And the best is yet to come...</p>
     
-    <h2>How is build couchit ?</h2>
+    <h2>How?</h2>
     <ul>
-        <li>No SQL database. We use the new and powerfull document oriented database <a href="http://www.couchdb.org">Apache CouchDB</a>.</li>
+        <li>No SQL at all. We use the new and powerfull document oriented database, <a href="http://www.couchdb.org">Apache CouchDB</a>.</li>
         <li><a href="http://werkzeug.pocoo.org">Werkzeug</a>, a micro web framework</li>
     </ul>
     
-    <h2>Who ?</h2>
-    <p><a href="http://couchit.net">Couchit</a> has been produced by <a href="http://e-engura.com">Enki Multimedia</a>.</p>
+    <h2>Who?</h2>
+    <p><a href="http://couchit.net">Couchit</a> is produced by <a href="http://e-engura.com">Enki Multimedia</a>.</p>
     
-    <h2>Privacy</h2>
-    <p><strong>There is no logging on Couchit.</strong> Cookie is only used to store your preferences. Period.</p>
-    <p>So use it freely and don't hesitate to share it with your friends ;)</p>
+    <h2>Privacy?</h2>
+    <p><strong>We do not track your usage of this site</strong>, cookies are used to store your 
+        preferences only.</p>
+    <p>Use it freely and share with your friends.</p>
     
 </section>
 </div> 

templates/base.html

 
 <head>
     <meta charset="utf-8" />
-    <title>{% block title %}{% endblock %}</title>
+    <title>{% if site and site.title %}{{ site.title }} - {% endif %}{% block title %}{% endblock %}</title>
+    <link rel="icon" type="image/png" href="/static/img/favicon.png" />
+    
     {% if DEBUG %}
     <link rel="stylesheet" href="/static/css/src/debug.css" type="text/css" />
     <link rel="stylesheet" type="text/css" href="/static/css/src/textarea.css" />
     <script src="/static/js/lib/prototype.js" type="text/javascript"></script>
     <script src="/static/js/lib/effects.js" type="text/javascript"></script>
+    <script src="/static/js/lib/controls.js" type="text/javascript"></script>
     <script src="/static/js/lib/dragdrop.js" type="text/javascript"></script>
     <script src="/static/js/lib/builder.js" type="text/javascript"></script>
     <script src="/static/js/lib/slider.js" type="text/javascript"></script>
     <style type="text/css" media="screen">
 body{background-color:#{{ site.theme.background_color }};color:#{{ site.theme.text_color }};}
 a{color:#{{ site.theme.link_color }};}
+header h1 a{color:#{{ site.theme.text_color }};}
 #page article, #pedit #pedit_wrapper{background-color:#{{ site.theme.page_fill_color }};border-right-color:#{{ site.theme.border_color }};border-left-color:#{{ site.theme.border_color }};border-bottom-color:#{{ site.theme.border_color }};color:#{{ site.theme.page_text_color }};}
 #phistory,#pdiff,#pdesign,#pedit,#claim_wrapper,#psettings{background-color:#{{ site.theme.page_fill_color }};border-color:#{{ site.theme.border_color }};color:#{{ site.theme.page_text_color }};}
 #phistory,#pdiff,#pdesign,#page,#claim_wrapper,#psettings{color:#{{ site.theme.page_text_color }};}
-#phistory a, #pdiff a, #pdesign a, #page a, #psettings a{color:#{{ site.theme.page_link_color }};}
+#phistory a, #pdiff a, #pdesign a, #page a, #psettings a, #claim_wrapper a{color:#{{ site.theme.page_link_color }};}
 ul.subsection_tabs{background-color:#{{ site.theme.border_color }};}
 ul.subsection_tabs li.tab a, ul.subsection_tabs li.tab a:visited{color:#{{ site.theme.menu_inactive_color }};}
 .box{background-color:#{{ site.theme.page_fill_color }};}
     <div id="container">
         {% if site %}
          <header id="site_header">
-             <h1>{% if site.title %}{{ site.title }}{% endif %}</h1>
+             <h1><a href="{% if site_url %}{{ site_url }}{% else %}/{% endif %}">{% if site.title %}{{ site.title }}{% endif %}</a></h1>
              <h2>{% if site.subtitle %}{{ site.subtitle }}{% endif %}</h2>
          </header>   
         {% endif %}

templates/page/show.html

     {% if page.id %}
         
     
-    <article>
+    <article id="post">
         {% if page.title or page.subtitle %}
         <header>
             <h2>{{ page.title }}</h2>
     {% if can_edit %}
     {% if not page.id %}
     Page.created = true;
+    {% else %}
+    {% if page.title == 'Home' %}
+    Page.home = true;
+    {% else %}
+     Page.home = false;
+    {% endif %}
     {% endif %}
     new Create();
     new PageUI();

templates/site/login.html

         {% if notify %}
         <p class="notify">{{ notify }}</p>
         {% endif %}
-        <p><input type="password" name="password" id="password" value="password" /> (<a href="{{ site_url }}/site/forgot-password?back={{ back }}">I forgot the password)</a></p>
+        <p><input type="password" name="password" id="password" value="password" /> <a href="{{ site_url }}/site/forgot-password?back={{ back }}">(I forgot the password)</a></p>
         <p><input type="checkbox" id="remerber" name="remember" /><label for="remember">Remember me</label></p>
         <p><input type="submit" id="spassword" name="spassword" value="Login"></p>
     </form>