Renders the inputted plain text wiki information into HTML rich text.
    
    :param      plain       |  <str> | \
                               Include some additional documentation
                urlHandler  |  <UlrHandler> || None
    
    :return     <str> html

def render(plain,
           urlHandler=None,
           templatePaths=None,
           options=None,
           defaultTag='div',
           wikiStyle='basic'):
    """
    Renders the inputted plain text wiki information into HTML rich text.
    
    :param      plain       |  <str> | \
                               Include some additional documentation
                urlHandler  |  <UlrHandler> || None
    
    :return     <str> html
    """
    if not plain:
        return ''

    __style = WIKI_STYLES.styles.get(wikiStyle, WIKI_STYLES.styles['basic'])

    # process the wiki text with the mako template system
    if not urlHandler:
        urlHandler = UrlHandler.current()

    # render the text out from mako template
    plain = projex.makotext.render(plain,
                                   options=options,
                                   templatePaths=templatePaths,
                                   silent=True)

    # generate wiki doc info
    lines = re.split('\n\r|\r\n|\n|\r', plain)
    curr_section = ''
    curr_section_level = 0
    html = []
    skip = []
    nowiki_stack = []
    nowiki_mode = 'pre'
    code_stack = []
    table_stack = []
    list_stack = []
    section_stack = []
    toc_data = []
    align_div = ''
    list_indent = None
    ignore_list_stack = False

    # add the default tag
    html.append(__style['wiki_open'].format(tag=defaultTag))

    for i, line in enumerate(lines):
        ignore_list_stack = False
        sline = line.strip()

        #----------------------------------------------------------------------
        #                           INDENTATION CHECKS
        #----------------------------------------------------------------------

        # check to see if we are continuing a list entry
        if list_indent:
            line_indent = len(re.match('\s*', line).group())

            if line_indent < list_indent:
                list_indent = None
                html.append(__style['list_item_close'])
            else:
                ignore_list_stack = True

                if not sline:
                    html.append(__style['spacer'])
                    continue

        if i in skip:
            continue

        #----------------------------------------------------------------------
        #                           ALIGNMENT
        #----------------------------------------------------------------------

        # check for a center option
        center = EXPR_CENTER.match(sline)
        right = EXPR_RIGHT.match(sline)
        left = EXPR_LEFT.match(sline)

        if center:
            style = center.groups()[0]
            line = center.groups()[1].strip()

            if align_div and align_div != 'center':
                html.append(__style['align_close'])
                align_div = ''

            if not align_div:
                if style == '--':
                    html.append(__style['align_center'])
                else:
                    html.append(__style['align_center_floated'])
                align_div = 'center'

            else:
                html.append(__style['newline'])

        # check for a right align option
        elif right:
            style = right.groups()[0]
            line = right.groups()[1]

            if align_div and align_div != 'right':
                html.append(__style['align_close'])
                align_div = ''

            if not align_div:
                if style == '--':
                    html.append(__style['align_right'])
                else:
                    html.append(__style['align_right_floated'])
                align_div = 'right'
            else:
                html.append(__style['newline'])

        # check for a left align option
        elif left:
            style = left.groups()[1]
            line = left.groups()[0]

            if align_div and align_div != 'left':
                html.append(__style['align_close'])
                align_div = ''

            if not align_div:
                if style == '--':
                    html.append(__style['align_left'])
                else:
                    html.append(__style['align_left_floated'])

                align_div = 'left'
            else:
                html.append(__style['newline'])

        # otherwise, clear alignment
        elif align_div:
            html.append(__style['align_close'])
            align_div = ''

        #----------------------------------------------------------------------
        #                           INDENTATION CHECKS
        #----------------------------------------------------------------------

        # make sure we're on the same level
        if curr_section and sline and (len(line) - len(line.lstrip())) < curr_section_level:
            html += section_stack
            section_stack = []

            curr_section = ''
            curr_section_level = 0

        count = i
        while sline.endswith('\\') and count + 1 < len(lines):
            sline += ' ' + lines[count + 1].strip()
            skip.append(count)
            count += 1

        #----------------------------------------------------------------------
        #                           IGNORE WIKI INFORMATION
        #----------------------------------------------------------------------

        # check to see what is wiki protected
        if sline.startswith('<nowiki'):
            mode = re.search('mode="(\w*)"', sline)
            if mode:
                nowiki_mode = nstr(mode.group(1))
            else:
                nowiki_mode = None

            if not ignore_list_stack:
                html += list_stack
                list_stack = []

            html += table_stack
            table_stack = []

            if nowiki_mode is None:
                html.append(__style['nowiki_open'])
                nowiki_stack.append(__style['nowiki_close'])
            else:
                nowiki_stack.append('')

            continue

        elif sline == '</nowiki>':
            html += nowiki_stack
            nowiki_stack = []
            continue

        elif nowiki_stack:
            if nowiki_mode == 'safe':
                html.append(line)
            else:
                html.append(xml.sax.saxutils.escape(line))
            continue

        #----------------------------------------------------------------------
        #                           TABLES
        #----------------------------------------------------------------------

        parts = line.split(' | ')
        if len(parts) == 1:
            html += table_stack
            table_stack = []

        # replace standard items
        for key, repl in PRE_ESCAPE_REPLACE.items():
            line = line.replace(key, repl)

        # strip out nowiki lines
        nowiki_dict = {}
        count = 0
        for section in EXPR_NOWIKI.findall(line)[::2]:
            nowiki_dict['nowiki_%i' % count] = section
            newtext = '%%(nowiki_%i)s' % count
            line = line.replace('<nowiki>%s</nowiki>' % section, newtext)
            count += 1

        #----------------------------------------------------------------------
        #                           SECTIONS
        #----------------------------------------------------------------------

        # check for a div section
        section = EXPR_SECTION.match(sline)
        if section:
            html += code_stack
            code_stack = []

            name = section.group(2)
            if name != curr_section:
                html += section_stack
                section_stack = []

                if name not in SECTION_ALERTS:
                    section_stack.append(__style['section_close'])

                    display = projex.text.capitalizeWords(name)
                    mapped = SECTION_MAP.get(name, display)

                    html.append(__style['section_open'].format(name=name,
                                                               title=mapped))
                else:
                    display = projex.text.capitalizeWords(name)
                    mapped = SECTION_MAP.get(name, display)

                    section_stack.append(__style['section_alert_close'])
                    url, success = urlHandler.resolve('img:%s.png' % name)
                    html.append(__style['section_alert_open'].format(name=name,
                                                                     title=mapped))

                curr_section = name
            else:
                html.append(__style['newline'])

            sline = sline.replace(section.group(), '')
            line = line.replace(section.group(), ' ' * len(section.group()))
            curr_section_level = len(line) - len(line.lstrip())

        #----------------------------------------------------------------------
        #                           CODE
        #----------------------------------------------------------------------

        # check for code
        code = EXPR_CODE.match(sline)
        if code:
            templ = ''
            code_line = code.groups()[0]

            if not code_stack:
                lang = 'python'
                lang_search = EXPR_LANG.search(code_line)

                if lang_search:
                    lang = lang_search.groups()[0]
                    code_line = code_line.replace(lang_search.group(), '')

                templ = __style['code_open'].format(lang=lang)
                code_stack.append(__style['code_close'])

            escaped = xml.sax.saxutils.escape(code_line)

            if not ignore_list_stack:
                html += list_stack
                list_stack = []

            html += table_stack
            table_stack = []

            html.append(templ + escaped)
            continue

        # exit out of the code mode
        else:
            html += code_stack
            code_stack = []

        #----------------------------------------------------------------------

        # make sure we have no html data in the line
        if not sline:
            html.append(__style['paragraph_close'])
            html.append(__style['paragraph_open'])
            continue

        # check for horizontal rules
        if EXPR_HR.match(sline):
            style = ''
            html.append(__style['hr'].format(style=style))
            continue

        #----------------------------------------------------------------------
        #                           HEADERS
        #----------------------------------------------------------------------

        # check for headers
        header = EXPR_HEADER.match(sline)
        if header:
            hopen, title, hclose = header.groups()
            hopencount = len(hopen)
            title = title.strip()

            if hopencount == len(hclose):
                name = projex.text.underscore(title)
                add = __style['header'].format(name=name,
                                               title=title,
                                               size=len(hopen))
                spacing = '#' * hopencount
                opts = (spacing, name, title)
                toc_data.append('%s. [[#%s|%s]]' % opts)

                if not ignore_list_stack:
                    html += list_stack
                    list_stack = []

                html += table_stack
                table_stack = []

                html.append(add)
                continue

        line = xml.sax.saxutils.escape(line)

        for key, repl in POST_ESCAPE_REPLACE.items():
            line = line.replace(key, repl)

        #----------------------------------------------------------------------
        #                           CLASS TYPES
        #----------------------------------------------------------------------

        # resolve any class links
        for result in EXPR_CLASS_LINK.findall(line):
            opts = result.split()
            for o, cls in enumerate(opts):
                # ignore base classes, need modules
                if '.' not in cls:
                    continue

                url, success = urlHandler.resolveClass(cls)
                if success:
                    opts[o] = __style['link_class'].format(url=url,
                                                           text=cls.split('.')[-1])

            info = __style['span_class'].format(crumbs=' '.join(opts))
            line = line.replace('&lt;' + result + '&gt;', info)

        #----------------------------------------------------------------------
        #                           GENERAL FORMATTING
        #----------------------------------------------------------------------

        # replace formatting options
        for section in EXPR_UNDERLINE.findall(line)[::2]:
            text = __style['underline'].format(text=section)
            line = line.replace("___%s___" % section, text)

        for section in EXPR_INLINE_CODE.findall(line)[::2]:
            text = __style['inline_code'].format(text=section)
            line = line.replace("`%s`" % section, text)

        for section in EXPR_STRIKEOUT.findall(line)[::2]:
            text = __style['strikeout'].format(text=section)
            line = line.replace("---%s---" % section, text)

        for section in EXPR_BOLD.findall(line)[::2]:
            text = __style['bold'].format(text=section)
            line = line.replace("'''%s'''" % section, text)

        for section in EXPR_ITALIC.findall(line)[::2]:
            text = __style['italic'].format(text=section)
            line = line.replace("''%s''" % section, text)

        #----------------------------------------------------------------------
        #                           IMAGES
        #----------------------------------------------------------------------

        # resolve any images
        for grp, url in EXPR_IMG.findall(line):
            urlsplit = url.split('|')
            last_word = re.findall('\w+', urlsplit[0])[-1]

            if len(urlsplit) == 1:
                urlsplit.append('')

            url, _ = urlHandler.resolveImage(urlsplit[0])
            line = line.replace(grp, __style['img'].format(url=url,
                                                           style=urlsplit[1],
                                                           title=last_word))

        #----------------------------------------------------------------------
        #                           COLORS
        #----------------------------------------------------------------------

        # resolve any colors
        for grp, coloring in EXPR_COLOR.findall(line):
            splt = coloring.split('|')
            if len(splt) == 1:
                splt.append('')

            line = line.replace(grp, __style['color'].format(color=splt[0],
                                                             text=splt[1]))

        #----------------------------------------------------------------------
        #                           SPANS
        #----------------------------------------------------------------------

        # resolve any spans
        for grp, coloring in EXPR_SPAN.findall(line):
            splt = coloring.split('|')
            if len(splt) == 1:
                splt.append('')

            templ = '<span style="%s">%s</span>' % (splt[0], splt[1])
            line = line.replace(grp, __style['span'].format(style=splt[0],
                                                            text=splt[1]))

        #----------------------------------------------------------------------
        #                           LINKS
        #----------------------------------------------------------------------

        # resolve any external urls
        for result in EXPR_EXTLINK.findall(line):
            grp = result[0]
            url = result[1]

            urlsplit = url.split()
            if len(urlsplit) == 1:
                urlsplit.append(urlsplit[0])

            url = urlsplit[0]
            urltext = ' '.join(urlsplit[1:])

            line = line.replace(grp, __style['link_ext'].format(url=url, text=urltext))

        # resolve any internal urls
        for grp, url in EXPR_INTLINK.findall(line):
            urlsplit = url.split('|')
            if len(urlsplit) == 1:
                last_word = re.findall('\w+', urlsplit[0])[-1]
                urlsplit.append(last_word)

            url = urlsplit[0]
            title = '|'.join(urlsplit[1:])
            found = True

            tagsplit = url.split('#')
            if len(tagsplit) == 1:
                url = url
                tag = ''
            else:
                url = tagsplit[0]
                tag = '#'.join(tagsplit[1:])

            # make sure the url exists
            if url:
                url, exists = urlHandler.resolve(url)
                if not exists:
                    found = False

            # join together the resolved url and the tag
            if tag:
                url = url + '#' + tag

            # generate the link
            if found:
                templ = __style['link_found'].format(url=url, text=title)
            else:
                templ = __style['link_not_found'].format(url=url, text=title)

            line = line.replace(grp, templ)

        #----------------------------------------------------------------------
        #                           LISTS
        #----------------------------------------------------------------------

        # process lists
        results = EXPR_LIST.match(line)
        if results:
            level, linetext = results.groups()
            level_count = len(level)
            level_type = 'unordered' if level[-1] == '*' else 'ordered'

            while level_count > len(list_stack):
                html.append(__style[level_type + '_list_open'])
                list_stack.append(__style[level_type + '_list_close'])

            while len(list_stack) > level_count:
                html.append(list_stack[-1])
                list_stack = list_stack[:-1]

            space_line = line.replace(level + '.', ' ' * (len(level) + 1))
            list_indent = len(re.match('\s*', space_line).group())

            html.append(__style['list_item_open'])
            html.append(linetext)

            continue

        elif not ignore_list_stack:
            html += list_stack
            list_stack = []

        #----------------------------------------------------------------------
        #                           TABLES
        #----------------------------------------------------------------------

        parts = line.split(' | ')
        if len(parts) > 1:
            if not table_stack:
                table_stack.append(__style['table_close'])
                html.append(__style['table_open'])

            cell_type = 'td'
            styles = ''

            cells = []
            for part in parts:
                results = EXPR_TABLE_CELL.search(part)

                if not results:
                    cells.append(__style['table_cell'].format(tag='td',
                                                              style='',
                                                              text=part.strip()))

                else:
                    grp, cell_type, styles = results.groups()

                    if not styles:
                        styles = ''
                    else:
                        styles = styles.strip('[]')

                    part = part.replace(grp, '').strip()
                    opts = (cell_type, styles, part, cell_type)

                    cells.append(__style['table_cell'].format(tag=cell_type,
                                                              style=styles,
                                                              text=part))

            line = __style['table_row'].format(text=''.join(cells))

            html.append((line % nowiki_dict))

        else:
            html += table_stack
            table_stack = []

            html.append(line % nowiki_dict)

    if align_div:
        html.append(__style['align_close'])

    if list_indent:
        html.append(__style['list_item_close'])

    html += table_stack
    html += list_stack
    html += code_stack
    html += nowiki_stack
    html += section_stack

    html.append(__style['wiki_close'].format(tag=defaultTag))
    html_txt = '\n'.join(html)

    # resolve any table of contents
    for toc, options in EXPR_TOC.findall(html_txt):
        toc_wiki = '\n\t'.join(toc_data)
        toc_html = __style['toc_open']
        toc_html += render(toc_wiki, urlHandler, templatePaths, options, 'div', wikiStyle)
        toc_html += __style['toc_close']

        html_txt = html_txt.replace(toc, toc_html)

    # replace \[ and \] options
    html_txt = html_txt.replace('\[', '[').replace('\]', ']')

    return html_txt