From deb1cb5d24c3d483d27c7bab8abb0383c25d5323 Mon Sep 17 00:00:00 2001 From: Gareth Coles Date: Thu, 12 Apr 2018 16:28:54 +0100 Subject: [Wiki] Some excellent shitcode for document TOCs --- pysite/rst/__init__.py | 70 ++++++++++++++++++++++++++++++++++++++++++++- pysite/views/wiki/edit.py | 5 +++- pysite/views/wiki/render.py | 4 +-- pysite/views/ws/rst.py | 2 +- templates/wiki/base.html | 20 +++++++++++++ 5 files changed, 96 insertions(+), 5 deletions(-) diff --git a/pysite/rst/__init__.py b/pysite/rst/__init__.py index e0fc973e..0c069615 100644 --- a/pysite/rst/__init__.py +++ b/pysite/rst/__init__.py @@ -1,15 +1,83 @@ # coding=utf-8 +import re + from docutils.core import publish_parts from docutils.parsers.rst.roles import register_canonical_role from pysite.rst.roles import icon_role, page_role, url_for_role +RST_TEMPLATE = """.. contents:: + +{0}""" + +CONTENTS_REGEX = re.compile(r"""
(.*?)
""", re.DOTALL) +HREF_REGEX = re.compile(r"""(.*?)""") + def render(rst: str): - return publish_parts( + rst = RST_TEMPLATE.format(rst) + html = publish_parts( source=rst, writer_name="html5", settings_overrides={"halt_level": 2, "syntax_highlight": "short"} )["html_body"] + data = { + "html": html, + "headers": [] + } + + match = CONTENTS_REGEX.search(html) # Find the contents HTML + + if match: + data["html"] = html.replace(match.group(0), "") # Remove the contents from the document HTML + + depth = 0 + headers = [] + current_header = {} + + group = match.group(1) + + # Sanitize the output so we can more easily parse it + group = group.replace("
  • ", "
  • \n") + group = group.replace("
  • ", "\n") + group = group.replace("

    ", "

    \n") + group = group.replace("

    ", "\n

    ") + + for line in group.split("\n"): + line = line.strip() # Remove excess whitespace + + if not line: # Nothing to process + continue + + if line.startswith("
  • ") and depth <= 2: + # We've found a header, or the start of a header group + depth += 1 + elif line.startswith("
  • ") and depth >= 0: + # That's the end of a header or header group + + if depth == 1: + # We just dealt with an entire header group, so store it + headers.append(current_header.copy()) # Store a copy, since we're clearing the dict + current_header.clear() + + depth -= 1 + elif line.startswith("
      + {% if data is defined %} + {% if "headers" in data %} +
    • Contents
    • + {% for header in data.headers %} + {% if "sub_headers" in header %} +
    • + {{ header.title }} + +
    • + {% else %} +
    • {{ header.title }}
    • + {% endif %} + {% endfor %} + {% endif %} +
    • + {% endif %}
    •  Home
    • -- cgit v1.2.3