projects
/
geekigeeki.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Fix corner cases of humanized links
[geekigeeki.git]
/
geekigeeki.py
diff --git
a/geekigeeki.py
b/geekigeeki.py
index 6170d7394ca6bb7b91d3fdb195d0d2ba6a5b4503..678754e3a9633d29fc779eeed48eeddb8fa9fa87 100755
(executable)
--- a/
geekigeeki.py
+++ b/
geekigeeki.py
@@
-22,12
+22,10
@@
__version__ = '$Id$'[4:12]
from time import clock
start_time = clock()
from time import clock
start_time = clock()
+title_done = False
import cgi, sys, os, re, errno, stat
import cgi, sys, os, re, errno, stat
-# Regular expression defining a WikiWord
-# (but this definition is also assumed in other places)
-word_re = re.compile(r"^\b((([A-Z][a-z0-9]+){2,}/)*([A-Z][a-z0-9]+){2,})\b$")
# FIXME: we accept stuff like foo/../bar and we shouldn't
file_re = re.compile(r"^\b([A-Za-z0-9_\-][A-Za-z0-9_\.\-/]*)\b$")
img_re = re.compile(r"^.*\.(png|gif|jpg|jpeg|bmp|ico|ogm|ogg|mkv|mpg|mpeg|mp4|avi|asf|flv|wmv|qt)$", re.IGNORECASE)
# FIXME: we accept stuff like foo/../bar and we shouldn't
file_re = re.compile(r"^\b([A-Za-z0-9_\-][A-Za-z0-9_\.\-/]*)\b$")
img_re = re.compile(r"^.*\.(png|gif|jpg|jpeg|bmp|ico|ogm|ogg|mkv|mpg|mpeg|mp4|avi|asf|flv|wmv|qt)$", re.IGNORECASE)
@@
-35,8
+33,6
@@
video_re = re.compile(r"^.*\.(ogm|ogg|mkv|mpg|mpeg|mp4|avi|asf|flv|wmv|qt)$", re
url_re = re.compile(r"^[a-z]{3,8}://[^\s'\"]+\S$")
ext_re = re.compile(r"\.([^\./]+)$")
url_re = re.compile(r"^[a-z]{3,8}://[^\s'\"]+\S$")
ext_re = re.compile(r"\.([^\./]+)$")
-title_done = False
-
# CGI stuff ---------------------------------------------------------
def script_name():
return os.environ.get('SCRIPT_NAME', '')
# CGI stuff ---------------------------------------------------------
def script_name():
return os.environ.get('SCRIPT_NAME', '')
@@
-82,16
+78,19
@@
def relative_url(pathname, privileged=False):
def permalink(s):
return re.sub(' ', '-', re.sub('[^a-z0-9_ ]', '', s.lower()).strip())
def permalink(s):
return re.sub(' ', '-', re.sub('[^a-z0-9_ ]', '', s.lower()).strip())
+def humanlink(s):
+ return re.sub(r'([^:/\.]+)(?:\.[^/:]+|)$', r'\1', s.replace('_', ' '))
+
# Split arg lists like "blah| blah blah| width=100 | align = center",
# return a list containing anonymous arguments and a map containing the named arguments
def parse_args(s):
args = []
kwargs = {}
for arg in s.strip('<[{}]>').split('|'):
# Split arg lists like "blah| blah blah| width=100 | align = center",
# return a list containing anonymous arguments and a map containing the named arguments
def parse_args(s):
args = []
kwargs = {}
for arg in s.strip('<[{}]>').split('|'):
- try:
- key, val = arg.split('=', 1)
- kwargs[
key.strip()] = val.strip(
)
- e
xcept ValueError
:
+ m = re.match('\s*(\w+)\s*=\s*(.+)\s*', arg)
+ if m is not None:
+ kwargs[
m.group(1)] = m.group(2
)
+ e
lse
:
args.append(arg.strip())
return (args, kwargs)
args.append(arg.strip())
return (args, kwargs)
@@
-162,24
+161,24
@@
def send_title(name, text="Limbo", msg_text=None, msg_type='error', writable=Fal
# Navbar
print('<div class="nav">')
# Navbar
print('<div class="nav">')
- print link_tag('FrontPage', site_icon or 'Home', 'navlink')
+ print link_tag('FrontPage', site_icon or 'Home',
cssclass=
'navlink')
if name:
if name:
- print(' <b>' + link_tag('?fullsearch=' + name, text, 'navlink') + '</b> ')
+ print(' <b>' + link_tag('?fullsearch=' + name, text,
cssclass=
'navlink') + '</b> ')
else:
print(' <b>' + text + '</b> ')
else:
print(' <b>' + text + '</b> ')
- print(' | ' + link_tag('FindPage', 'Find Page', 'navlink'))
+ print(' | ' + link_tag('FindPage', 'Find Page',
cssclass=
'navlink'))
if 'history_url' in globals():
print(' | <a href="' + relative_url(history_url) + '" class="navlink">Recent Changes</a>')
if name:
print(' | <a href="' + relative_url(history_url + '?a=history;f=' + name) + '" class="navlink">Page History</a>')
if name:
if 'history_url' in globals():
print(' | <a href="' + relative_url(history_url) + '" class="navlink">Recent Changes</a>')
if name:
print(' | <a href="' + relative_url(history_url + '?a=history;f=' + name) + '" class="navlink">Page History</a>')
if name:
- print(' | ' + link_tag(
'?raw=' + name, 'Raw Text',
'navlink'))
+ print(' | ' + link_tag(
name + '?a=raw', 'Raw Text', cssclass=
'navlink'))
if privileged_url is not None:
if writable:
if privileged_url is not None:
if writable:
- print(' | ' + link_tag('?a=edit&q=' + name, 'Edit', 'navlink', privileged=True))
+ print(' | ' + link_tag('?a=edit&q=' + name, 'Edit',
cssclass=
'navlink', privileged=True))
else:
else:
- print(' | ' + link_tag(name, 'Login', 'navlink', privileged=True))
+ print(' | ' + link_tag(name, 'Login',
cssclass=
'navlink', privileged=True))
else:
print(' | <i>Immutable Page</i>')
else:
print(' | <i>Immutable Page</i>')
@@
-195,33
+194,34
@@
def send_httperror(status="403 Not Found", query=""):
send_title(None, msg_text=("%s: on query '%s'" % (status, query)))
send_footer()
send_title(None, msg_text=("%s: on query '%s'" % (status, query)))
send_footer()
-def link_tag(
params, text=None, link_class
=None, privileged=False, **kvargs):
+def link_tag(
dest, text
=None, privileged=False, **kvargs):
if text is None:
if text is None:
- text =
params # default
+ text =
humanlink(dest)
elif img_re.match(text):
text = '<img border="0" src="' + relative_url(text) + '" alt="' + text + '" />'
elif img_re.match(text):
text = '<img border="0" src="' + relative_url(text) + '" alt="' + text + '" />'
+ link_class = kvargs.get('class', kvargs.get('cssclass', None))
if not link_class:
if not link_class:
- if is_external_url(
params
):
+ if is_external_url(
dest
):
link_class = 'external'
link_class = 'external'
- elif file_re.match(
params) and Page(params
).exists():
+ elif file_re.match(
dest) and Page(dest
).exists():
link_class = 'wikilink'
else:
link_class = 'wikilink'
else:
- params = nonexist_pfx + params
+ text = nonexist_pfx + text
link_class = 'nonexistent'
link_class = 'nonexistent'
- classattr = 'class="%s" ' % link_class
# Prevent crawlers from following links potentially added by spammers or to generated pages
# Prevent crawlers from following links potentially added by spammers or to generated pages
+ nofollow = ''
if link_class == 'external' or link_class == 'navlink':
if link_class == 'external' or link_class == 'navlink':
-
classattr += 'rel="nofollow"
'
+
nofollow = 'rel="nofollow"
'
- return '<a
%shref="%s">%s</a>' % (classattr, relative_url(params
, privileged=privileged), text)
+ return '<a
class="%s" %shref="%s">%s</a>' % (link_class, nofollow, relative_url(dest
, privileged=privileged), text)
def link_inline(name, descr=None, kvargs={}):
def link_inline(name, descr=None, kvargs={}):
- if not descr: descr =
name
+ if not descr: descr =
humanlink(name)
url = relative_url(name)
if video_re.match(name):
url = relative_url(name)
if video_re.match(name):
- return '<video src="%s">Your browser does not support the HTML5 video tag</video>' % url
+ return '<video
controls="1"
src="%s">Your browser does not support the HTML5 video tag</video>' % url
elif img_re.match(name):
return '<a href="%s"><img border="0" src="%s" alt="%s" /></a>' % (url, url + url_args(kvargs), descr)
elif file_re.match(name) and not ext_re.search(name): # FIXME: this guesses a wiki page
elif img_re.match(name):
return '<a href="%s"><img border="0" src="%s" alt="%s" /></a>' % (url, url + url_args(kvargs), descr)
elif file_re.match(name) and not ext_re.search(name): # FIXME: this guesses a wiki page
@@
-264,7
+264,6
@@
def handle_fullsearch(query, form):
print_search_stats(len(hits), len(all_pages))
def handle_titlesearch(query, form):
print_search_stats(len(hits), len(all_pages))
def handle_titlesearch(query, form):
- # TODO: check needle is legal -- but probably we can just accept any RE
needle = form['q'].value
send_title(None, 'Title search for "' + needle + '"')
needle = form['q'].value
send_title(None, 'Title search for "' + needle + '"')
@@
-325,7
+324,10
@@
def make_index_key():
links = ['<a href="#%s">%s</a>' % (ch, ch) for ch in 'abcdefghijklmnopqrstuvwxyz']
return '<p style="text-align: center">' + ' | '.join(links) + '</p>'
links = ['<a href="#%s">%s</a>' % (ch, ch) for ch in 'abcdefghijklmnopqrstuvwxyz']
return '<p style="text-align: center">' + ' | '.join(links) + '</p>'
-def page_list(dirname = None, re = word_re):
+def page_list(dirname = None, re = None):
+ if re is None:
+ # FIXME: WikiWord is too restrictive now!
+ re = re.compile(r"^\b((([A-Z][a-z0-9]+){2,}/)*([A-Z][a-z0-9]+){2,})\b$")
return sorted(filter(re.match, os.listdir(dirname or data_dir)))
def send_footer(mod_string=None):
return sorted(filter(re.match, os.listdir(dirname or data_dir)))
def send_footer(mod_string=None):
@@
-414,8
+416,9
@@
class WikiFormatter:
name = args.pop(0)
if len(args):
descr = args.pop(0)
name = args.pop(0)
if len(args):
descr = args.pop(0)
- # The "extthumb" nonsense works around a limitation of the HTML block model
- return '<div class="extthumb"><div class="thumb">' \
+ # This double div nonsense works around a limitation of the HTML block model
+ return '<div class="' + kvargs.get('class', 'thumb') + '">' \
+ + '<div class="innerthumb">' \
+ link_inline(name, descr, kvargs) \
+ '<div class="caption">' + descr + '</div></div></div>'
else:
+ link_inline(name, descr, kvargs) \
+ '<div class="caption">' + descr + '</div></div></div>'
else:
@@
-648,8
+651,8
@@
class Page:
for filename in page_list(self._filename(), file_re):
if img_re.match(filename):
if image_maxwidth:
for filename in page_list(self._filename(), file_re):
if img_re.match(filename):
if image_maxwidth:
- maxwidth_arg = '
|
maxwidth=' + str(image_maxwidth)
- out += '{{' + self.page_name + '/' + filename + '
|' + filename + maxwidth_arg + '
}}\n'
+ maxwidth_arg = '
|
maxwidth=' + str(image_maxwidth)
+ out += '{{' + self.page_name + '/' + filename + '
| ' + humanlink(filename) + maxwidth_arg + ' | class=thumbleft
}}\n'
else:
out += ' * [[' + self.page_name + '/' + filename + ']]\n'
return out
else:
out += ' * [[' + self.page_name + '/' + filename + ']]\n'
return out