Commits

Roger Haase committed 6f5477c Merge

merge

Comments (0)

Files changed (13)

MoinMoin/script/account/create.py

 from flaskext.script import Command, Option
 
 from MoinMoin import user
+from MoinMoin.app import before_wiki
 
 
 class Create_User(Command):
     )
 
     def run(self, name, aliasname, email, openid, password):
-        flaskg.unprotected_storage = app.storage
+        before_wiki()
         msg = user.create_user(username=name,
                                password=password,
                                email=email,

MoinMoin/script/account/disable.py

 from flaskext.script import Command, Option
 
 from MoinMoin import user
+from MoinMoin.app import before_wiki
 
 
 class Disable_User(Command):
     )
 
     def run(self, name, uid):
-        flaskg.unprotected_storage = app.unprotected_storage
         flags_given = name or uid
         if not flags_given:
             print 'incorrect number of arguments'
             import sys
             sys.exit()
 
+        before_wiki()
         if uid:
             u = user.User(uid)
         elif name:
             print 'This user "{0!r}" does not exists!'.format(u.name)
             return
 
-        print " {0:<20} {1:!r<25} {2:<35}".format(u.id, u.name, u.email),
+        print " {0:<20} {1:!r<25} {2:<35}".format(u.itemid, u.name, u.email),
         if not u.disabled: # only disable once
             u.disabled = 1
             u.name = u"{0}-{1}".format(u.name, u.id)

MoinMoin/script/account/resetpw.py

 from flaskext.script import Command, Option
 
 from MoinMoin import user
+from MoinMoin.app import before_wiki
 from MoinMoin.util import crypto
 
 
     )
 
     def run(self, name, uid, password):
-        flaskg.unprotected_storage = app.unprotected_storage
         flags_given = name or uid
         if not flags_given:
             print 'incorrect number of arguments'
             import sys
             sys.exit()
 
+        before_wiki()
         if uid:
             u = user.User(uid)
         elif name:

MoinMoin/script/maint/modified_systemitems.py

 
 from flask import current_app as app
 from flaskext.script import Command
+
 from MoinMoin.config import IS_SYSITEM, SYSITEM_VERSION
-from MoinMoin.storage.error import NoSuchRevisionError
 
 class Modified_SystemItems(Command):
     description = 'This command can be used to list system items that has been edited in this wiki.'
 
     def run(self):
-        storage = app.unprotected_storage
         edited_sys_items = []
-        for item in storage.iteritems():
-            try:
-                rev = item.get_revision(-1)
-            except NoSuchRevisionError:
-                continue
-            is_sysitem = rev.get(IS_SYSITEM, False)
+        for current_rev in app.storage.documents():
+            is_sysitem = current_rev.meta.get(IS_SYSITEM, False)
             if is_sysitem:
-                version = rev.get(SYSITEM_VERSION)
+                version = current_rev.meta.get(SYSITEM_VERSION)
                 if version is None:
                     # if we don't have the version, it was edited:
                     edited_sys_items.append(item.name)

MoinMoin/script/maint/reduce_revisions.py

 # Copyright: 2009 MoinMoin:ChristopherDenter
 # Copyright: 2011 MoinMoin:ReimarBauer
 # Copyright: 2011 MoinMoin:ThomasWaldmann
+# Copyright: 2012 MoinMoin:CheerXiao
 # License: GNU GPL v2 (or any later version), see LICENSE.txt for details.
 
 """
 from flask import current_app as app
 from flaskext.script import Command, Option
 
-from MoinMoin.config import NAME, NAME_EXACT
+from whoosh.query import Every
+
+from MoinMoin.config import NAME, NAME_EXACT, REVID
 
 
 class Reduce_Revisions(Command):
     )
 
     def run(self, query):
-        storage = app.unprotected_storage
         if query:
-            qp = storage.query_parser([NAME_EXACT, ])
-            q = qp.parse(query)
+            qp = app.storage.query_parser([NAME_EXACT, ])
+            q = qp.parse(query_text)
         else:
             q = Every()
-        results = storage.search(q, limit=None)
-        for result in results:
-            item_name = result[NAME]
-            item = storage.get_item(item_name)
-            current_revno = item.next_revno - 1
-            for revno in item.list_revisions():
-                if revno < current_revno:
-                    rev = item.get_revision(revno)
-                    print "Destroying {0!r} revision {1}.".format(item_name, revno)
-                    rev.destroy()
+
+        for current_rev in app.storage.search(q, limit=None):
+            current_name = current_rev.meta[NAME]
+            current_revid = current_rev.meta[REVID]
+            print "Destroying historical revisions of {0!r}:".format(current_name)
+            has_historical_revision = False
+            for rev in current_rev.item.iter_revs():
+                revid = rev.meta[REVID]
+                if revid == current_revid:
+                    continue
+                has_historical_revision = True
+                name = rev.meta[NAME]
+                if name == current_name:
+                    print "    Destroying revision {0}".format(revid)
+                else:
+                    print "    Destroying revision {0} (named {1!r})".format(revid, name)
+                current_rev.item.destroy_revision(revid)
+            if not has_historical_revision:
+                print "    (no historical revisions)"
 
         print "Finished reducing backend."

MoinMoin/script/maint/set_meta.py

 # Copyright: 2009 MoinMoin:ChristopherDenter
 # Copyright: 2011 MoinMoin:ReimarBauer
 # Copyright: 2011 MoinMoin:ThomasWaldmann
+# Copyright: 2012 MoinMoin:CheerXiao
 # License: GNU GPL v2 (or any later version), see LICENSE.txt for details.
 
 """
 
 
 from ast import literal_eval
-from shutil import copyfileobj
 
 from flask import current_app as app
-from flask import g as flaskg
 from flaskext.script import Command, Option
 
+from whoosh.query import Every
+
 from MoinMoin.config import NAME, NAME_EXACT
 from MoinMoin.script import fatal
-from MoinMoin.storage.error import NoSuchRevisionError
 
 
 class Set_Meta(Command):
     )
 
     def run(self, key, value, remove, query):
-        storage = app.unprotected_storage
-
         if not ((key and value) or (key and remove)) or (key and value and remove):
             fatal("You need to either specify a proper key/value pair or "
                   "only a key you want to delete (with -r set).")
 
+        if not remove:
+            try:
+                value = literal_eval(value)
+            except ValueError:
+                fatal("You need to specify a valid Python literal as the argument")
+
         if query:
-            qp = storage.query_parser([NAME_EXACT, ])
-            q = qp.parse(query)
+            qp = app.storage.query_parser([NAME_EXACT, ])
+            q = qp.parse(query_text)
         else:
             q = Every()
-        results = storage.search(q, limit=None)
-        for result in results:
-            item_name = result[NAME]
-            item = storage.get_item(item_name)
-            try:
-                last_rev = item.get_revision(-1)
-            except NoSuchRevisionError:
-                last_rev = None
 
-            next_rev = item.create_revision(item.next_revno)
-
-            if last_rev:
-                # Copy data.
-                copyfileobj(last_rev, next_rev)
-                # Copy metadata:
-                for k, v in last_rev.iteritems():
-                    if remove and k == key:
-                        continue
-                    next_rev[k] = v
-
-            if not remove:
-                # Set or overwrite given metadata key with text
-                next_rev[key] = literal_eval(value)
-                print "Processing {0!r}, setting {1}={2!r}.".format(item_name, key, value)
+        for current_rev in app.storage.search(q, limit=None):
+            name = current_rev.meta[NAME]
+            newmeta = dict(current_rev.meta)
+            if remove:
+                newmeta.pop(key)
+                print "Processing {0!r}, removing {1}.".format(name, key)
             else:
-                print "Processing {0!r}, removing {1}.".format(item_name, key)
-
-            item.commit()
+                newmeta[key] = value
+                print "Processing {0!r}, setting {1}={2!r}.".format(name, key, value)
+            current_rev.item.store_revision(newmeta, current_rev.data)

MoinMoin/templates/index.html

     <script src="{{ url_for('frontend.template', filename='index_action.js') }}"></script>
 {% endblock %}
 
+{% block action_bars_inner %}
+    <ul>
+        {% if index %}
+        <li class="action-bar">
+        <div class="moin-select-all">
+            <span class="moin-select-allitem allitem-toselect" title="{{ _("Select All") }}">{{ _("Select All") }}</span>
+        </div>
+        </li>
+        {% endif %}
+        <li class="action-bar">
+        <div class="moin-select-actions">
+            <div>
+                <span class="show-action">Actions</span>
+            </div>
+            <ul>
+                <li id="moin-create-newitem">{{ _("New item") }}</li>
+                {% if index %}
+                <li id="moin-download-trigger">{{ _("Download") }}</li>
+                <li class="moin-action-tab"
+                    id="moin-delete-trigger"
+                    data-actionurl="{{ url_for('frontend.ajaxdelete', item_name=item_name) }}">
+                    {{ _("Delete") }}
+                </li>
+                <li class="moin-action-tab"
+                    id="moin-destroy-trigger"
+                    data-actionurl="{{ url_for('frontend.ajaxdestroy', item_name=item_name) }}">
+                    {{ _("Destroy") }}
+                </li>
+                {% endif %}
+            </ul>
+        </div>
+        </li>
+        <li class="action-bar">
+        <div class="moin-contenttypes-wrapper">
+            <div class="ct-hide">{{ _("Filter by content type") }}</div>
+            {% set unknown_items_label = _("items having unknown mime types") %}
+            {{ gen.form.open(form, method="get", action=url_for('frontend.index', item_name=item_name)) }}
+            <ul>
+                <li>
+                    <a href="#" class="filter-toggle">&raquo; {{ _("Toggle") }}</a>
+                    <a href="#" class="filter-more">&raquo; {{ _("More") }}</a>
+                </li>
+                {{ forms.render(form['contenttype']) }}
+            </ul>
+            {{ forms.render(form['submit']) }}
+            {{ gen.form.close() }}
+        </div>
+        </li>
+    </ul>
+{% endblock %}
+
+{% block action_bars %}
+    <div class="moin-align-right">
+        {{ self.action_bars_inner() }}
+    </div>
+{% endblock %}
+
 {% block content %}
     <div class="moin-index-message"><span></span></div>
-    <div class="moin-align-right">
-        <ul>
-            {% if index %}
-            <li class="action-bar">
-            <div class="moin-select-all">
-                <span class="moin-select-allitem allitem-toselect" title="{{ _("Select All") }}">{{ _("Select All") }}</span>
-            </div>
-            </li>
-            {% endif %}
-            <li class="action-bar">
-            <div class="moin-select-actions">
-                <div>
-                    <span class="show-action">Actions</span>
-                </div>
-                <ul>
-                    <li id="moin-create-newitem">{{ _("New item") }}</li>
-                    {% if index %}
-                    <li id="moin-download-trigger">{{ _("Download") }}</li>
-                    <li class="moin-action-tab"
-                        id="moin-delete-trigger"
-                        data-actionurl="{{ url_for('frontend.ajaxdelete', item_name=item_name) }}">
-                        {{ _("Delete") }}
-                    </li>
-                    <li class="moin-action-tab"
-                        id="moin-destroy-trigger"
-                        data-actionurl="{{ url_for('frontend.ajaxdestroy', item_name=item_name) }}">
-                        {{ _("Destroy") }}
-                    </li>
-                    {% endif %}
-                </ul>
-            </div>
-            </li>
-            <li class="action-bar">
-            <div class="moin-contenttypes-wrapper">
-                <div class="ct-hide">{{ _("Filter by content type") }}</div>
-                {% set unknown_items_label = _("items having unknown mime types") %}
-                {{ gen.form.open(form, method="get", action=url_for('frontend.index', item_name=item_name)) }}
-                <ul>
-                    <li>
-                        <a href="#" class="filter-toggle">&raquo; {{ _("Toggle") }}</a>
-                        <a href="#" class="filter-more">&raquo; {{ _("More") }}</a>
-                    </li>
-                    {{ forms.render(form['contenttype']) }}
-                </ul>
-                {{ forms.render(form['submit']) }}
-                {{ gen.form.close() }}
-            </div>
-            </li>
-        </ul>
-    </div>
+    {{ self.action_bars() }}
     <div>
     {% if item_name: %}
         <h1>{{ title }}</h1>
     <div id="popup">
         <div id="popup-for-action" class="popup-container">
             <div class="popup-header">
-                <div class="popup-closer popup-cancel" title="{{ _("Close") }}">x</div>
+                <input type="button" class="popup-closer popup-cancel" value="{{ _("X") }}" title="{{ _("Close") }}"/>
                 <span>{{ _("Please provide comment for this action") }}</span>
             </div>
             <div class="popup-body">
         </div>
         <div id="popup-for-newitem" class="popup-container">
             <div class="popup-header">
-                <div class="popup-closer popup-cancel" title="{{ _("Close") }}">x</div>
+                <input type="button" class="popup-closer popup-cancel" value="{{ _("X") }}" title="{{ _("Close") }}"/>
                 <span>{{ _("Create new item") }}</span>
             </div>
             <div class="popup-body">

MoinMoin/themes/foobar/templates/blog/layout.html

-{% extends theme("local.html") %}
+{% extends theme("layout.html") %}
 {% import theme("blog/utils.html") as blog_utils %}
 
 {% if blog_item %}
     {% endblock %}
 {% endblock %}
 
-{% block local %}
+{% block local_panel  %}
     <ul>
         {% if blog_name and supertags %}
         <li>

MoinMoin/themes/foobar/templates/index.html

-{% extends theme("local.html") %}
-{% import "forms.html" as forms with context %}
-{% block head_scripts %}
-{{ super() }}
-    <script src="{{ url_for('frontend.template', filename='index_action.js') }}"></script>
+{% extends "index.html" %}
+
+{% block action_bars %}
 {% endblock %}
 
-{% block local %}
-    <ul>
-        {% if index %}
-        <li class="action-bar">
-        <div class="moin-select-all">
-            <span class="moin-select-allitem allitem-toselect" title="{{ _("Select All") }}">{{ _("Select All") }}</span>
-        </div>
-        </li>
-        {% endif %}
-        <li class="action-bar">
-        <div class="moin-select-actions">
-            <div>
-                <span>Actions</span>
-            </div>
-            <ul>
-                <li id="moin-create-newitem">{{ _("New item") }}</li>
-                {% if index %}
-                <li id="moin-download-trigger">{{ _("Download") }}</li>
-                <li class="moin-action-tab"
-                    id="moin-delete-trigger"
-                    data-actionurl="{{ url_for('frontend.ajaxdelete', item_name=item_name) }}">
-                    {{ _("Delete") }}
-                </li>
-                <li class="moin-action-tab"
-                    id="moin-destroy-trigger"
-                    data-actionurl="{{ url_for('frontend.ajaxdestroy', item_name=item_name) }}">
-                    {{ _("Destroy") }}
-                </li>
-                {% endif %}
-            </ul>
-        </div>
-        </li>
-        {% if index %}
-        <li class="action-bar">
-        <div class="moin-contenttypes-wrapper">
-            <div class="ct-hide">{{ _("Filter by type") }}</div>
-            {% set unknown_items_label = _("items having unknown mime types") %}
-            {{ gen.form.open(form, method="post", action=url_for('frontend.index', item_name=item_name)) }}
-            <ul>
-                <li>
-                    <a href="#" class="filter-toggle">&raquo; {{ _("Toggle") }}</a>
-                    <a href="#" class="filter-more">&raquo; {{ _("More") }}</a>
-                </li>
-                {% for e in [
-                    'markup_text_items',
-                    'other_text_items',
-                    'image_items',
-                    'audio_items',
-                    'video_items',
-                    'other_items',
-                    'unknown_items',
-                    ] %}
-                    <li>{{ forms.render(form[e]) }}</li>
-                {% endfor %}
-            </ul>
-            {{ forms.render(form['submit']) }}
-            {{ gen.form.close() }}
-        </div>
-        </li>
-        {% endif %}
-    </ul>
+{% block local_panel %}
+    {{ self.action_bars_inner() }}
 {% endblock %}
-
-{% block content %}
-    <div class="moin-index-message"><span></span></div>
-    <div>
-    {% if item_name: %}
-        <h1>{{ _("Index of subitems of '%(item_name)s'", item_name=item_name) }}</h1>
-        <div class="moin-index-path">
-            <a href="{{ url_for('frontend.index') }}" title="{{ _("Global Index") }}">{{ ("..") }}</a>
-            <span class="moin-path-separator">{{ ("/") }}</span>
-            {% for i in range(0, item_names|count) %}
-                {% set fullname = item_names[:i+1]|join('/') %}
-                {% set relname = item_names[i] %}
-                <a href="{{ url_for('frontend.index', item_name=fullname) }}" title="{{ relname }}">{{ relname }}</a>
-                <span class="moin-path-separator">{{ ("/") }}</span>
-            {% endfor %}
-        </div>
-    {% else %}
-    {% endif %}
-    </div>
-    <div class='moin-clr'></div>
-    <div id="moin-new-index" class="moin-item-index">
-        <h3 style="display: none;">{{ _("Recently uploaded items") }}</h3>
-        <div class="file_download_template" style="display: none;">
-            <a></a>
-        </div>
-    </div>
-    <div class="moin-index-separator"></div>
-    {% if index %}
-    <div id="moin-initials">
-        {% if not startswith %}
-            <a class="selected" href="{{ url_for('frontend.index', item_name=item_name) }}">{{ _("All") }}</a>
-        {% else %}
-            <a href="{{ url_for('frontend.index', item_name=item_name) }}">{{ _("All") }}</a>
-        {% endif %}
-        {% for initial in initials %}
-            {% if startswith == initial %}
-                <a class="selected" href="{{ url_for('frontend.index', item_name=item_name, startswith=initial) }}">{{ initial }}</a>
-            {% else %}
-                <a href="{{ url_for('frontend.index', item_name=item_name, startswith=initial) }}">{{ initial }}</a>
-            {% endif %}
-        {% endfor %}
-    </div>
-    <div class="moin-item-index">
-        {% set maxchars = 20 %}
-        {% for fullname, relname, contenttype, hassubitem in index %}
-            <div>
-                <span class="moin-select-item">&nbsp;</span>
-                {% set mimetype = "application/x.moin.download" %}
-                <a href="{{ url_for('.download_item', item_name=fullname, mimetype=mimetype) }}" class="moin-download-link">
-                </a>
-                <a href="{{ url_for('.show_item', item_name=fullname) }}"
-                   class="{{ contenttype|contenttype_to_class }} moin-item"
-                   title="{{ relname }}">
-                   {{ relname|truncate(maxchars, true, '..') }}
-                </a>
-                {% if hassubitem %}
-                    <a href="{{ url_for('frontend.index', item_name=fullname) }}"
-                       title="{{ _("More") }}"
-                       class="moin-more-index">&nbsp;
-                </a>
-                {% endif %}
-            </div>
-        {% endfor %}
-    </div>
-    <div class="moin-clr"></div>
-    {% endif %}
-    <div id="popup">
-        <div id="popup-for-action" class="popup-container">
-            <div class="popup-header">
-                <input type="button" class="popup-closer popup-cancel" value="{{ _("X") }}" title="{{ _("Close") }}"/>
-                <span>{{ _("Please provide comment for this action") }}</span>
-            </div>
-            <div class="popup-body">
-                <input type="text" class="popup-comment" placeholder="{{ _("Enter your comment") }}"/>
-                <input type="hidden" class="popup-action" value=""/>
-                <br/>
-                <input type="button" class="popup-submit" value="{{ _("Submit") }}"/>
-                <input type="button" class="popup-cancel" value="{{ _("Cancel") }}"/>
-            </div>
-        </div>
-        <div id="popup-for-newitem" class="popup-container">
-            <div class="popup-header">
-                <input type="button" class="popup-closer popup-cancel" value="{{ _("X") }}" title="{{ _("Close") }}"/>
-                <span>{{ _("Create new item") }}</span>
-            </div>
-            <div class="popup-body">
-                <form action={{ url_for('.ajaxmodify') }} method="post">
-                    <label for="moin-newitem">{{ _("Item name") }}</label>
-                    {% if item_name %}
-                        <input type="text" id="moin-newitem" name="newitem" placeholder="{{ _("Enter item name here") }}" value="{{ item_name }}/" required="required"/>
-                    {% else %}
-                        <input type="text" id="moin-newitem" name="newitem" placeholder="{{ _("Enter item name here") }}" required="required"/>
-                    {% endif %}
-                    <br/>
-                    <input type="submit" value="{{ _("Create") }}"/>
-                    <input type="button" class="popup-cancel" value="{{ _("Cancel") }}"/>
-                </form>
-            </div>
-        </div>
-    </div>
-
-    <div id="moin-upload-cont">
-    {% set submit_url = url_for('.jfu_server', item_name=item_name) %}
-    {{ forms.render_file_uploader(submit_url) }}
-    </div>
-    <span class="moin-drag">{{ _("(Drag and drop multiple files to this white area to upload them.)") }}</span>
-    <script src="{{ url_for('static', filename='js/jfu.js') }}"></script>
-    <div id="lightbox">&nbsp;</div>
-{% endblock %}

MoinMoin/themes/foobar/templates/layout.html

-{% import "forms.html" as forms %}
+{# If you want itemviews in your template, extend from show.html, not from here. #}
 {% extends theme("base.html") %}
 
+{% import "forms.html" as forms %}
+{% import "utils.html" as utils %}
+{% import "itemviews.html" as itemviews with context %}
 {% import theme("snippets.html") as snippets with context %}
+
 {% set logo = snippets.logo() %}
 {% set footer_logos = snippets.creditlogos() %}
 {% set footer_items = '' %}
 </div>
 
 {% block content_container %}
-    <div id="moin-content-no-panel" lang="{{ theme_supp.content_lang }}" dir="{{ theme_supp.content_dir }}">
-    {% block content %}
-    {% endblock %}
+    {% set content_id = self.local_panel and 'moin-content' or 'moin-content-no-panel' %}
+    <div id="{{ content_id }}" lang="{{ theme_supp.content_lang }}" dir="{{ theme_supp.content_dir }}">
+        {% block content %}
+            {# All content templates should implement this block. #}
+        {% endblock %}
     </div>
+
+    {% if self.local_panel %}
+        <div id="moin-local-panel">
+            {{ self.local_panel() }}
+        </div>
+    {% endif %}
 {% endblock %}
 </div>
 

MoinMoin/themes/foobar/templates/local.html

-{% extends theme("layout.html") %}
-{% import "utils.html" as utils %}
-{% import "itemviews.html" as itemviews with context %}
-
-{% block content_container %}
-<div id="moin-content" lang="{{ theme_supp.content_lang }}" dir="{{ theme_supp.content_dir }}">
-    {% block item -%}
-        {# If you want itemviews in your template, extend from show.html, not from here. #}
-        {% block content %}
-            {# All content templates should have implement this block. #}
-        {% endblock %}
-    {%- endblock %}
-</div>
-
-<div id="moin-local-panel">
-{% block local %}
-<ul>
-    <li class="panel">Views
-        {{ itemviews }}
-    </li>
-    {% if rev %}
-    <li id="moin-metadata">Metadata
-        <ul>
-            <li>{{ _("Revision:") }} {{rev.revid | shorten_id}}</li>
-            <li>({{ rev.meta['mtime']|datetimeformat }})</li>
-            <li>{{ _("By:") }} {{ utils.editor_info(rev.meta) }}</li>
-            <li>{{ _("Size:") }} {{ rev.meta['size'] }}</li>
-            <li>{{ _("Type:") }} {{ rev.meta['contenttype'] }}</li>
-            {% if rev.meta.tags %}
-            <li>
-            {{ _("Tags:") }}
-            {% for tag in rev.meta.tags -%}
-            <a href="{{ url_for('frontend.tagged_items', tag=tag) }}">{{ tag }}</a>{% if not loop.last %}, {% endif %}
-            {%- endfor -%}
-            </li>
-            {% endif %}
-        </ul>
-    </li>
-    {% endif %}
-    <li>
-        {% block subitem_navigation %}
-        {{ utils.render_subitem_navigation(item_name, False) }}
-        {% endblock %}
-    </li>
-</ul>
-{% endblock %}
-</div>
-{% endblock %}

MoinMoin/themes/foobar/templates/show.html

-{% extends theme("local.html") %}
+{% extends theme("layout.html") %}
 
 {% block head_links %}
     {{ super() }}
     {% endblock %}
 {% endblock %}
 
+{% block local_panel %}
+    <ul>
+        <li class="panel">Views
+            {{ itemviews }}
+        </li>
+        {% if rev %}
+        <li id="moin-metadata">Metadata
+            <ul>
+                <li>{{ _("Revision:") }} {{rev.revid | shorten_id}}</li>
+                <li>({{ rev.meta['mtime']|datetimeformat }})</li>
+                <li>{{ _("By:") }} {{ utils.editor_info(rev.meta) }}</li>
+                <li>{{ _("Size:") }} {{ rev.meta['size'] }}</li>
+                <li>{{ _("Type:") }} {{ rev.meta['contenttype'] }}</li>
+                {% if rev.meta.tags %}
+                <li>
+                {{ _("Tags:") }}
+                {% for tag in rev.meta.tags -%}
+                <a href="{{ url_for('frontend.tagged_items', tag=tag) }}">{{ tag }}</a>{% if not loop.last %}, {% endif %}
+                {%- endfor -%}
+                </li>
+                {% endif %}
+            </ul>
+        </li>
+        {% endif %}
+        <li>
+            {% block subitem_navigation %}
+            {{ utils.render_subitem_navigation(item_name, False) }}
+            {% endblock %}
+        </li>
+    </ul>
+{% endblock %}
+
 {% block options_for_javascript %}
 {%- if item_name and user.edit_on_doubleclick and user.may.write(item_name) -%}
     <br id="moin-edit-on-doubleclick" />

MoinMoin/themes/foobar/templates/usersettings.html

-{% extends theme("local.html") %}
+{% extends theme("layout.html") %}
 {% import "usersettings_forms.html" as user_forms %}
 
-{% block local %}
+{% block local_panel %}
 <ul id="moin-usersetting-title">
 <li class="moin-tab-title"><a href="#moin-personal">{{ _("Personal Settings") }}</a></li>
 <li class="moin-tab-title"><a href="#moin-password">{{ _("Change Password") }}</a></li>