1. NikitaUtiu
  2. moin-2.0

Commits

Sam Toyer  committed 69cc30e

Modify view subitems index: smarter content type handling, icons

  • Participants
  • Parent commits 8f73b05
  • Branches default

Comments (0)

Files changed (4)

File MoinMoin/static/js/common.js

View file
         var match = ctype_regex.exec(meta_text);
         if (match) return match[1];
     }
-    return null;
+    // text/plain is the default value
+    return "text/plain";
 }
 
-function transcludeSubitem(subitem_name) {
+function transcludeSubitem(subitem_name, fullname) {
+    function moinwiki(subitem_name, fullname) {
+        return "{{/" + subitem_name.replace("{{", "\\}}") + "}} ";
+    }
+    function mediawiki(subitem_name, fullname) {
+        return "{{:" + fullname.replace("}}", "\\}}") + "}} ";
+    }
+    function rst(subitem_name, fullname) {
+        return "\n.. include:: " + subitem_name + "\n";
+    }
+    function docbook(subitem_name, fullname) {
+        return ""; //XXX: the docbook converter currently doesn't handle transclusion with <ref> tags
+    }
+    var transclude_formats = {
+        "text/x.moin.wiki" : moinwiki,
+        "text/x.moin.creole" : moinwiki,
+        "text/x-mediawiki" : mediawiki,
+        "text/x-rst" : rst,
+        "application/docbook+xml" : docbook,
+        "text/plain" : function(x){return x + " ";},
+    }
+    var ctype = guessContentType();
     var input_element = $("#f_data_text");
-    input_element.val(input_element.val() + " {{/" + subitem_name + "}}");
+    var ctype_format = transclude_formats[ctype];
+    if (!ctype_format) ctype_format = transclude_formats["text/plain"];
+    input_element.val(input_element.val() + ctype_format(subitem_name, fullname));
 }
 
-function linkSubitem(subitem_name) {
+function linkSubitem(subitem_name, fullname) {
+    function moinwiki(subitem_name, fullname) {
+        return "[[/" + subitem_name.replace("]", "\\]") + "]] ";
+    }
+    function mediawiki(subitem_name, fullname) {
+        return "[[" + fullname.replace("]", "\\]") + "|" + subitem_name.replace("]", "\\]") + "]] ";
+    }
+    function rst(subitem_name, fullname) {
+        return "`" + subitem_name.replace(">", "\\>").replace("`", "\\`") + " <" + fullname.replace(">", "\\>") + ">`_ ";
+    }
+    function docbook(subitem_name, fullname) {
+        return '<ulink url="/' + fullname.replace('"', '\\"') + '">' + subitem_name + "</ulink>";;
+    }
+    var link_formats = {
+        "text/x.moin.wiki" : moinwiki,
+        "text/x.moin.creole" : moinwiki,
+        "text/x-mediawiki" : mediawiki,
+        "text/x-rst" : rst,
+        "application/docbook+xml" : docbook,
+        "text/plain" : function(x){return x + " ";},
+    }
+    var ctype = guessContentType();
     var input_element = $("#f_data_text");
-    input_element.val(input_element.val() + "[[/" + subitem_name + "]]");
+    var ctype_format = link_formats[ctype];
+    if (!ctype_format) ctype_format = link_formats["text/plain"];
+    input_element.val(input_element.val() + ctype_format(subitem_name, fullname));
 }

File MoinMoin/templates/modify_text.html

View file
 {% import "utils.html" as utils %}
 
 {% set subitems = theme_supp.subitem_index(item_name) %}
-{% if subitems %}
-    {% block subitem_navigation %}
+{% block subitem_navigation %}
+    {% if subitems %}
         {% call(fullname, shortname, contenttype, has_children) utils.render_subitem_navigation(subitems) %}
-            {# XXX: The replace filter is used to prevent XSS attacks
-                This needs security review, it could still be vulnerable #}
-            <a href="#" onclick="linkSubitem('{{ shortname|replace("\\", "\\\\")|replace("'", "\\'") }}')" title="{{ _('Link to Subitem') }}">
-                {{ _('Link') }}
-            </a>
-            <a href="#" onclick="transcludeSubitem('{{ shortname|replace("\\", "\\\\")|replace("'", "\\'") }}')" title="{{ _('Transclude Subitem') }}">
-                {{ _('Transclude') }}
-            </a>
+            <button class="link-action" onclick="linkSubitem('{{ shortname|js_string_escape }}', '{{ fullname|js_string_escape }}')" title="{{ _('Link to Subitem') }}" value="{{ _('Link to Subitem') }}" /></button>
+            <button class="transclude-action" onclick="transcludeSubitem('{{ shortname|js_string_escape }}', '{{ fullname|js_string_escape }}')" title="{{ _('Transclude Subitem') }}" value="{{ _('Transclude') }}"></button>
         {% endcall %}
-    {% endblock %}
-{% endif %}
+    {% endif %}
+{% endblock %}
 
 {% block data_editor %}
 {{ gen.textarea(form['data_text'], lang=lang, dir=direction, rows=rows_data, cols=cols) }}

File MoinMoin/themes/__init__.py

View file
         result['email'] = email
     return result
 
+def js_string_escape(data):
+    """
+    Escape the given string so it is safe to use as a Javscript string
+
+    :param data: string to be escaped
+    :rtype: str
+    :returns: Javascript escaped version
+    """
+    return data.replace("\\", r"\\").replace("'", r"\'").replace('"', r'\"')
 
 def shorten_item_name(name, length=25):
     """
     app.jinja_env.filters['shorten_item_name'] = shorten_item_name
     app.jinja_env.filters['shorten_id'] = shorten_id
     app.jinja_env.filters['contenttype_to_class'] = contenttype_to_class
+    app.jinja_env.filters['js_string_escape'] = js_string_escape
     # please note that these filters are installed by flask-babel:
     # datetimeformat, dateformat, timeformat, timedeltaformat
 

File MoinMoin/themes/modernized/static/css/common.css

View file
 .moin-subitem-navigation li:hover { background: #4D7DA9; }
 .moin-subitem-navigation a { color: #0044B3; }
 .moin-subitem-navigation a:hover { text-decoration: underline; }
+.link-action,
+.transclude-action { border: hidden; text-indent: -9000%; padding: 0; margin: 0 -2px; vertical-align: middle;
+                height: 16px; width: 16px; overflow: hidden; cursor: pointer; }
+.moin-subitem-navigation .link-action { background: url(../img/moin-attach.png) no-repeat center center; }
+.moin-subitem-navigation .transclude-action { background: url(../img/moin-text.png) no-repeat center center; }
 
 /* moin-page moin-footer */
 #moin-footer { clear: both; margin: 0 0; }