infocalypse

(djk)
2010-02-03: Added anchor support to wikitext, added FreenetUri wikitext macro.

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')
 
-
-