Mercurial > hg > bitsyblog
changeset 15:36698624435b
blog page mostly works
author | k0s <k0scist@gmail.com> |
---|---|
date | Sun, 25 Oct 2009 17:25:58 -0400 |
parents | 645aa0f3279f |
children | 2bd6b2b543dc |
files | bitsyblog/bitsyblog.py bitsyblog/templates/blog.html bitsyblog/templates/navigation.html |
diffstat | 3 files changed, 166 insertions(+), 111 deletions(-) [+] |
line wrap: on
line diff
--- a/bitsyblog/bitsyblog.py Wed Oct 07 17:26:13 2009 -0400 +++ b/bitsyblog/bitsyblog.py Sun Oct 25 17:25:58 2009 -0400 @@ -31,11 +31,13 @@ from blog import FileBlog from cStringIO import StringIO from docutils.utils import SystemMessage +from genshi.builder import Markup from genshi.template import TemplateLoader from lxml import etree from markup.form import Form from paste.fileapp import FileApp from pkg_resources import resource_filename +from urlparse import urlparse from user import FilespaceUsers from webob import Request, Response, exc @@ -55,10 +57,13 @@ 'subject': '[ %(date)s ]:', 'n_links': 5, # number of links for navigation 'site_name': 'bitsyblog', - 'auto_reload': 'False', + 'auto_reload': 'True', 'help_file': None, } + + cooked_bodies = {} + def __init__(self, **kw): for key in self.defaults: setattr(self, key, kw.get(key, self.defaults[key])) @@ -386,41 +391,37 @@ name = None return name, path - def user_url(self, request, user, *args, **kw): - permalink = kw.get('permalink') - if permalink: - _args = [ request.host_url, user ] - else: - _args = [ user ] - _args.extend(args) - return '/'.join([str(arg) for arg in _args]) + ### methods - ### - - def isentry(self, string): # TODO -> blog.py - return (len(string) == len(''.join(utils.timeformat))) and string.isdigit() - - def permalink(self, request, blogentry): - return self.user_url(request, blogentry.user, blogentry.datestamp(), permalink=True) - - def link(self, request, path, permanant=False): + def link(self, request, path=(), permanant=False): if isinstance(path, basestring): path = [ path ] path = [ i.strip('/') for i in path ] if permanant: - path = [ request.application_url ] + list(path) - return '/'.join(path) + application_url = request.application_url else: - if request.path: - path = [ request.path ] + list(path) - return '/%s' % ('/'.join(path)) + + application_url = urlparse(request.application_url)[2] + path = [ application_url ] + list(path) + return '/'.join(path) - ### mangled URLs + def user_url(self, request, user, *args, **kw): + """link to a user resource""" + permalink = kw.get('permalink', False) + path = [ user ] + path.extend(args) + return self.link(request, path, permalink) + + def permalink(self, request, blogentry): + """permalink for a blog entry""" + return self.user_url(request, blogentry.user, blogentry.datestamp(), permalink=True) def mangledurl(self, request, blogentry): + """return a mangled url for obfuscated sharing""" return self.user_url(request, blogentry.user, 'x%x' % (int(blogentry.datestamp()) * self.users.secret(blogentry.user)), permalink=True) def unmangleurl(self, url, user): + """unmangle a url for obfuscated sharing""" url = url.strip('x') try: value = int(url, 16) @@ -436,6 +437,10 @@ ### blog retrival methods + def isentry(self, string): # TODO -> blog.py + """returns whether the string is a blog entry""" + return (len(string) == len(''.join(utils.timeformat))) and string.isdigit() + def number_of_posts(self, request, user=None): """return the number of blog posts to display""" # determine number of posts to display (None -> all) @@ -451,7 +456,6 @@ def number_of_links(self, request, user=None): """return the number of links to display in the navigation""" - # determine number of navigation links to display n_links = request.GET.get('n') if n_links == 'all': return -1 @@ -525,25 +529,28 @@ if feedtitle: head_markup = ( '<link rel="alternate" type="application/atom+xml" title="%s" href="atom" />' % feedtitle, '<link rel="alternate" type="application/rss+xml" title="%s" href="rss" />' % feedtitle,) + return markup.wrap(self.site_nav(request)+body, title, stylesheets, head_markup=head_markup) def site_nav(self, request): """returns HTML for site navigation""" - links = [('/',), ] + + links = [(self.link(request), '/'), ] user = self.authenticated(request) if user: - links.extend([('/%s' % user, user), - ('/%s/post' % user, 'post'), - ('/%s/preferences' % user, 'preferences'), - ('/logout', 'logout')]) + links.extend([(self.user_url(request, user), user), + (self.user_url(request, user, 'post'), user), + (self.user_url(request, user, 'preferences'), 'preferences'), + (self.link(request, 'logout'), 'logout')]) else: - links.extend([('/login', 'login'), ('/join', 'join')]) + links.extend([(self.link(request, 'login'), 'login'), + (self.link(request, 'join'), 'join')]) if hasattr(self, 'help'): - links.append(('/help', 'help')) + links.append((self.link(request, 'help'), 'help')) - links = [ markup.link(*i) for i in links ] - return markup.listify(links, ordered=False, **{ 'class': 'site-nav'}) + request.environ['data']['links'] = links + def index(self, n_links): retval = StringIO() @@ -597,60 +604,90 @@ print >> retval, '</div>' return retval.getvalue() - def blog_entry(self, request, user, entry): - """given the content string, return a marked-up blog entry""" - # XXX no need to pass user +# def blog_entry(self, request, user, entry): +# """given the content string, return a marked-up blog entry""" +# # XXX no need to pass user - # user preferences - prefs = request.user.settings - format = prefs.get('Date format', self.date_format) - subject = prefs.get('Subject', self.subject) +# # user preferences +# prefs = request.user.settings +# format = prefs.get('Date format', self.date_format) +# subject = prefs.get('Subject', self.subject) - role = self.role(user, request) +# role = self.role(user, request) - subject = subject % { 'date' : entry.date.strftime(format) } - subject = cgi.escape(subject) - html = StringIO() - blog_id = entry.datestamp() - print >> html, '<div id="%s" class="blog-entry">' % blog_id - print >> html, '<a name="%s" />' % blog_id - print >> html, '<div class="subject">' - print >> html, '<a href="/%s">%s</a>' % (self.user_url(request, user, blog_id), subject) - if (entry.privacy == 'secret') and (role == 'friend'): - print >> html, '<em>secret</em>' - print >> html, '</div>' - print >> html, self.cooker(entry.body) +# subject = subject % { 'date' : entry.date.strftime(format) } +# subject = cgi.escape(subject) +# html = StringIO() +# blog_id = entry.datestamp() +# print >> html, '<div id="%s" class="blog-entry">' % blog_id +# print >> html, '<a name="%s" />' % blog_id +# print >> html, '<div class="subject">' +# print >> html, '<a href="/%s">%s</a>' % (self.user_url(request, user, blog_id), subject) +# if (entry.privacy == 'secret') and (role == 'friend'): +# print >> html, '<em>secret</em>' +# print >> html, '</div>' +# print >> html, self.cooker(entry.body) - if role == 'author': - print >> html, '<div><form action="/%s" method="post">' % self.user_url(request, entry.user, blog_id) - print >> html, self.privacy_settings(entry.privacy) - print >> html, '<input type="submit" name="submit" value="Change Privacy" />' - print >> html, '</form></div>' - if entry.privacy != 'public': - title = "You can give this URL so people may see this %s post without logging in" % entry.privacy - print >> html, '<div>' - print >> html, '<span title="%s">Mangled URL:</span>' % title - print >> html, markup.link(self.mangledurl(request, entry)) - print >> html, '</div>' +# if role == 'author': +# print >> html, '<div><form action="/%s" method="post">' % self.user_url(request, entry.user, blog_id) +# print >> html, self.privacy_settings(entry.privacy) +# print >> html, '<input type="submit" name="submit" value="Change Privacy" />' +# print >> html, '</form></div>' +# if entry.privacy != 'public': +# title = "You can give this URL so people may see this %s post without logging in" % entry.privacy +# print >> html, '<div>' +# print >> html, '<span title="%s">Mangled URL:</span>' % title +# print >> html, markup.link(self.mangledurl(request, entry)) +# print >> html, '</div>' - print >> html, '</div>' - return html.getvalue() +# print >> html, '</div>' +# return html.getvalue() def write_blog(self, user, blog, path, n_links, request): """return the user's blog in HTML""" - # XXX no need to pass path or user! - retval = StringIO() - print >> retval, self.navigation(user, blog, path, n_links, 0) + + # XXX probably should go elsewhere for entry in blog: - print >> retval, self.blog_entry(request, user, entry) - feedtitle=None - if request.path_info.strip('/') == user: - feedtitle = "%s's blog" % user - title = None - if len(blog) == 1: - format = request.user.settings.get('Date format', self.date_format) - title = blog[0].date.strftime(format) - return self.render(request, retval.getvalue(), title=title, feedtitle=feedtitle) + if (user, entry.datestamp()) not in self.cooked_bodies: + self.cooked_bodies[(user, entry.datestamp())] = self.cooker(entry.body) + entry.cooked_body = Markup(self.cooked_bodies[(user, entry.datestamp())]) + + # site nav + # XXX def site_nav() puts directly in request.environ['data'] + # should return instead + self.site_nav(request) + + # user data -> should be moved up the chain + data = request.environ['data'] + data['user'] = user + data['role'] = self.role(user, request) + data['stylesheets'] = () # TODO + data['subject'] = request.user.settings.get('Subject', self.subject) + data['date_format'] = request.user.settings.get('Date format', self.date_format) + data['user_url'] = self.user_url + data['mangledurl'] = self.mangledurl + + # blog data + data['blog'] = blog + data['n_links'] = n_links + + # render the template + template = self.loader.load('blog.html') + return template.generate(**data).render() + +# # XXX no need to pass path or user! +# retval = StringIO() +# print >> retval, self.navigation(user, blog, path, n_links, 0) +# for entry in blog: +# print >> retval, self.blog_entry(request, user, entry) +# feedtitle=None +# if request.path_info.strip('/') == user: +# feedtitle = "%s's blog" % user +# title = None +# if len(blog) == 1: +# format = request.user.settings.get('Date format', self.date_format) +# title = blog[0].date.strftime(format) +# return self.render(request, retval.getvalue(), title=title, feedtitle=feedtitle) def restructuredText(self, string): origstring = string @@ -781,7 +818,7 @@ return self.render(request, retval.getvalue()) def preferences_form(self, request, user): - prefs = self.request.user.settings + prefs = request.user.settings form = Form() # date format @@ -863,31 +900,26 @@ return self.user, path def user_url(self, request, user, *args, **kw): - permalink = kw.get('permalink') - if permalink: - _args = [ request.host_url ] - else: - _args = [ ] - _args.extend(args) - return '/'.join([str(arg) for arg in _args]) + permalink = kw.get('permalink', False) + return self.link(request, args, permalink) def passwords(self): return { self.user: self.users.password(self.user) } def site_nav(self, request): """returns HTML for site navigation""" - links = [('/', self.user), ] + links = [(self.user_url(request, self.user), self.user), ] user = self.authenticated(request) if user: - links.extend([ - ('/post', 'post'), - ('/preferences', 'preferences'), - ('/logout', 'logout')]) + links.extend([(self.user_url(request, user, 'post'), 'post'), + (self.user_url(request, user, 'preferences'), 'preferences'), + (self.link(request, 'logout'), 'logout')]) else: - links.append(('/login', 'login')) + links.append((self.link(request, 'login'), 'login')) if hasattr(self, 'help'): - links.append(('/help', 'help')) + links.append((self.link(request, 'help'), 'about')) + - links = [ markup.link(*i) for i in links ] - return markup.listify(links, ordered=False, **{ 'class': 'site-nav'}) + request.environ['data']['links'] = links +
--- a/bitsyblog/templates/blog.html Wed Oct 07 17:26:13 2009 -0400 +++ b/bitsyblog/templates/blog.html Sun Oct 25 17:25:58 2009 -0400 @@ -8,8 +8,8 @@ <head> <title>${user} - ${site_name}</title> - <py:for each="index, sheet in stylesheets"> - <link href="${link(request, ('css', sheet)" + <py:for each="index, sheet in enumerate(stylesheets)"> + <link href="${link(request, ('css', sheet))}" type="text/css" rel="${index and 'alternate stylesheet' or 'stylesheet'}" title="sheet.rsplit('.', 1)[0]"/> @@ -19,13 +19,16 @@ <body> - <!-- nav links --> - <xi:include href="navigation.html"> + <xi:include href="navigation.html" /> - <div py:if="n_links == 0 or not len(blog)" class="navigation"> + <div class="navigation" + py:if="n_links == 0 or not len(blog)" + py:with="_n_links = (n_links != -1) and n_links or len(blog)"> <ul> - + <li py:for="index in range(_n_links)"> + </li> </ul> + <a py:if="_n_links != len(blog)" href="TODO?n=all">more</a> </div> <!-- blog entries --> @@ -34,28 +37,41 @@ <a name="${entry.datestamp()}" /> <div class="subject"> - <a href="${'foo'}">${subject}</a> - <em py:if="entry.privacy == secret and role == 'friend'"> + <a href="${user_url(request, request.user.name, entry.datestamp())}">${subject % dict(date=entry.date.strftime(date_format))}</a> + <em py:if="entry.privacy == 'secret' and role == 'friend'"> secret </em> </div> - ${body} + ${entry.cooked_body} <div py:if="role == 'author'"> <!-- privacy settings --> <form action="TODO" method="post"> - <span title="viewable to everyone">public<input checked type="radio" name="privacy" value="public"/></span> - <span title="viewable only to your friends">secret<input type="radio" name="privacy" value="secret"/></span> - <span title="viewable only to you">private<input type="radio" name="privacy" value="private"/></span> + <span title="viewable to everyone"> + public + <input type="radio" name="privacy" value="public" + py:attrs="{'checked': entry.privacy=='public' and True or None}"/> + </span> + <span title="viewable only to your friends"> + secret + <input type="radio" name="privacy" value="secret" + py:attrs="{'checked': entry.privacy=='secret' and True or None}"/> + </span> + <span title="viewable only to you"> + private + <input type="radio" name="privacy" value="private" + py:attrs="{'checked': entry.privacy=='private' and True or None}"/> + </span> <input type="submit" name="submit" value="Change Privacy" /> </form> <!-- mangled URL --> - <div> + <div py:if="entry.privacy != 'public'" + py:with="mangled_url = mangledurl(request, entry)"> <span title="${'You can give this URL so people may see this %s post without logging in' % entry.privacy}">Mangled URL:</span> - <a href="TODO">${'TODO'}</a> + <a href="${mangled_url}">${mangled_url}</a> </div> </div>
--- a/bitsyblog/templates/navigation.html Wed Oct 07 17:26:13 2009 -0400 +++ b/bitsyblog/templates/navigation.html Sun Oct 25 17:25:58 2009 -0400 @@ -5,7 +5,14 @@ xmlns:py="http://genshi.edgewall.org/" xmlns:xi="http://www.w3.org/2001/XInclude" py:strip="True"> + <!-- nav bar --> - + <div class="site-nav"> + <ul> + <li py:for="link, name in links"> + <a href="${link}">${name}</a> + </li> + </ul> + </div> </html>