changeset 2958:6dd6f10636b3

update configuration rst docs and supporting files, fixes #406
author RogerHaase <haaserd@gmail.com>
date Wed, 17 Jun 2015 15:36:46 -0700
parents e035a2b2f244
children 0ac2c8e85ed3
files .hgignore MoinMoin/templates/snippets.html docs/admin/configure.rst docs/devel/development.rst wiki_local/README.txt wikiconfig.py
diffstat 6 files changed, 337 insertions(+), 195 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Jun 17 14:52:23 2015 -0700
+++ b/.hgignore	Wed Jun 17 15:36:46 2015 -0700
@@ -8,6 +8,7 @@
 ^moin.egg-info/
 ^MoinMoin/_tests/wiki/data/cache/
 ^wiki/
+^wiki_local/
 ^instance/
 ^wikiconfig_.+\.py
 ^MoinMoin/translations/.*/LC_MESSAGES/messages.mo$
--- a/MoinMoin/templates/snippets.html	Wed Jun 17 14:52:23 2015 -0700
+++ b/MoinMoin/templates/snippets.html	Wed Jun 17 15:36:46 2015 -0700
@@ -89,8 +89,10 @@
 
 {# Additional Stylesheets (after theme css, before user css #}
 {% macro stylesheets() -%}
+    {# <link media="all" rel="stylesheet" href="{{ url_for('serve.files', name='wiki_local', filename='MyStyleSheet.css') }}"> #}
 {%- endmacro %}
 
 {# Additional Javascript #}
 {% macro scripts() -%}
+    {# <script type="text/javascript" src="{{ url_for('serve.files', name='wiki_local', filename='MyScript.js') }}"></script> #}
 {%- endmacro %}
--- a/docs/admin/configure.rst	Wed Jun 17 14:52:23 2015 -0700
+++ b/docs/admin/configure.rst	Wed Jun 17 15:36:46 2015 -0700
@@ -51,6 +51,26 @@
 and using something else would usually mean much more work when developing new
 functionality.
 
+Directory Structure
+===================
+
+Shown below are parts of the directory structure after cloning moin or unpacking a release.
+The default uses the OS file system for storage of wiki data and indexes.
+The directories and files shown are referenced in this section of documentation related to configuration::
+
+    moin-2.0/                     # clone root or unpack directory
+        contrib/
+            interwiki/
+                intermap.txt      # interwiki map: created by cloning or unpacking, updated by "./m interwiki"
+        docs/
+            _build/
+                html/             # local copy of moin documentation, created by running "./m docs" command
+        MoinMoin/                 # large directory containing moin application code
+        wiki/                     # the wiki instance; created by running "./m sample" or "./m new-wiki" commands
+            data/                 # wiki data is stored here
+            index/                # wiki indexes are stored here
+        wiki_local/               # a convenient location to store custom CSS, Javascript, templates, logos, etc.
+        wikiconfig.py             # main configuration file, modify this to add or change features
 
 wikiconfig.py Layout
 ====================
@@ -103,35 +123,44 @@
 User Interface Customization
 ============================
 
+Customizing a wiki usually requires adding a few files that contain custom templates,
+logo image, CSS, etc. To accomplish this, a directory named "wiki_local"
+is provided. One advantage of using this directory and following the examples below
+is that MoinMoin will serve the files.
+
+If desired, the name of this directory may be changed or a separate subdirectory
+for template files may be created by editing
+the wikiconfig file and changing the line that defines `template_dirs`::
+
+    template_dirs = [os.path.join(wikiconfig_dir, 'wiki_local'), ]
+
 Using a custom snippets.html template
 -------------------------------------
 The user interface or html elements that often need customization are
 defined as macros in the template file `snippets.html`.
 
-If you would like to customize some parts, you have to make a copy of the built-in
-`MoinMoin/templates/snippets.html` and configure moin so it will use your
-copy instead of the built-in one.
-
-This is done by giving a list of template directories where moin itself will
-look first::
-
-    template_dirs = ['path/to/my/templates', ]
+If you would like to customize some parts, you have to copy the built-in
+`MoinMoin/templates/snippets.html` file and save it in the `wiki_local` directory so moin
+can use your copy instead of the built-in one.
 
 To customize something, you usually have to insert your code between the
 `{% macro ... %}` and `{% endmacro %}` lines, see below for more details.
 
 Logo
 ~~~~
-To replace the default MoinMoin logo with your own logo, apply the following code::
+To replace the default MoinMoin logo with your own logo, copy your logo to
+`wiki_local` and change the logo macro to something like::
 
     {% macro logo() -%}
-    <img src="http://wiki.example.org/logos/my_logo.png" id="moin-img-logo" alt="Example Logo">
+        <img src="{{ url_for('wiki_local', filename='MyLogo.png') }}" id="moin-img-logo" alt="Logo">
     {%- endmacro %}
 
 This is recommended to allow your users to immediately recognize which wiki site they are currently on.
 
-You can even use some simple text or even nothing at all for the logo, it is not
-required to be an image.
+You can use text or even nothing at all for the logo, it is not
+required to be an image::
+
+        <span style="font-size: 50px; color: red;">My Wiki</span>
 
 Make sure the dimensions of your logo image or text fit into the layout of
 the theme(s) your wiki users are using.
@@ -212,7 +241,7 @@
 
     {# Additional Javascript #}
     {% macro scripts() -%}
-    <script type="text/javascript" src="http://example.org/cool.js"></script>
+    <script type="text/javascript" src="{{ url_for('serve.files', name='wiki_local', filename='MyScript.js') }}"></script>
     {% endmacro %}
 
 Adding CSS
@@ -222,9 +251,9 @@
 
     {# Additional Stylesheets (after theme css, before user css #}
     {% macro stylesheets() -%}
-        <link media="screen" href="http://wiki.example.org/static/company.css" title="Company CSS" rel="stylesheet" />
-        <link media="screen" href="http://wiki.example.org/static/red.css" title="Red Style" rel="alternate stylesheet" />
-        <link media="screen" href="http://wiki.example.org/static/green.css" title="Green Style" rel="alternate stylesheet" />
+        <link media="screen" href="{{ url_for('serve.files', name='wiki_local', filename='company.css') }}" title="Company CSS" rel="stylesheet" />
+        <link media="screen" href="{{ url_for('serve.files', name='wiki_local', filename='red.css') }}" title="Red Style" rel="alternate stylesheet" />
+        <link media="screen" href="{{ url_for('serve.files', name='wiki_local', filename='green.css') }}" title="Green Style" rel="alternate stylesheet" />
     {%- endmacro %}
 
 You can either add some normal css stylesheet or add a choice of alternate
@@ -245,7 +274,7 @@
 Displaying user avatars
 ~~~~~~~~~~~~~~~~~~~~~~~
 Optionally, moin can display avatar images for the users, using gravatar.com
-service. To enable it, use::
+service. To enable it, add or uncomment this line in wikiconfig::
 
     user_use_gravatar = True
 
@@ -276,15 +305,18 @@
 * `jquery_file_upload <http://pypi.python.org/pypi/XStatic-jQuery-File-Upload>`_
   loaded in the template file of index view. It allows to upload many files at once.
 
-* `JSON-js <http://pypi.python.org/pypi/XStatic-JSON-js>`_
-  JSON encoders/decoders in JavaScript.
+* `bootstrap <https://pypi.python.org/pypi/XStatic-Bootstrap>`_
+  used by the basic theme.
+
+* `font_awesome <https://pypi.python.org/pypi/XStatic-Font-Awesome>`_
+  provides text icons.
 
 * `ckeditor <http://pypi.python.org/pypi/XStatic-CKEditor>`_
   used in template file modify_text_html. A WYSIWYG editor similar to word processing
   desktop editing applications.
 
-* `svgweb <http://pypi.python.org/pypi/XStatic-svgweb>`_
-  used at base.html for enabling SVG support on many browsers.
+* `autosize <https://pypi.python.org/pypi/XStatic-autosize>`_
+  used by basic theme to adjust textarea on modify view.
 
 * `svgedit_moin <http://pypi.python.org/pypi/XStatic-svg-edit-moin>`_
   is loaded at template modify_svg-edit. It is a fast, web-based, Javascript-driven
@@ -297,18 +329,32 @@
   a Java applet loaded from template file of modify_anywikidraw. It can be used for
   editing drawings and diagrams on items.
 
+* `jquery_tablesorter <https://pypi.python.org/pypi/XStatic-JQuery.TableSorter/2.14.5.1>`_
+  used to provide client side table sorting.
+
+* `pygments <https://pypi.python.org/pypi/XStatic-Pygments>`_
+  used to style code fragments.
+
 
 These packages are imported in wikiconfig by::
 
     from xstatic.main import XStatic
-    mod_names = ['jquery', 'jquery_file_upload', 'ckeditor',
-                 'svgweb', 'svgedit_moin', 'twikidraw_moin',
-                 'anywikidraw', ]
+    # names below must be package names
+    mod_names = [
+        'jquery', 'jquery_file_upload',
+        'bootstrap',
+        'font_awesome',
+        'ckeditor',
+        'autosize',
+        'svgedit_moin', 'twikidraw_moin', 'anywikidraw',
+        'jquery_tablesorter',
+        'pygments',
+    ]
     pkg = __import__('xstatic.pkg', fromlist=mod_names)
     for mod_name in mod_names:
         mod = getattr(pkg, mod_name)
         xs = XStatic(mod, root_url='/static', provider='local', protocol='http')
-        serve_files.update([(xs.name, xs.base_dir)])
+        serve_files[xs.name] = xs.base_dir
 
 In a template file you access the files of such a package by its module name::
 
@@ -319,11 +365,14 @@
 
 The following example shows how you can enable the additional package
 `XStatic-MathJax <http://pypi.python.org/pypi/XStatic-MathJax>`_ which is
-used for mathml or latex formulas in items content.
+used for mathml or latex formulas in an item's content.
 
-Just *pip install xstatic-mathjax* add the name 'mathjax' to mod_names in wikiconfig
-and add the required fragment in base.html::
+* activate the virtual environment and do *pip install xstatic-mathjax*
+* add the name 'mathjax' to to the list of mod_names in wikiconfig
+* copy /templates/snippets.html to the wiki_local directory
+* modify the snippets.html copy by adding the required fragment to the scripts macro::
 
+    {% macro scripts() -%}
     <script type="text/x-mathjax-config">
     MathJax.Hub.Config({
         extensions: ["tex2jax.js"],
@@ -332,7 +381,7 @@
     });
     </script>
     <script src="{{ url_for('serve.files', name='mathjax', filename='MathJax.js') }}"></script>
-
+    {%- endmacro %}
 
 Custom Themes
 -------------
@@ -342,10 +391,17 @@
 Caution: developing your own theme means you also have to maintain and update it,
 which normally requires a long-term effort.
 
-.. todo::
+To add a new theme, add a new directory under MoinMoin/themes/ where the directory
+name is the name of your theme. Note the directory structure under the basic and
+modernized themes. At a minimum, a new CSS file will be required; add a file named
+theme.css in the MoinMoin/themes/MyTheme/static/css/ directory.
 
-   Add more details about custom themes
+To change the layout of the theme header, sidebar and footer, create a templates/ directory and
+copy and modify the files layout.html and show.html from either MoinMoin/templates/ or basic/templates.
 
+For many themes, modifying the three files noted above will be sufficient. If changes to
+views are required, copy additional template files. If there is a requirement to change
+the MoinMoin base code, please consider submitting a patch.
 
 Authentication
 ==============
@@ -680,39 +736,38 @@
 Authorization
 =============
 Moin uses Access Control Lists (ACLs) to specify who is authorized to perform
-a given action.
-
-Please note that wikis usually make much use of so-called *soft security*,
-which means that they are rather open and give freedom to users, while at the same time
-providing the means to revert any damage that may have been caused.
-
-*Hard security* means that one would lock items, etc. so that no damage can possibly be done.
+a given action. ACLs enable wiki administrators and possibly users to choose
+between *soft security* and *hard security*.
 
-Moin's default configuration tries to give a sane compromise of both soft
-and hard security. However, you may need different settings depending on the situation that the wiki
-admin, wiki owner or wiki community will have to deal with.
-
-So keep in mind:
+* if your wiki is rather open (soft security), you make it easy to contribute, e.g. a
+  user who is not a regular user of your wiki could fix some typos he has just
+  found. However, a hostile user or bot could easily add spam into your wiki.
+  In this case, an active user community can quickly detect and remove the spam.
+* if your wiki is rather closed (hard security), e.g. you require every user to first apply for an
+  account and to log in before being able to do changes, you will rarely get
+  contributions from casual users and possibly discourage contributions from
+  members of your community. But, getting spam is then less likely.
+* ACLs provide the means of using both methods. Key wiki items that are frequently viewed
+  and infrequently changed may be updated only by selected users while other items that
+  are frequently changed may be updated by any user.
 
-* if your wiki is rather open, you might make it easy to contribute, e.g. a
-  user who is not a regular user of your wiki could fix some typos he has just
-  found. However, a hostile user or bot might also put some spam into your wiki
-  with the ability to be able to revoke the spam later.
-* if your wiki is rather closed, e.g. you require every user to first apply for an
-  account and to log in before being able to do changes, you will rarely get
-  contributions from casual users and maybe also less from members of your
-  community. But, getting spam is then less likely.
+Moin's default configuration makes use of *soft security* which is in use by many wikis to
+maximize collaboration among its user community.
+
+Wiki administrators may harden security by reconfiguring the default ACLs. Later, as wiki
+items are created and updated, the default configuration may be overridden by setting
+an ACL on the item.
+
+Hardening security implies that there will be a registration and login process that enables
+individual users to gain privileges. While wikis with a small user community may function
+with ACLs specifying only usernames, larger wikis will make use of ACLs that reference
+groups or lists of usernames. The definitions of built-in groups and creation of groups are
+discussed below under the headings `ACLs - special groups` and `Groups`.
 
 
 ACL for functions
 -----------------
-This ACL controls access to some specific functions / views of moin::
-
-    # the default value of acl_rights_functions for information, you usually do not have to change it:
-    #acl_rights_functions = ['superuser', 'notextcha', ]
-    acl_functions = u'+YourName:superuser TrustedEditorGroup:notextcha'
-
-Supported capabilities (rights):
+Moin has two built in functions that are protected by ACLs: superuser and notextcha:
 
 * superuser - used for miscellaneous administrative functions. Give this only to
   highly trusted people
@@ -720,23 +775,24 @@
   won't get questions to answer. Give this to known and trusted users who
   regularly edit in your wiki.
 
+Example::
+
+    acl_functions = u'YourName:superuser TrustedEditorGroup:notextcha'
+
 ACLs for contents
 -----------------
-These ACLs control access to contents stored in the wiki, they are configured
-per storage backend (see storage backend docs) and optionally in the metadata of wiki
-items::
+This type of ACL controls access to content stored in the wiki. Wiki items
+may have ACLs defined in their metadata. Within wikiconfig, ACLs are specified
+per namespace and storage backend (see storage backend docs for details). The
+example below shows an entry for the default namespace::
 
-    # the default value of acl_rights_contents for information, you usually do not have to change it:
-    #acl_rights_contents = ['read', 'write', 'create', 'destroy', 'admin', ]
-    ... backend configuration ...
-    ... before=u'YourName:read,write,create,destroy,admin',
-    ... default=u'All:read,write,create',
-    ... after=u'',
-    ... hierarchic=False,
+    default_acl=dict(before=u'SuperUser:read,write,create,destroy,admin',
+                     default=u'TrustedEditorGroup:read,write,create,destroy,admin Known:read,write,create',
+                     after=u'All:read',
+                     hierarchic=False, ),
 
-Usually, you have a `before`, `on item` or `default` and a `after` ACL which
-are processed exactly in this order. The `default` ACL is only used if no ACL
-is specified in the metadata of the item in question.
+As shown above, `before`, `default` and  `after` ACLs are specified. The `default` ACL
+is only used if no ACL is specified in the metadata of the target item.
 
 .. digraph:: acl_order
 
@@ -744,13 +800,14 @@
    "before" -> "item acl from metadata (if specified)" -> "after";
    "before" -> "default (otherwise)"                   -> "after";
 
-How to use before/default/after:
+How to use before, default, and after:
 
 * `before` is usually used to force something, for example if you want to give some
-  wiki admin all permissions indiscriminately
-* `default` is the behavior if nothing special has been specified, ie no ACL in the
-  item's metadata
-* `after` is rarely used and when it is, it is used to "not forget something unless otherwise specified".
+  wiki admin all permissions indiscriminately; in the example above, no one can create an item
+  ACL rule locking out SuperUser's access
+* `default` is the behavior if no ACL was created in the item's metadata; above, only members of a trusted group can write ACL rules or delete items, and a user must be logged in (known) to write or create items
+* `after` is rarely used and when it is, it is used to "not forget something unless otherwise specified";
+  above, all users may read all items unless blocked (or given more privileges) by an ACL on the target item
 
 When configuring content ACLs, you can choose between standard (flat) ACL
 processing and hierarchic ACL processing. Hierarchic processing means that
@@ -772,7 +829,8 @@
 ACLs - special groups
 ---------------------
 In addition to the groups provided by the group backend(s), there are some
-special group names available within ACLs:
+special group names available within ACLs. These names are case-sensitive
+and must be capitalized as shown:
 
 * All - a virtual group containing every user
 * Known - a virtual group containing every logged-in user
@@ -794,7 +852,7 @@
 
 Example::
 
-    u"SuperMan:read,write,create,destroy,admin All:read,write"
+    u"SuperMan,WonderWoman:read,write,create,destroy,admin All:read,write"
 
 If "SuperMan" is currently logged in and moin processes this ACL, it will find
 a name match in the first entry. If moin wants to know whether he may destroy,
@@ -828,8 +886,6 @@
 
 * A right that is not explicitly given by an applicable ACL is denied.
 
-* For most ACLs there are built-in defaults which give some limited rights.
-
 ACLs - entry prefixes
 ---------------------
 To make the system more flexible, there are two ways to modify an ACL entry: prefixing it with a '+' or a '-'.
@@ -857,8 +913,8 @@
 
 If "Idiot" is currently logged in and moin wants to know whether he may write,
 it will find no match in the first entry, but the second entry will match. As
-the prefix is '-', the answer will be "no" and it will not even proceed and
-look at the third entry.
+the prefix is '-', the answer will be "no". Because a match has been made,
+the third entry is not processed.
 
 Notes:
 
@@ -916,6 +972,7 @@
 * you should at least give textchas for 'en' or for your language_default, if
   that is not 'en', as this will be used as fallback if MoinMoin does not find
   a textcha in the user's language
+* if a determined bot learns the answers, create new textchas
 
 In your wiki config, do something like this::
 
@@ -957,26 +1014,55 @@
 SECRET_KEY for all secrets it needs.
 
 
-Groups and Dicts
-================
-Moin can get group and dictionary information from some supported backends
-like the wiki configuration or wiki items.
+Groups
+======
 
-A group is a list of unicode names. It can be used for any application:
-one application is defining user groups for usage in ACLs.
+Group names can be used in place of usernames within ACLs.
+There are three types of groups: WikiGroups, ConfigGroups, and CompositeGroups.
+A group is a list of unicode names, where a name may be either a username or
+another group name.
 
-A dict is a mapping of unicode keys to unicode values. It can be used for any
-application. Currently, it is not used by moin itself.
+Use of groups will reduce the administrative effort required to maintain ACL rules,
+especially in wikis with a large community of users. Rather than change multiple
+ACL rules to reflect a new or departing member, a group may be updated. To achieve
+maximum benefit, some advance planning is required to determine the kind and names
+of groups suitable for your wiki.
+
+The wiki server must be restarted to reflect updates made to ConfigGroups
+and CompositeGroups.
+
+Names of WikiGroup items must end in "Group". There is no such requirement for the
+names of ConfigGroups or CompositeGroups.
 
 Group backend configuration
 ---------------------------
-The WikiGroups backend gets groups from wiki items and is used by default::
+
+The WikiGroups backend is enabled by default so there is no need to add the following to wikiconfig::
 
     def groups(self):
         from MoinMoin.datastruct import WikiGroups
         return WikiGroups()
 
-The ConfigGroups backend uses groups defined in the configuration file::
+To create a WikiGroup that can be used in an ACL rule:
+
+* Create a wiki item with a name ending in "Group" (the content of the item is not relevant)
+* Edit the metadata and add an entry for "usergroup" under the heading "Extra Metadata (JSON)"::
+
+    {
+      "itemid": "36b6cd973d7e4daa9cfa265dcf751e79",
+      "namespace": "",
+      "usergroup": [
+        "JaneDoe",
+        "JohnDoe"
+      ]
+    }
+
+* Use the new group name in one or more ACL rules.
+
+
+The ConfigGroups backend uses groups defined in the configuration file. Adding the
+following to wikiconfig creates an EditorGroup and an AdminGroup and prevents
+the use of any WikiGroups::
 
     def groups(self):
         from MoinMoin.datastruct import ConfigGroups
@@ -984,53 +1070,18 @@
                   u'AdminGroup': [u'Admin1', u'Admin2', u'John']}
         return ConfigGroups(groups)
 
-CompositeGroups can use, for the most part, any combination of backends. The
-following is an example of using the ConfigGroups and WikiGroups backends::
+CompositeGroups enable both ConfigGroups and WikiGroups to be used. The example
+below defines the same ConfigGroups used above and enables the use of WikiGroups.
+Note that order matters! Since ConfigGroups backend is first in the return tuple,
+the EditGroup and AdminGroup defined below will be used should there be WikiGroup
+items with the same names::
 
     def groups(self):
         from MoinMoin.datastruct import ConfigGroups, WikiGroups, CompositeGroups
         groups = {u'EditorGroup': [u'AdminGroup', u'John', u'JoeDoe', u'Editor1'],
                   u'AdminGroup': [u'Admin1', u'Admin2', u'John']}
-
-        # Here ConfigGroups and WikiGroups backends are used.
-        # Note that order matters! Since ConfigGroups backend is mentioned first
-        # EditorGroup will be retrieved from it, not from WikiGroups.
         return CompositeGroups(ConfigGroups(groups), WikiGroups())
 
-
-Dict backend configuration
---------------------------
-
-The WikiDicts backend gets dicts from wiki items and is used by default::
-
-    def dicts(self, request):
-        from MoinMoin.datastruct import WikiDicts
-        return WikiDicts(request)
-
-The ConfigDicts backend uses dicts defined in the configuration file::
-
-    def dicts(self, request):
-        from MoinMoin.datastruct import ConfigDicts
-        dicts = {u'OneDict': {u'first_key': u'first item',
-                              u'second_key': u'second item'},
-                 u'NumbersDict': {u'1': 'One',
-                                  u'2': 'Two'}}
-        return ConfigDicts(request, dicts)
-
-The CompositeDicts backend can use any combination of backends. The following
-is an example of using the ConfigDicts and WikiDicts backends::
-
-    def dicts(self, request):
-        from MoinMoin.datastruct import ConfigDicts, WikiDicts, CompositeDicts
-        dicts = {u'OneDict': {u'first_key': u'first item',
-                              u'second_key': u'second item'},
-                 u'NumbersDict': {u'1': 'One',
-                                  u'2': 'Two'}}
-        return CompositeDicts(request,
-                              ConfigDicts(request, dicts),
-                              WikiDicts(request))
-
-
 Storage
 =======
 MoinMoin supports storage backends as different ways of storing wiki items.
--- a/docs/devel/development.rst	Wed Jun 17 14:52:23 2015 -0700
+++ b/docs/devel/development.rst	Wed Jun 17 15:36:46 2015 -0700
@@ -130,11 +130,22 @@
 * if you want a graphical interface to Mercurial, install SourceTree (best for mac) or TortoiseHG (best for Windows)
 * join #moin-dev IRC channel; ask questions, learn what other developers are doing
 
+review configuration options
+----------------------------
+
+* review https://moin-20.readthedocs.org/en/latest/admin/configure.html
+* following the instructions in wikiconfig.py, create wikiconfig_local.py and wikiconfig_editme.py
+* configure options by editing wikiconfig_editme.py
+
+  * set superuser privileges on at least one username
+  * the default configuration options are commonly used, it is likely new bugs can be
+    found by testing different options
+
 find a task to work on
 ----------------------
 
 * look at the issue tracker to find a task you can solve
-* in case you want to work on some (non-trivial) new issue or idea that is
+* in case you find a new bug or want to work on some (non-trivial) new issue or idea that is
   not on the issue tracker, create an issue with a detailed description
 * discuss your chosen task with other developers on the #moin-dev IRC
   channel
@@ -183,7 +194,9 @@
 * look for poor variable names, spelling errors in comments, accidental addition
   or deletion of blank lines, complex code without comments, missing/extra spaces
 * fix everything you find before requesting feedback from others
-* run tests again "./m tests", check for trailing spaces, line endings "./m coding-std"
+* run tests again "./m tests"
+* check for trailing spaces, line endings, template indentation "./m coding-std"
+* if Javascript files were changed, run http://jslint.com/
 
 get feedback from other developers
 ----------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wiki_local/README.txt	Wed Jun 17 15:36:46 2015 -0700
@@ -0,0 +1,4 @@
+The directory containing this file is intended as a convenient place to store
+local customizations, such as logo images, templates, CSS, Javascript, etc.
+
+See the docs on installation and configuration for more information.
--- a/wikiconfig.py	Wed Jun 17 14:52:23 2015 -0700
+++ b/wikiconfig.py	Wed Jun 17 15:36:46 2015 -0700
@@ -1,64 +1,112 @@
 # -*- coding: utf-8 -*-
 """
-MoinMoin Wiki - Configuration
+MoinMoin Wiki Configuration - see https://moin-20.readthedocs.org/en/latest/admin/configure.html
 
-Developers can use this configuration to run moin right from their mercurial workdir.
+This configuration is designed to run moin from a workdir using
+the built-in server. Wiki admins who install moin via a mercurial repository rather
+than a release package may opt to follow the developer instructions below to
+reduce merge issues when pulling updates.
+
+
+DEVELOPERS! Do not add your configuration items here - you could accidentally
+commit them! Instead, follow these steps:
+
+(1) In this directory, create a wikiconfig_local.py file containing the following one line of code:
+
+from wikiconfig_editme import *  # enable auto reload when wikiconfig_editme.py changes
+
+(2) Create a second file named wikiconfig_editme.py with the following six lines of code:
+
+from wikiconfig import *
+class LocalConfig(Config):
+    configuration_item_1 = 'value1'  # overlay this with local customizations
+MOINCFG = LocalConfig
+SECRET_KEY = 'you need to change this so it is really secret'
+DEBUG = True
+
+(3) Overlay the 3rd line in wikiconfig_editme.py by copying any or all of the indented
+    lines from "class Config" below.
+
+(4) Customize wikiconfig_editme.py as needed. Not all customization options are included
+    here, read the docs for other options.
 """
 
 import os
 
-from MoinMoin.config.default import DefaultConfig
+from MoinMoin.config.default import DefaultConfig, _default_password_checker
 from MoinMoin.storage import create_simple_mapping
 from MoinMoin.util.interwiki import InterWikiMap
 
 
 class Config(DefaultConfig):
-    # Directory containing THIS wikiconfig:
-    wikiconfig_dir = os.path.abspath(os.path.dirname(__file__))
-    # We assume this structure for a simple "unpack and run" scenario:
-    # wikiconfig.py
-    # wiki/
-    #      data/
-    #      index/
-    # contrib/
-    #      interwiki/
-    #          intermap.txt
-    # If that's not true, feel free to adjust the pathes.
-    instance_dir = os.path.join(wikiconfig_dir, 'wiki')
-    data_dir = os.path.join(instance_dir, 'data')  # Note: this used to have a trailing / in the past
-    index_storage = 'FileStorage', (os.path.join(instance_dir, "index"), ), {}
 
-    # This provides a simple default setup for your backend configuration.
-    # 'stores:fs:...' indicates that you want to use the filesystem backend.
-    # Alternatively you can set up the mapping yourself (see HelpOnStorageConfiguration).
-    namespace_mapping, backend_mapping, acl_mapping = create_simple_mapping(
-        uri='stores:fs:{0}/%(backend)s/%(kind)s'.format(data_dir),
-        # XXX we use rather relaxed ACLs for the development wiki:
-        default_acl=dict(before=u'',
-                         default=u'All:read,write,create,destroy,admin',
-                         after=u'',
-                         hierarchic=False, ),
-        userprofiles_acl=dict(before=u'',
-                              default=u'All:read,write,create,destroy,admin',
-                              after=u'',
-                              hierarchic=False, ),
+    # We assume this structure for a mercurial clone or simple "unpack and run" scenario:
+    # moin-2.0/                     # wikiconfig_dir points here: clone root or unpack directory, contains this file.
+    #     wikiconfig.py             # the file you are reading now.
+    #     wiki/                     # instance_dir variable points here: created by running "./m sample" or "./m new-wiki" commands.
+    #         data/                 # data_dir variable points here.
+    #         index/                # index_storage variable points here.
+    #     contrib/
+    #         interwiki/
+    #             intermap.txt      # interwiki_map variable points here.
+    #     docs/
+    #         _build/
+    #             html/             # serve_files['docs']: html docs made by sphinx, create by running "./m docs" command.
+    #     wiki_local/               # serve_files['wiki_local']: store custom logos, CSS, templates, etc. here
+    # If that's not true, adjust these paths
+    wikiconfig_dir = os.path.abspath(os.path.dirname(__file__))
+    instance_dir = os.path.join(wikiconfig_dir, 'wiki')
+    data_dir = os.path.join(instance_dir, 'data')
+    index_storage = 'FileStorage', (os.path.join(instance_dir, "index"), ), {}
+    # setup static files' serving:
+    serve_files = dict(
+        docs=os.path.join(wikiconfig_dir, 'docs', '_build', 'html'),  # html docs made by sphinx
+        wiki_local=os.path.join(wikiconfig_dir, 'wiki_local'),  # store custom logos, CSS, templates, etc. here
     )
+    # copy templates/snippets.html to directory below and edit per requirements to customize logos, etc.
+    template_dirs = [os.path.join(wikiconfig_dir, 'wiki_local'), ]
 
-    # for display purposes:
-    sitename = u'My MoinMoin'
     # it is required that you set this to a unique, stable and non-empty name:
     interwikiname = u'MyMoinMoin'
-    # Load the interwiki map from intermap.txt:
+    # load the interwiki map from intermap.txt:
     interwiki_map = InterWikiMap.from_file(os.path.join(wikiconfig_dir, 'contrib', 'interwiki', 'intermap.txt')).iwmap
-    # we must add entries for 'Self' and our interwikiname:
+    # we must add entries for 'Self' and our interwikiname, change these if you are not running the built-in desktop server:
     interwiki_map[interwikiname] = 'http://127.0.0.1:8080/'
     interwiki_map['Self'] = 'http://127.0.0.1:8080/'
 
-    # setup static files' serving:
-    serve_files = dict(
-        docs=os.path.join(wikiconfig_dir, 'docs', '_build', 'html'),  # html docs made by sphinx
-    )
-    # see https://bitbucket.org/thomaswaldmann/xstatic for infos about xstatic:
+    # sitename is displayed in heading of all wiki pages
+    sitename = u'My MoinMoin'
+
+    # default theme is basic
+    # theme_default = u"modernized"
+
+    # read about PRIVACY ISSUES in docs before uncommenting the line below to use gravatars
+    # user_use_gravatar = True
+
+    # read about SECURITY ISSUES in docs before uncommenting the line below allowing users
+    # to edit style attributes in HTML and Markdown items
+    # allow_style_attributes = True
+
+    # default passwords are required to be => 8 characters with minimum of 5 unique characters
+    # password_checker = None  # no password length or quality checking
+    # password_checker = lambda cfg, name, pw: _default_password_checker(cfg, name, pw, min_length=8, min_different=5)  # default
+
+    # optional, configure email, uncomment line below and choose (a) or (b)
+    # mail_from = u"wiki <wiki@example.org>"  # the "from:" address [Unicode]
+    # (a) using an SMTP server, e.g. "mail.provider.com" with optional `:port`appendix, which defaults to 25 (set None to disable mail)
+    # mail_smarthost = "smtp.example.org"
+    # mail_username = "smtp_username"  # if you need to use SMTP AUTH at your mail_smarthost:
+    # mail_password = "smtp_password"
+    # (b) an alternative to SMTP is the sendmail commandline tool:
+    # mail_sendmail = "/usr/sbin/sendmail -t -i"
+
+    # list of admin emails
+    admin_emails = []
+    # send tracebacks to admins
+    email_tracebacks = False
+
+    # add or remove packages - see https://bitbucket.org/thomaswaldmann/xstatic for info about xstatic
+    # it is uncommon to change these because of local customizations
     from xstatic.main import XStatic
     # names below must be package names
     mod_names = [
@@ -77,13 +125,52 @@
         xs = XStatic(mod, root_url='/static', provider='local', protocol='http')
         serve_files[xs.name] = xs.base_dir
 
-    # list of admin emails
-    admin_emails = []
-    # send tracebacks to admins
-    email_tracebacks = False
+    # create a super user who will have access to administrative functions
+    # acl_functions = u'+YourName:superuser'
+    # OR, create several WikiGroups and create several superusers and turn off textchas for selected users
+    # SuperGroup and TrustedEditorGroup reference WikiGroups you must create
+    # acl_functions = u'+YourName:superuser SuperGroup:superuser YourName:notextcha TrustedEditorGroup:notextcha'
+
+    # This provides a simple default setup for your backend configuration.
+    # 'stores:fs:...' indicates that you want to use the filesystem backend.
+    # Alternatively you can set up the mapping yourself (see HelpOnStorageConfiguration).
+    namespace_mapping, backend_mapping, acl_mapping = create_simple_mapping(
+        uri='stores:fs:{0}/%(backend)s/%(kind)s'.format(data_dir),
+        # XXX we use rather relaxed ACLs for the development wiki:
+        default_acl=dict(before=u'',
+                         default=u'All:read,write,create,destroy,admin',
+                         after=u'',
+                         hierarchic=False, ),
+        userprofiles_acl=dict(before=u'',
+                              default=u'All:read,write,create,destroy,admin',
+                              after=u'',
+                              hierarchic=False, ),
+    )
+
+    # uncomment and improve block below to enable textchas
+    """
+    textchas = {
+    'en': { # silly english example textchas (do not use them!)
+            u"Enter the first 9 digits of Pi.": ur"3\.14159265",
+            u"What is the opposite of 'day'?": ur"(night|nite)",
+            # ...
+    },
+    'de': { # some german textchas
+            u"Gib die ersten 9 Stellen von Pi ein.": ur"3\.14159265",
+            u"Was ist das Gegenteil von 'Tag'?": ur"nacht",
+            # ...
+    },
+    # you can add more languages if you like
+    }
+    #
+    secrets = {
+        'security/textcha': 'EnterSecretStringHere',
+        'security/ticket': 'EnterDifferentSceretStringHere',
+    }
+    """
 
 
-MOINCFG = Config  # Flask only likes uppercase stuff
+MOINCFG = Config  # Flask requires uppercase
 # Flask settings - see the flask documentation about their meaning
 SECRET_KEY = 'you need to change this so it is really secret'
 # DEBUG = False # use True for development only, not for public sites!
@@ -95,19 +182,3 @@
 # config for flask-cache:
 # CACHE_TYPE = 'filesystem'
 # CACHE_DIR = '/path/to/flask-cache-dir'
-
-# DEVELOPERS! Do not add your configuration items here - you could accidentally
-# commit them! Instead, create a wikiconfig_local.py file containing this:
-#
-# from wikiconfig_editme import *
-#
-# In wikiconfig_editme.py (the indirection is needed so that the auto reload
-# mechanism of the builtin server works) you do this:
-#
-# from wikiconfig import *
-#
-# class LocalConfig(Config):
-#    configuration_item_1 = 'value1'
-#
-# MOINCFG = LocalConfig
-# DEBUG = True