← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands-website/get_rid_of_wikiwords into lp:widelands-website

 

kaputtnik has proposed merging lp:~widelands-dev/widelands-website/get_rid_of_wikiwords into lp:widelands-website with lp:~widelands-dev/widelands-website/convert_wikiwords as a prerequisite.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  Bug #1595294 in Widelands Website: "Get rid of wikiwordification"
  https://bugs.launchpad.net/widelands-website/+bug/1595294

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands-website/get_rid_of_wikiwords/+merge/318283

Remove the code for WikiWordification and implement a new syntax for internal links:

Syntax: [[ Main Page ]] 
Result in html:
<a href="/wiki/Main Page">Main Page</a>

Syntax: [[ Main Page | Look at the first page ]] 
Result in html:
<a href="/wiki/Main Page">Look at the first page</a>

Syntax: [[ GameHelpMultiplayer/#login-into-metaserver-lobby | Metaserver login ]] 
Result in html:
<a href="/wiki/GameHelpMultiplayer/#login-into-metaserver-lobby">Metaserver login</a>

The original markdown syntax, e.g. [Look here](/wiki/Main Page), could be used furthermore for internal links and MUST be used for: External links and links which point to other parts of widelands.org like maps, profile, forum, and so on.
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands-website/get_rid_of_wikiwords into lp:widelands-website.
=== modified file 'mainpage/templatetags/wl_markdown.py'
--- mainpage/templatetags/wl_markdown.py	2017-01-21 12:39:23 +0000
+++ mainpage/templatetags/wl_markdown.py	2017-02-24 20:42:44 +0000
@@ -14,6 +14,7 @@
 from django.utils.encoding import smart_str, force_unicode
 from django.utils.safestring import mark_safe
 from settings import BLEACH_ALLOWED_TAGS, BLEACH_ALLOWED_ATTRIBUTES
+from markdownextensions.semanticwikilinks.mdx_semanticwikilinks import SemanticWikiLinkExtension
 
 # Try to get a not so fully broken markdown module
 import markdown
@@ -152,25 +153,16 @@
     return None
 
 
-custom_filters = {
-    # Wikiwordification
-    # Match a wiki page link LikeThis. All !WikiWords (with a !
-    # in front) are ignored
-    'wikiwords': (re.compile(r"(!?)(\b[A-Z][a-z]+[A-Z]\w+\b)"), lambda m:
-                  m.group(2) if m.group(1) == '!' else
-                  u"""<a href="/wiki/%(match)s">%(match)s</a>""" %
-                  {'match': m.group(2)}),
-
-}
-
+# Predefine the markdown extensions here to have a clean code in
+# do_wl_markdown()
+md_extensions = ['extra', 'toc', SemanticWikiLinkExtension()]
 
 def do_wl_markdown(value, *args, **keyw):
     # Do Preescaping for markdown, so that some things stay intact
     # This is currently only needed for this smiley ">:-)"
     value = _insert_smiley_preescaping(value)
     custom = keyw.pop('custom', True)
-    html = smart_str(markdown(value, extensions=[
-                     'extra', 'toc'], *args, **keyw))
+    html = smart_str(markdown(value, extensions=md_extensions))
 
     # Sanitize posts from potencial untrusted users (Forum/Wiki/Maps)
     if 'bleachit' in args:
@@ -199,11 +191,6 @@
             if not text.parent.name == 'code':
                 rv = _insert_smileys(rv)
 
-            for name, (pattern, replacement) in custom_filters.iteritems():
-                if not len(text.strip()) or not keyw.get(name, True):
-                    continue
-
-                rv = pattern.sub(replacement, rv)
             text.replaceWith(rv)
 
     # This call slows the whole function down...

=== added directory 'markdownextensions'
=== added file 'markdownextensions/__init__.py'
=== added directory 'markdownextensions/semanticwikilinks'
=== added file 'markdownextensions/semanticwikilinks/ChangeLog.md'
--- markdownextensions/semanticwikilinks/ChangeLog.md	1970-01-01 00:00:00 +0000
+++ markdownextensions/semanticwikilinks/ChangeLog.md	2017-02-24 20:42:44 +0000
@@ -0,0 +1,22 @@
+Changelog
+=========
+
+
+Version 1.1
+-----------
+
+- The make_link function now takes four arguments:
+    - `md`
+      :    the current Markdown instance
+    - `rel`
+      :    the value of the rel attribute
+    - `target`
+      :    the value of the href attribute
+    - `label`
+      :    the link text, if any given.
+
+
+Version 1.0
+-----------
+
+- Initial release

=== added file 'markdownextensions/semanticwikilinks/LICENSE.md'
--- markdownextensions/semanticwikilinks/LICENSE.md	1970-01-01 00:00:00 +0000
+++ markdownextensions/semanticwikilinks/LICENSE.md	2017-02-24 20:42:44 +0000
@@ -0,0 +1,30 @@
+- Copyright 2011, 2012 The Active Archives contributors
+- Copyright 2011, 2012 Michael Murtaugh 
+- Copyright 2011, 2012 Alexandre Leray
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the <organization> nor the names of its contributors may
+   be used to endorse or promote products derived from this software without
+   specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE PYTHON MARKDOWN PROJECT ''AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL ANY CONTRIBUTORS TO THE PYTHON MARKDOWN PROJECT
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=== added file 'markdownextensions/semanticwikilinks/README.md'
--- markdownextensions/semanticwikilinks/README.md	1970-01-01 00:00:00 +0000
+++ markdownextensions/semanticwikilinks/README.md	2017-02-24 20:42:44 +0000
@@ -0,0 +1,78 @@
+SemanticWikiLinks Extension for Python-Markdown
+===============================================
+
+Adds support for semantic (wiki)links (RDFa).
+
+Converts links of style `[[rel :: target | label ]]`, where `rel` and `label`
+are optional.
+
+Customizable with `make_link` option as to what the actual element is.
+
+
+Installation
+------------
+
+    pip install git+git://github.com/aleray/mdx_semanticwikilinks.git
+
+
+Usage
+-----
+
+    >>> text = "Some text with a [[WikiLink]]."
+    >>> html = markdown.markdown(text, ['semanticwikilinks'])
+    >>> print(html)
+    <p>Some text with a <a href="WikiLink">WikiLink</a>.</p>
+
+    >>> text = "[[http://activearchives.org/]], [[#id|anchor]], [[../index.html|a relative link]], [[/|an absolute link]], [[/index.html|another absolute link]]"
+    >>> html = markdown.markdown(text, ['semanticwikilinks'])
+    >>> print(html)
+    <p><a href="http://activearchives.org/";>http://activearchives.org/</a>, <a href="#id">anchor</a>, <a href="../index.html">a relative link</a>, <a href="/">an absolute link</a>, <a href="/index.html">another absolute link</a></p>
+
+Define a custom URL builder:
+
+    >>> def make_rdfa(md, rel, target, label):
+    ...     # `md` is the Markdown instance
+    ...     elt = etree.Element("span")
+    ...     elt.set("property", rel)
+    ...     elt.set("value", target)
+    ...     elt.text = label or target
+    ...     return elt
+
+    >>> md = markdown.Markdown(extensions=['semanticwikilinks'],
+    ...         extension_configs={'semanticwikilinks' : [('make_link', make_rdfa)]})
+    >>> html = md.convert('[[ Speaker :: Sherry Turkle | Second Self ]]')
+    >>> print(html)
+    <p><span property="aa:Speaker" value="Sherry Turkle">Second Self</span></p>
+
+Change the default namespace (which is "aa"):
+
+    >>> md = markdown.Markdown(extensions=['semanticwikilinks'],
+    ...         extension_configs={'semanticwikilinks' : [('namespace', 'mynamespace')]})
+    >>> html = md.convert('[[ Speaker :: Sherry Turkle | Second Self ]]')
+    >>> print(html)
+    <p><a href="Sherry Turkle" rel="mynamespace:Speaker">Second Self</a></p>
+
+To do
+-----
+
+- An optional function to wikify names? (It is already possible to achieve
+this with the custom `make_link` function).
+
+
+Dependencies
+------------
+
+* [Markdown 2.0+](http://www.freewisdom.org/projects/python-markdown/)
+
+
+Copyright
+---------
+
+- 2011, 2012 [The active archives contributors](http://activearchives.org/)
+- 2011, 2012 [Michael Murtaugh](http://automatist.org/)
+- 2011, 2012 [Alexandre Leray](http://stdin.fr/)
+
+All rights reserved.
+
+This software is released under the modified BSD License. 
+See LICENSE.md for details.

=== added file 'markdownextensions/semanticwikilinks/__init__.py'
=== added file 'markdownextensions/semanticwikilinks/mdx_semanticwikilinks.py'
--- markdownextensions/semanticwikilinks/mdx_semanticwikilinks.py	1970-01-01 00:00:00 +0000
+++ markdownextensions/semanticwikilinks/mdx_semanticwikilinks.py	2017-02-24 20:42:44 +0000
@@ -0,0 +1,168 @@
+#! /usr/bin/env python
+
+
+'''
+SemanticWikiLinks Extension for Python-Markdown
+===============================================
+
+Adds support for semantic (wiki)links (RDFa).
+
+Converts links of style `[[rel :: target | label ]]`, where `rel` and `label`
+are optional.
+
+Customizable with `make_link` option as to what the actual element is.
+
+
+Usage
+-----
+
+    >>> text = "Some text with a [[WikiLink]]."
+    >>> html = markdown.markdown(text, ['semanticwikilinks'])
+    >>> print(html)
+    <p>Some text with a <a href="WikiLink">WikiLink</a>.</p>
+
+    >>> text = "[[http://activearchives.org/]], [[#id|anchor]], [[../index.html|a relative link]], [[/|an absolute link]], [[/index.html|another absolute link]]"
+    >>> html = markdown.markdown(text, ['semanticwikilinks'])
+    >>> print(html)
+    <p><a href="http://activearchives.org/";>http://activearchives.org/</a>, <a href="#id">anchor</a>, <a href="../index.html">a relative link</a>, <a href="/">an absolute link</a>, <a href="/index.html">another absolute link</a></p>
+
+Define a custom URL builder:
+
+    >>> from markdown.util import etree
+    >>> def make_rdfa(md, rel, target, label):
+    ...     # `md` is the Markdown instance
+    ...     elt = etree.Element("span")
+    ...     elt.set("property", rel)
+    ...     elt.set("value", target)
+    ...     elt.text = label or target
+    ...     return elt
+
+    >>> md = markdown.Markdown(extensions=['semanticwikilinks'],
+    ...         extension_configs={'semanticwikilinks' : [('make_link', make_rdfa)]})
+    >>> html = md.convert('[[ Speaker :: Sherry Turkle | Second Self ]]')
+    >>> print(html)
+    <p><span property="aa:Speaker" value="Sherry Turkle">Second Self</span></p>
+
+Change the default namespace (which is "aa"):
+
+    >>> md = markdown.Markdown(extensions=['semanticwikilinks'],
+    ...         extension_configs={'semanticwikilinks' : [('namespace', 'mynamespace')]})
+    >>> html = md.convert('[[ Speaker :: Sherry Turkle | Second Self ]]')
+    >>> print(html)
+    <p><a href="Sherry Turkle" rel="mynamespace:Speaker">Second Self</a></p>
+
+To do
+-----
+
+- An optional function to wikify names? (It is already possible to achieve
+this with the custom `make_link` function).
+
+
+Dependencies
+------------
+
+* [Markdown 2.0+](http://www.freewisdom.org/projects/python-markdown/)
+
+
+Copyright
+---------
+
+2011, 2012 [The active archives contributors](http://activearchives.org/)
+2011, 2012 [Michael Murtaugh](http://automatist.org/)
+2011, 2012 [Alexandre Leray](http://stdin.fr/)
+
+All rights reserved.
+
+This software is released under the modified BSD License. 
+See LICENSE.md for details.
+'''
+
+
+import markdown
+try:
+    from markdown import etree
+except ImportError:
+    from markdown.util import etree
+import re
+
+
+__version__ = '1.1.1'
+
+
+WIKILINK_RE = r"""
+\[\[\s*
+    (?:((?P<namespace>\w+):)?(?P<rel>[^\]#]+?) \s* ::)? \s*
+    (?P<target>.+?) \s*
+    (?:\| \s* (?P<label>.+?) \s*)?
+\]\](?!\])
+""".strip()
+
+
+def make_link(md, rel, target, label):
+    a = etree.Element('a')
+    a.set('href', target)
+    if rel:
+        a.set('rel', rel)
+    a.text = label or target
+    return a
+
+
+def make_wikilink(md, rel, target, label):
+    # Turns a link from Syntax [[ Page Name | linktext ]]
+    a = etree.Element('a')
+    a.set('href', '/wiki/' + target)
+    a.set('class', 'wikilink')
+    if rel:
+        pass
+    a.text = label or target
+    return a
+
+
+class SemanticWikiLinkExtension(markdown.Extension):
+
+    def __init__(self, *args, **kwargs):
+        self.config = {
+            'make_link': [make_wikilink, 'Callback to convert link parts into an HTML/etree element'],
+            'namespace': ['aa', 'Default namespace'],
+        }
+        super(SemanticWikiLinkExtension, self).__init__(*args, **kwargs)
+
+    def extendMarkdown(self, md, md_globals):
+        self.md = md
+
+        # append to end of inline patterns
+        ext = SemanticWikiLinkPattern(self.config, md)
+        md.inlinePatterns.add('semanticwikilink', ext, '<not_strong')
+
+
+class SemanticWikiLinkPattern(markdown.inlinepatterns.Pattern):
+
+    def __init__(self, config, md=None):
+        markdown.inlinepatterns.Pattern.__init__(self, '', md)
+        self.compiled_re = re.compile(
+            '^(.*?)%s(.*?)$' % WIKILINK_RE, re.DOTALL | re.X)
+        self.config = config
+
+    def getCompiledRegExp(self):
+        return self.compiled_re
+
+    def handleMatch(self, m):
+        """Returns etree."""
+        d = m.groupdict()
+        fn = self.config['make_link'][0]
+        namespace = d.get('namespace') or self.config['namespace'][0]
+        rel = d.get('rel')
+
+        if rel:
+            rel = '%s:%s' % (namespace, d.get('rel'))
+
+        return fn(self.markdown, rel, d.get('target'), d.get('label'))
+
+
+def makeExtension(*args, **kwargs):
+    return SemanticWikiLinkExtension(*args, **kwargs)
+
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()

=== modified file 'pybb/models.py'
--- pybb/models.py	2016-12-13 18:28:51 +0000
+++ pybb/models.py	2017-02-24 20:42:44 +0000
@@ -188,7 +188,7 @@
             self.body_html = mypostmarkup.markup(self.body, auto_urls=False)
         elif self.markup == 'markdown':
             self.body_html = unicode(do_wl_markdown(
-                self.body, 'bleachit', wikiwords=False))
+                self.body, 'bleachit'))
         else:
             raise Exception('Invalid markup property: %s' % self.markup)
 

=== modified file 'pybb/views.py'
--- pybb/views.py	2016-12-13 18:28:51 +0000
+++ pybb/views.py	2017-02-24 20:42:44 +0000
@@ -356,7 +356,7 @@
     if markup == 'bbcode':
         html = mypostmarkup.markup(content, auto_urls=False)
     elif markup == 'markdown':
-        html = unicode(do_wl_markdown(content, 'bleachit', wikiwords=False))
+        html = unicode(do_wl_markdown(content, 'bleachit'))
 
     html = urlize(html)
     return {'content': html}

=== modified file 'templates/wiki/article_content.html'
--- templates/wiki/article_content.html	2016-06-15 19:20:24 +0000
+++ templates/wiki/article_content.html	2017-02-24 20:42:44 +0000
@@ -6,9 +6,9 @@
 {% load creole %}
 
 {% switch markup %}
-    {% case 'crl' %} {{ content|creole|wikiwords|safe }} {% endcase %}
-    {% case 'rst' %} {{ content|restructuredtext|wikiwords|safe }} {% endcase %}
+    {% case 'crl' %} {{ content|creole|safe }} {% endcase %}
+    {% case 'rst' %} {{ content|restructuredtext|safe }} {% endcase %}
     {% case 'mrk' %} {{ content|wl_markdown:"bleachit"}} {% endcase %}
-    {#{% case 'txl' %} {{ content|force_escape|restore_commandsymbols|textile|wikiwords }} {% endcase %}#}
-    {% case '' %} {{ content|force_escape|wikiwords|linebreaks|safe }} {% endcase %}
+    {#{% case 'txl' %} {{ content|force_escape|restore_commandsymbols|textile }} {% endcase %}#}
+    {% case '' %} {{ content|force_escape|linebreaks|safe }} {% endcase %}
 {% endswitch %}

=== modified file 'wiki/forms.py'
--- wiki/forms.py	2017-01-17 21:25:32 +0000
+++ wiki/forms.py	2017-02-24 20:42:44 +0000
@@ -7,7 +7,7 @@
 
 from wiki.models import Article
 from wiki.models import ChangeSet
-from wiki.templatetags.wiki_extras import WIKI_WORD_RE
+from settings import WIKI_WORD_RE
 
 wikiword_pattern = re.compile('^' + WIKI_WORD_RE + '$')
 

=== modified file 'wiki/templatetags/wiki_extras.py'
--- wiki/templatetags/wiki_extras.py	2016-12-13 18:28:51 +0000
+++ wiki/templatetags/wiki_extras.py	2017-02-24 20:42:44 +0000
@@ -6,38 +6,11 @@
 from django.utils.encoding import force_unicode
 from django.utils.safestring import mark_safe
 
-try:
-    WIKI_WORD_RE = settings.WIKI_WORD_RE
-except AttributeError:
-    WIKI_WORD_RE = r'(?:[A-Z]+[a-z]+){2,}'
-
-try:
-    WIKI_URL_RE = settings.WIKI_URL_RE
-except AttributeError:
-    WIKI_URL_RE = r'\w+'
-
-
-wikiwordfier = re.compile(r'(?<!!)\b(%s)\b' % WIKI_WORD_RE)
-#wikiwordfier = re.compile(r'\b(%s)\b' % WIKI_WORD)
 
 register = template.Library()
 
 
 @register.filter
-def wikiwords(s):
-    """Transform every WikiWord in a text into links.
-
-    WikiWord must match this regular expression:
-    '(?:[A-Z]+[a-z]+){2,}'
-
-    """
-    # @@@ TODO: absolute links
-    s = wikiwordfier.sub(r'<a href="/wiki/\1/">\1</a>', s)
-    return force_unicode(s)
-wikiwords.is_safe = True
-
-
-@register.filter
 def restore_commandsymbols(s):
     """We need to restore " " for textile to work properly."""
     s = s.replace('&quot;', '"')

=== modified file 'wiki/urls.py'
--- wiki/urls.py	2017-01-11 19:43:17 +0000
+++ wiki/urls.py	2017-02-24 20:42:44 +0000
@@ -3,7 +3,7 @@
 from django.conf.urls import *
 from django.http import HttpResponseRedirect
 from wiki import views, models
-from wiki.templatetags.wiki_extras import WIKI_URL_RE
+from settings import WIKI_URL_RE
 from django.views.generic import RedirectView
 from wiki.feeds import RssHistoryFeed, AtomHistoryFeed, RssArticleHistoryFeed, AtomArticleHistoryFeed
 

=== modified file 'wiki/views.py'
--- wiki/views.py	2017-01-23 13:01:31 +0000
+++ wiki/views.py	2017-02-24 20:42:44 +0000
@@ -17,6 +17,7 @@
 from wiki.utils import get_ct
 from django.contrib.auth.decorators import login_required
 from mainpage.templatetags.wl_markdown import do_wl_markdown
+from markdownextensions.semanticwikilinks.mdx_semanticwikilinks import WIKILINK_RE
 
 from wl_utils import get_real_ip
 import re
@@ -626,12 +627,8 @@
 
 
 def backlinks(request, title):
-    """Simple text search for links in other wiki articles pointing to the
+    """Search for links in other wiki articles pointing to the
     current article.
-
-    If we convert WikiWords to markdown wikilinks syntax, this view
-    should be changed to use '[[title]]' for searching.
-
     """
 
     # Find old title(s) of this article
@@ -642,24 +639,19 @@
         if cs.old_title and cs.old_title != title and cs.old_title not in old_titles:
             old_titles.append(cs.old_title)
 
-    # Differentiate between WikiWords and other
-    m = re.match(r"(!?)(\b[A-Z][a-z]+[A-Z]\w+\b)", title)
-    if m:
-        # title is a 'WikiWord' -> This catches also 'MingW' but we have no such title
-        search_title = re.compile(r"%s" % title)
-    else:
-        # Others must be written like links: '[Wiki Page](/wiki/Wiki Page)'
-        search_title = re.compile(r"\/%s\)" % title)
-    
+    search_title = [re.compile(r"\[\[\s*%s\s*\]\]" % title)]
+    search_title.append(re.compile(r"\/%s\)" % title))
+
     # Search for current and previous titles
     found_old_links = []
     found_links = []
     articles_all = Article.objects.all().exclude(title=title)
     for article in articles_all:
-        match = search_title.search(article.content)
-        if match:
-            found_links.append({'title': article.title})
-        
+        for regexp in search_title:
+            match = regexp.search(article.content)
+            if match:
+                found_links.append({'title': article.title})
+
         for old_title in old_titles:
             if old_title in article.content:
                 found_old_links.append({'old_title': old_title, 'title': article.title })


Follow ups