# Path: simiki/jinja_exts.py
# def rfc3339(dt_obj):
# 
# Path: simiki/utils.py
# def import_string(import_name, silent=False):
#     """Imports an object based on a string.  This is useful if you want to
#     use import paths as endpoints or something similar.  An import path can
#     be specified either in dotted notation (``xml.sax.saxutils.escape``)
#     or with a colon as object delimiter (``xml.sax.saxutils:escape``).
#     If `silent` is True the return value will be `None` if the import fails.
#     :param import_name: the dotted name for the object to import.
#     :param silent: if set to `True` import errors are ignored and
#                    `None` is returned instead.
#     :return: imported object
#     """
#     # ref: https://github.com/pallets/werkzeug/blob/master/werkzeug/utils.py
# 
#     # force the import name to automatically convert to strings
#     # __import__ is not able to handle unicode strings in the fromlist
#     # if the module is a package
#     import_name = str(import_name).replace(':', '.')
#     try:
#         try:
#             __import__(import_name)
#         except ImportError:
#             if '.' not in import_name:
#                 raise
#         else:
#             return sys.modules[import_name]
# 
#         module_name, obj_name = import_name.rsplit('.', 1)
#         try:
#             module = __import__(module_name, None, None, [obj_name])
#         except ImportError:
#             # support importing modules not yet set up by the parent module
#             # (or package for that matter)
#             module = import_string(module_name)
# 
#         try:
#             return getattr(module, obj_name)
#         except AttributeError as e:
#             raise ImportError(e)
# 
#     except ImportError as e:
#         if not silent:
#             raise ImportError(e)
# 
# Path: simiki/compat.py



import os
import os.path
import io
import copy
import re
import traceback
import warnings
import markdown
import yaml
    from collections import OrderedDict
    from ordereddict import OrderedDict
from jinja2 import (Environment, FileSystemLoader, TemplateError)
from simiki import jinja_exts
from simiki.utils import import_string
from simiki.compat import is_py2, is_py3, basestring
    from functools import cmp_to_key
            p = dct
            for x in path.split(os.sep):
                if ext in x:
                    meta["name"] = os.path.splitext(x)[0]
                    p = p.setdefault(x, meta)
                else:
                    p = p.setdefault(x, {})

        self.structure = dct.get(self.site_config['source'], {})

        self.sort_structure()

    def sort_structure(self):
        """Sort index structure in lower-case, alphabetical order

        Compare argument is a key/value structure, if the compare argument is a
        leaf node, which has `title` key in its value, use the title value,
        else use the key to compare.
        """

        def _cmp(arg1, arg2):
            arg1 = arg1[1]["title"] if "title" in arg1[1] else arg1[0]
            arg2 = arg2[1]["title"] if "title" in arg2[1] else arg2[0]
            # cmp not exists in py3
            # via <https://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons> # noqa
            cmp = lambda x, y: (x > y) - (x < y)  # noqa: E731
            return cmp(arg1.lower(), arg2.lower())

        if is_py2:
            sorted_opts = {'cmp': _cmp}

# Path: simiki/jinja_exts.py
# def rfc3339(dt_obj):
# 
# Path: simiki/utils.py
# def import_string(import_name, silent=False):
#     """Imports an object based on a string.  This is useful if you want to
#     use import paths as endpoints or something similar.  An import path can
#     be specified either in dotted notation (``xml.sax.saxutils.escape``)
#     or with a colon as object delimiter (``xml.sax.saxutils:escape``).
#     If `silent` is True the return value will be `None` if the import fails.
#     :param import_name: the dotted name for the object to import.
#     :param silent: if set to `True` import errors are ignored and
#                    `None` is returned instead.
#     :return: imported object
#     """
#     # ref: https://github.com/pallets/werkzeug/blob/master/werkzeug/utils.py
# 
#     # force the import name to automatically convert to strings
#     # __import__ is not able to handle unicode strings in the fromlist
#     # if the module is a package
#     import_name = str(import_name).replace(':', '.')
#     try:
#         try:
#             __import__(import_name)
#         except ImportError:
#             if '.' not in import_name:
#                 raise
#         else:
#             return sys.modules[import_name]
# 
#         module_name, obj_name = import_name.rsplit('.', 1)
#         try:
#             module = __import__(module_name, None, None, [obj_name])
#         except ImportError:
#             # support importing modules not yet set up by the parent module
#             # (or package for that matter)
#             module = import_string(module_name)
# 
#         try:
#             return getattr(module, obj_name)
#         except AttributeError as e:
#             raise ImportError(e)
# 
#     except ImportError as e:
#         if not silent:
#             raise ImportError(e)
# 
# Path: simiki/compat.py



# Path: simiki/generators.py
import os
import os.path
import io
import copy
import re
import traceback
import warnings
import markdown
import yaml
    from collections import OrderedDict
    from ordereddict import OrderedDict
from jinja2 import (Environment, FileSystemLoader, TemplateError)
from simiki import jinja_exts
from simiki.utils import import_string
from simiki.compat import is_py2, is_py3, basestring
    from functools import cmp_to_key

            p = dct
            for x in path.split(os.sep):
                if ext in x:
                    meta["name"] = os.path.splitext(x)[0]
                    p = p.setdefault(x, meta)
                else:
                    p = p.setdefault(x, {})

        self.structure = dct.get(self.site_config['source'], {})

        self.sort_structure()

    def sort_structure(self):
        """Sort index structure in lower-case, alphabetical order

        Compare argument is a key/value structure, if the compare argument is a
        leaf node, which has `title` key in its value, use the title value,
        else use the key to compare.
        """

        def _cmp(arg1, arg2):
            arg1 = arg1[1]["title"] if "title" in arg1[1] else arg1[0]
            arg2 = arg2[1]["title"] if "title" in arg2[1] else arg2[0]
            # cmp not exists in py3
            # via <https://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons> # noqa
            cmp = lambda x, y: (x > y) - (x < y)  # noqa: E731
            return cmp(arg1.lower(), arg2.lower())

        if is_py2:
            sorted_opts = {'cmp': _cmp}

        elif is_py3: