Added anchor support to wikitext, added FreenetUri wikitext macro. Features: Patch from tesselation+ to add support for anchors and anchor links to wikitext. @@@text0|label0@@@ makes an anchor with display text text0 and label label0. @@@@text0|label0@@@@ makes a link with display text text0 to the anchor with label label0 You can style anchor text with A.namedanchor in piki.css. Added FreesiteUri wikitext macro. [[FreesiteUri]] makes an "aggressive" (i.e. negative) link to the freesite uri specified in info.txt. Fixes: Fix missing script name in query urls.
diff --git a/fniki/default_files/www/piki.css b/fniki/default_files/www/piki.css
--- a/fniki/default_files/www/piki.css
+++ b/fniki/default_files/www/piki.css
@@ -4,3 +4,4 @@ A.nonexistent { background-color: #CCCCC
A.forkedtitle {color: #585858}
A.removedfork {color: #00FF00}
A.existingfork {color: #FF0000}
+A.namedanchor {color: #000000}
\ No newline at end of file
diff --git a/fniki/piki.py b/fniki/piki.py
--- a/fniki/piki.py
+++ b/fniki/piki.py
@@ -497,30 +497,11 @@ def _macro_RemoteChanges():
buf.write(reject_summary(entry, time_tuple))
return buf.getvalue()
-
def _macro_BookMark():
- # REDFLAG: Revisit.
- # Config file is in the directory above the data_dir directory,
- # so I don't want to depend on that while running.
- # Used info.txt file from the head end instead.
-
- full_path = os.path.join(data_dir, 'info.txt')
try:
- in_file = codecs.open(full_path, 'rb', 'ascii')
- usk, desc, link_name = in_file.read().splitlines()[:3]
-
- except ValueError:
- return "[BookMark macro failed: couldn't parse data from info.txt]"
- except IOError:
- return "[BookMark macro failed: couldn't read data from info.txt]"
- except UnicodeError:
- # REDFLAG: Untested code path.
- return "[BookMark macro failed: illegal encoding in info.txt]"
-
- if (has_illegal_chars(usk) or
- has_illegal_chars(desc) or
- has_illegal_chars(link_name)):
- return "[BookMark macro failed: illegal html characters in info.txt]"
+ usk, desc, link_name = read_info()
+ except ValueError, err:
+ return "[BookMark macro failed: %s]" % str(err.args[0])
if not scrub_links:
return '<a href="%s">%s</a>' % (LINKS_DISABLED_PAGE, link_name)
@@ -529,6 +510,23 @@ def _macro_BookMark():
% (usk, desc, link_name))
+def _macro_FreesiteUri():
+ try:
+ usk, desc, link_name = read_info()
+ fields = usk.split('/')
+ if len(fields) > 2 and (not fields[-2].startswith('-')):
+ fields[-2] = '-' + fields[-2]
+ usk = '/'.join(fields)
+
+ except ValueError, err:
+ return "[FreesiteUri macro failed: %s]" % str(err.args[0])
+
+ if not scrub_links:
+ return '<a href="%s">freenet:%s</a>' % (LINKS_DISABLED_PAGE, usk)
+
+
+ return '<a href="/%s">freenet:%s</a>' % (usk, usk)
+
# ----------------------------------------------------------
# REDFLAG: faster way to do this? does it matter?
@@ -605,6 +603,36 @@ class PageFormatter:
return ' <img src="%s"%s%s/> ' % (uri, alt_attrib, title_attrib)
+
+ def _anch_repl(self, word):
+ word = word[3:-3]
+
+ if has_illegal_chars(word):
+ return (" <br>[ILLEGAL ANCHOR IN WIKITEXT: " +
+ " illegal characters! ]<br> ")
+
+ fields = word.strip().split('|')
+ if len(fields) != 2:
+ return (" <br>[ILLEGAL ANCHOR IN WIKITEXT: " +
+ " needs to be in the @@@text|label@@@ format! ]<br> ")
+
+ return ('<a class="namedanchor" name="%s">%s</a>' %
+ (fields[1], fields[0]))
+
+ def _anchl_repl(self, word):
+ word = word[4:-4]
+ if has_illegal_chars(word):
+ return (" <br>[ILLEGAL ANCHOR LINK IN WIKITEXT: " +
+ " illegal characters! ]<br> ")
+
+ fields = word.strip().split('|')
+
+ if len(fields) != 2:
+ return (" <br>[ILLEGAL ANCHOR LINK IN WIKITEXT: " +
+ " needs to be in the @@@text|label@@@ format! ]<br> ")
+
+ return '<a href="#%s">%s</a>' % (fields[1], fields[0])
+
def _ent_repl(self, s):
return {'&': '&',
'<': '<',
@@ -648,7 +676,6 @@ class PageFormatter:
self.list_indents = []
return res
-
def replace(self, match):
for type, hit in match.groupdict().items():
if hit:
@@ -662,6 +689,8 @@ class PageFormatter:
scan_re = re.compile(
r"(?:(?P<emph>'{2,3})"
+ r"|(?P<ent>[<>&])"
+ + r"|(?P<anch>@@@([^@]+)@@@)"
+ + r"|(?P<anchl>@@@@([^@]+)@@@@)"
+ r"|(?P<word>\b(?:[A-Z][a-z]+){2,}\b)"
+ r"|(?P<rule>-{4,})"
+ r"|(?P<img>\[\[\[(freenet\:[^\]]+)\]\]\])"
@@ -671,7 +700,8 @@ class PageFormatter:
+ r"|(?P<pre>(\{\{\{|\}\}\}))"
+ r"|(?P<macro>\[\[(TitleSearch|FullSearch|WordIndex"
+ r"|TitleIndex|ActiveLink"
- + r"|LocalChanges|RemoteChanges|BookMark|GoTo)\]\])"
+ + r"|LocalChanges|RemoteChanges|BookMark|"
+ + r"FreesiteUri|GoTo)\]\])"
+ r")")
blank_re = re.compile("^\s*$")
bullet_re = re.compile("^\s+\*")
@@ -772,19 +802,19 @@ class Page:
def send_footer(self, versioned, mod_string=None, page_path=None,
unmodified=False):
- #base = get_scriptname() # Hmmm... forget what this was for.
+ base = get_scriptname()
print '<hr>'
if is_read_only(data_dir, self.page_name):
print "<em>The bot owner has marked this page read only.</em>"
- print (('<br><a href="?viewunmodifiedsource=%s">' %
- self.page_name) + '[View page source]</a><br>')
+ print (('<br><a href="%s?viewunmodifiedsource=%s">' %
+ (base, self.page_name)) + '[View page source]</a><br>')
return
if unmodified:
print ("<em>Read only original version " +
"of a locally modified page.</em>")
- print (('<br><a href="?viewunmodifiedsource=%s">' %
- self.page_name) + '[View page source]</a><br>')
+ print (('<br><a href="%s?viewunmodifiedsource=%s">' %
+ (base, self.page_name)) + '[View page source]</a><br>')
return
if versioned:
@@ -793,19 +823,21 @@ class Page:
return
if filefuncs.has_overlay(page_path):
- print (('<br><a href="?unmodified=%s">' % self.page_name) +
+ print (('<br><a href="%s?unmodified=%s">' % (base,
+ self.page_name)) +
'[Show original version]</a><br>')
- print (('<a href="?deletelocal=%s">' % self.page_name) +
+ print (('<a href="%s?deletelocal=%s">' % (base,
+ self.page_name)) +
'[Mark unresolved, without confirmation!]</a><br>')
else:
if filefuncs.exists(page_path, True):
print "<em>This is an unmerged fork of another page!</em>"
- print (('<br><a href="?viewsource=%s">' %
- self.page_name) +
+ print (('<br><a href="%s?viewsource=%s">' %
+ (base, self.page_name)) +
'[View page source]</a><br>')
- print (('<br><a href="?removepage=%s">' %
- self.page_name) +
+ print (('<br><a href="%s?removepage=%s">' %
+ (base, self.page_name)) +
'[Locally mark resolved, ' +
'without confirmation!]</a><br>')
@@ -823,12 +855,12 @@ class Page:
print ("<strong>This page has forks: %s!</strong><br>" %
get_fork_html(filefuncs, text_dir, name, fork_table))
- print link_tag('?edit='+name, 'EditText')
+ print link_tag('?edit=%s' % name, 'EditText')
print "of this page"
if mod_string:
print "(last modified %s)" % mod_string
print '<br>'
- print link_tag('FindPage?value='+name, 'FindPage')
+ print link_tag('FindPage?value=%s' % name, 'FindPage')
print " by browsing, searching, or an index"
if page_path is None:
@@ -836,11 +868,11 @@ class Page:
return
if filefuncs.has_overlay(page_path):
- print (('<br><a href="?unmodified=%s">' % name) +
+ print (('<br><a href="%s?unmodified=%s">' % (base, name)) +
'[Show original version]</a><br>')
- print (('<a href="?removepage=%s">' % name) +
+ print (('<a href="%s?removepage=%s">' % (base, name)) +
'[Locally delete this page without confirmation!]</a><br>')
- print (('<a href="?deletelocal=%s">' % name) +
+ print (('<a href="%s?deletelocal=%s">' % (base, name)) +
'[Undo local edits without confirmation!]</a><br>')
print "<p><em>Wiki dir: %s </em>" % data_dir
@@ -1009,6 +1041,33 @@ def is_read_only(base_dir, page_name):
finally:
in_file.close()
+# REDFLAG: Revisit.
+# Config file is in the directory above the data_dir directory,
+# so I don't want to depend on that while running.
+# Used info.txt file from the head end instead.
+def read_info():
+ full_path = os.path.join(data_dir, 'info.txt')
+ err_msg = None
+ try:
+ in_file = codecs.open(full_path, 'rb', 'ascii')
+ try:
+ usk, desc, link_name = in_file.read().splitlines()[:3]
+ finally:
+ in_file.close()
+ except UnicodeError: # ISA ValueError. Order important!
+ raise ValueError("Illegal encoding in info.txt")
+ except ValueError:
+ raise ValueError("Couldn't parse data from info.txt")
+ except IOError:
+ raise ValueError("Couldn't read data from info.txt")
+
+ if (has_illegal_chars(usk) or has_illegal_chars(desc) or
+ has_illegal_chars(link_name)):
+ raise ValueError("Illegal html characters in info.txt")
+
+ return usk, desc, link_name
+
+
def read_log_file_entries(base_dir, max_entries):
accepted = []
full_path = os.path.join(base_dir, 'accepted.txt')
@@ -1191,5 +1250,3 @@ if __name__ == "__main__" or __name__ ==
sys.stdout = real_out
print buf.getvalue().encode('utf8')
-
-