Permalink
Browse files

Begin the assault on #if/#while

Start with the common style pseudo-path on the top of pages. We have
a variety of pseudo-paths that allow to identify pages at a glance:

 root:  user/*
 mark:  user      (traditional, no slash)
 tags:  user/tags
 Tag:   user/Tag/
 new:   user/[w]  (whitestar)
 edit:  user/[w]  (whitestar links back)

This patch restores regressions that templatizing introduced in the
pseudo-path area and a few other simple regressions (like missing <hr>).
  • Loading branch information...
1 parent c8980b1 commit 7aa871b5d246314517acb40fa4d9487246a1c9c0 @zaitcev committed May 29, 2012
Showing with 80 additions and 53 deletions.
  1. +6 −3 README
  2. +35 −0 slasti/__init__.py
  3. +32 −24 slasti/main.py
  4. +3 −0 slasti/tagbase.py
  5. +4 −26 slasti/template.py
View
@@ -1,4 +1,4 @@
-Slasti version 1.90 (post-Christian checkpoint)
+Slasti version 1.90.dev
Unfortunately, Oishii was taken, so Slasti it is. It's good to be trilingual.
TODO:
@@ -8,15 +8,17 @@ TODO:
- localizations
- tests (Christan's main() in template.py lacked verification)
- template docs for 2.0
+ - macro variables list - document starting with underscore
+ - parse and beautify devel notes
fixup TODO for templates:
- http://www.zaitcev.us/slasti/tester/login?savedref=%E3%82%A2%E3%83%8B%E3%83%BB%E3%83%8E%E3%83%BC%E3%83%88/
savedref = savedref.decode("utf-8", 'replace')
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
- Hitting "Preload" ends with same, in fetch_get()
Maybe just drop templating for the helper.
- - remove flooding print from template.py
- - BLACKSTAR for individual marks in the path
+ - remove flooding print from template.py - 'str found:' etc. Kill all print.
+ - rename "jsondict" into something sensible
zaitcev@kotori.zaitcev.us
@@ -70,5 +72,6 @@ Solution for the output encoding problem:
unicode and is safe to use within attributes.
* Everything else should end up in jsondict as unescaped unicode, escaping and
encoding is handled in the templating engine.
+ -- this breaks for variables that contain HTML, they start with '_'.
* Template().substitute() returns bytes. Don't mess with that, just return it
to the wsgi server.
View
@@ -8,6 +8,7 @@
import urllib
import urlparse
+
class AppError(Exception):
pass
class App400Error(Exception):
@@ -23,6 +24,7 @@ class AppPostError(Exception):
class AppGetPostError(Exception):
pass
+
def safestr(u):
if isinstance(u, unicode):
return u.encode('utf-8')
@@ -45,6 +47,32 @@ def escapeURL(s):
s = s.replace('>', '%3E')
return s
+html_escape_table = {
+ ">": "&gt;",
+ "<": "&lt;",
+ "&": "&amp;",
+ '"': "&quot;",
+ "'": "&apos;",
+ "\\": "&#92;",
+ }
+
+def escapeHTML(text):
+ """Escape strings to be safe for use anywhere in HTML
+
+ Should be used for escaping any user-supplied strings values before
+ outputting them in HTML. The output is safe to use HTML running text and
+ within HTML attributes (e.g. value="%s").
+
+ Escaped chars:
+ < and > HTML tags
+ & HTML entities
+ " and ' Allow use within HTML tag attributes
+ \\ Shouldn't actually be necessary, but better safe than sorry
+ """
+ # performance idea: compare with cgi.escape-like implementation
+ return "".join(html_escape_table.get(c,c) for c in text)
+
+
class Context:
def __init__(self, pfx, user, base, method, path, query, pinput, coos):
# prefix: Path where the application is mounted in WSGI or empty string.
@@ -74,11 +102,13 @@ def __init__(self, pfx, user, base, method, path, query, pinput, coos):
def create_jsondict(self):
userpath = self.prefix+'/'+self.user['name']
+ # XXX Decide if keep unused: name_user, href_user
jsondict = {"name_user": self.user["name"],
"href_user": userpath,
"href_tags": "%s/tags" % userpath,
"href_new": "%s/new" % userpath,
}
+
if self.flogin:
jsondict["href_export"]= userpath + '/export.xml'
jsondict["href_login"] = None
@@ -87,6 +117,10 @@ def create_jsondict(self):
jsondict["href_login"] = "%s/login" % userpath
if self.path and self.path != "login" and self.path != "edit":
jsondict["href_login"] += '?savedref=%s' % self.path
+
+ userstr = '<a href="%s/">%s</a>' % (userpath, self.user['name'])
+ jsondict['_main_path'] = userstr
+
return jsondict
def _parse_args(self, args):
@@ -109,4 +143,5 @@ def get_pinput_arg(self, argname):
self._pinput_args = self._parse_args(self._pinput)
return self._pinput_args.get(argname, None)
+
import main, tagbase
View
@@ -10,6 +10,7 @@
import urllib
import urlparse
import base64
+import cgi
import os
import hashlib
import httplib
@@ -18,13 +19,16 @@
from slasti import AppError, App400Error, AppLoginError, App404Error
from slasti import AppGetError, AppGetPostError
+from slasti import escapeHTML
+from slasti import Context
import slasti
import tagbase
from template import Template
PAGESZ = 25
-WHITESTAR = u"\u2606"
+BLACKSTAR = u"\u2605" # "&#9733;"
+WHITESTAR = u"\u2606" # "&#9734;"
def page_back(mark):
mark = mark.pred()
@@ -40,6 +44,12 @@ def page_back(mark):
n += 1
return mark
+def mark_anchor_html(mark, path, text):
+ if mark == None:
+ return '[-]'
+ (stamp0, stamp1) = mark.key()
+ return '[<a href="%s/mark.%d.%02d">%s</a>]' % (path, stamp0, stamp1, text)
+
def page_url_from_mark(mark, path):
if mark is None:
return None
@@ -69,16 +79,17 @@ def findmark(mark_str):
def page_any_html(start_response, ctx, mark_top):
userpath = ctx.prefix+'/'+ctx.user['name']
- what = mark_top.tag()
+ jsondict = ctx.create_jsondict()
+
+ what = mark_top.tag()
if what:
path = userpath + '/' + what
+ jsondict['_main_path'] = jsondict['_main_path']+' / '+escapeHTML(what)+'/'
else:
path = userpath
+ jsondict['_main_path'] = jsondict['_main_path']+' / '+BLACKSTAR
- start_response("200 OK", [('Content-type', 'text/html; charset=utf-8')])
- jsondict = ctx.create_jsondict()
- jsondict["current_tag"] = what
jsondict["marks"] = []
mark = mark_top
@@ -97,6 +108,8 @@ def page_any_html(start_response, ctx, mark_top):
"href_page_this": page_url_from_mark(mark_top, path),
"href_page_next": page_url_from_mark(mark_next, path),
})
+
+ start_response("200 OK", [('Content-type', 'text/html; charset=utf-8')])
return [template_html_page.substitute(jsondict)]
def page_mark_html(start_response, ctx, stamp0, stamp1):
@@ -123,8 +136,8 @@ def page_empty_html(start_response, ctx):
start_response("200 OK", [('Content-type', 'text/html; charset=utf-8')])
jsondict = ctx.create_jsondict()
+ jsondict['_main_path'] = jsondict['_main_path']+' / [-]'
jsondict.update({
- "current_tag": "[-]",
"marks": [],
})
return [template_html_page.substitute(jsondict)]
@@ -207,6 +220,7 @@ def fetch_get(start_response, ctx):
title = fetch_parse(body)
start_response("200 OK", [('Content-type', 'text/plain; charset=utf-8')])
+ # XXX Ewww, why substitute here? Just safe it out. Compare with 1.2.
jsondict = { "output": '%s\r\n' % title }
return [template_simple_output.substitute(jsondict)]
@@ -225,6 +239,10 @@ def mark_post(start_response, ctx, mark):
raise App404Error("Mark not found: "+str(stamp0)+"."+str(stamp1))
return mark_get(start_response, ctx, mark, stamp0)
+# XXX regressed HTML
+# - uses same format as page (not a bad idea - old format was too bland,
+# but needs something to differentiate them at a glance).
+# - bottom screwed up, goose feet left for right; blackstar instead of white
def mark_get(start_response, ctx, mark, stamp0):
path = ctx.prefix+'/'+ctx.user['name']
@@ -315,7 +333,7 @@ def full_tag_html(start_response, ctx):
userpath = ctx.prefix + '/' + ctx.user['name']
start_response("200 OK", [('Content-type', 'text/html; charset=utf-8')])
jsondict = ctx.create_jsondict()
- jsondict["current_tag"] = "tags"
+ jsondict['_main_path'] = jsondict['_main_path']+' / tags'
jsondict["tags"] = []
for tag in ctx.base.tagcurs():
ref = tag.key()
@@ -332,6 +350,7 @@ def login_form(start_response, ctx):
savedref = ctx.get_query_arg("savedref")
start_response("200 OK", [('Content-type', 'text/html; charset=utf-8')])
+ # XXX Common constructor with jsondict_create
jsondict = {
"username": username,
"action_login": "%s/login" % userpath,
@@ -436,13 +455,13 @@ def new_form(start_response, ctx):
href = ctx.get_query_arg('href')
jsondict = ctx.create_jsondict()
+ jsondict['_main_path'] = jsondict['_main_path']+' / ['+WHITESTAR+']'
jsondict.update({
"id_title": "title1",
"id_button": "button1",
"href_editjs": ctx.prefix + '/edit.js',
"href_fetch": userpath + '/fetchtitle',
"mark": None,
- "current_tag": "[" + WHITESTAR + "]",
"action_edit": userpath + '/edit',
"val_title": title,
"val_href": href,
@@ -459,14 +478,14 @@ def edit_form(start_response, ctx):
raise App400Error("not found: "+str(stamp0)+"."+str(stamp1))
jsondict = ctx.create_jsondict()
+ starref = mark_anchor_html(mark, userpath, WHITESTAR)
+ jsondict['_main_path'] = jsondict['_main_path']+' / '+starref
jsondict.update({
"id_title": "title1",
"id_button": "button1",
"href_editjs": ctx.prefix + '/edit.js',
"href_fetch": userpath + '/fetchtitle',
"mark": mark.to_jsondict(userpath),
- "current_tag": WHITESTAR,
- "href_current_tag": '%s/mark.%d.%02d' % (userpath, stamp0, stamp1),
"action_edit": "%s/mark.%d.%02d" % (userpath, stamp0, stamp1),
"action_delete": userpath + '/delete',
"val_title": mark.title,
@@ -627,20 +646,7 @@ def app(start_response, ctx):
border=0 cellpadding=1 cellspacing=0>
<tr valign="top">
<td align="left">
- <h2 style="margin-bottom:0">
- <a href="$href_user">$name_user</a> /
- #if ${href_current_tag:-}
- <a href="$href_current_tag">
- #end if
- #if ${current_tag:-}
- $current_tag
- #else
- &#9733;
- #end if
- #if ${href_current_tag:-}
- </a>
- #end if
- </h2>
+ <h2 style="margin-bottom:0"> $_main_path </h2>
</td>
<td align="right">
#if $href_login
@@ -817,6 +823,8 @@ def app(start_response, ctx):
(There is no undo.)
</form>
#end if
+
+ <hr />
""")
template_simple_output = Template("""$output""")
View
@@ -269,6 +269,7 @@ def to_jsondict(self, path_prefix):
mark_url = '%s/mark.%d.%02d' % (path_prefix, self.stamp0, self.stamp1)
ts = time.gmtime(self.stamp0)
+ # XXX common constructor with create_jsondict, please
jsondict = {
"date": unicode(time.strftime("%Y-%m-%d", ts)),
"href_mark": mark_url,
@@ -289,6 +290,8 @@ def to_jsondict(self, path_prefix):
})
jsondict["tags_str"] = ' '.join(tags_str)
+ jsondict['_main_path'] = "MOO"
+
return jsondict
def succ(self):
View
@@ -5,36 +5,11 @@
# See file COPYING for licensing information (expect GPL 2).
#
+from slasti import escapeHTML
import string
import re
-html_escape_table = {
- ">": "&gt;",
- "<": "&lt;",
- "&": "&amp;",
- '"': "&quot;",
- "'": "&apos;",
- "\\": "&#92;",
- }
-
-def escapeHTML(text):
- """Escape strings to be safe for use anywhere in HTML
-
- Should be used for escaping any user-supplied strings values before
- outputting them in HTML. The output is safe to use HTML running text and
- within HTML attributes (e.g. value="%s").
-
- Escaped chars:
- < and > HTML tags
- & HTML entities
- " and ' Allow use within HTML tag attributes
- \\ Shouldn't actually be necessary, but better safe than sorry
- """
- # performance idea: compare with cgi.escape-like implementation
- return "".join(html_escape_table.get(c,c) for c in text)
-
-
class TemplateError(ValueError):
def __init__(self, m, message):
self.m = m
@@ -122,12 +97,15 @@ def __getitem__(self, item):
# Separate the query into the real lookup string and the default
# Then do the lookup; if it blows up or the result is None, return the
# default. Otherwise return the looked up value
+ # XXX WTF we have defaults?!
lookup_str, default = self._parse_default(item)
default = self._enforce_encoding(default)
try:
lookup_result = self._do_lookup(lookup_str)
if lookup_result is None:
return default
+ if lookup_str[0] == '_':
+ return lookup_result
return self._enforce_encoding(lookup_result)
except (IndexError, KeyError) as e:
# If we can't find a member/submember, return the default

0 comments on commit 7aa871b

Please sign in to comment.