diff options
Diffstat (limited to '')
| -rw-r--r-- | pysite/rst/__init__.py | 5 | ||||
| -rw-r--r-- | pysite/rst/roles.py | 37 | ||||
| -rw-r--r-- | requirements.txt | 1 | ||||
| -rw-r--r-- | static/css/pygments-monokai.css | 70 | ||||
| -rw-r--r-- | templates/main/base.html | 1 | ||||
| -rw-r--r-- | templates/wiki/base.html | 3 | ||||
| -rw-r--r-- | templates/wiki/page_edit.html | 20 | 
7 files changed, 129 insertions, 8 deletions
| diff --git a/pysite/rst/__init__.py b/pysite/rst/__init__.py index 0e5f6ffe..815ad058 100644 --- a/pysite/rst/__init__.py +++ b/pysite/rst/__init__.py @@ -2,13 +2,14 @@  from docutils.core import publish_parts  from docutils.parsers.rst.roles import register_canonical_role -from pysite.rst.roles import icon_role +from pysite.rst.roles import icon_role, url_for_role  def render(rst: str):      return publish_parts( -        source=rst, writer_name="html5", settings_overrides={"halt_level": 2} +        source=rst, writer_name="html5", settings_overrides={"halt_level": 2, "syntax_highlight": "short"}      )["html_body"]  register_canonical_role("icon", icon_role) +register_canonical_role("url_for", url_for_role) diff --git a/pysite/rst/roles.py b/pysite/rst/roles.py index bff00533..414832df 100644 --- a/pysite/rst/roles.py +++ b/pysite/rst/roles.py @@ -2,6 +2,7 @@  from docutils import nodes  from docutils.parsers.rst.roles import set_classes  from docutils.parsers.rst.states import Inliner +from flask import url_for  from jinja2 import escape @@ -44,3 +45,39 @@ def icon_role(_role: str, rawtext: str, text: str, lineno: int, inliner: Inliner          node = nodes.raw(html, html, format="html", **options)          return [node], [] + + +def url_for_role(_role: str, rawtext: str, text: str, lineno: int, inliner: Inliner, +                 options: dict = None, _content: dict = None): +    if options is None: +        options = {} + +    set_classes(options) + +    if "/" in text: +        parts = [escape(x) for x in text.split("/")] +    else: +        msg = inliner.reporter.error("URL specification must be in the form <page.name>/<text>", line=lineno) +        prb = inliner.problematic(text, rawtext, msg) + +        return [prb], [msg] + +    if len(parts) != 2: +        msg = inliner.reporter.error("URL specification must be in the form <page.name>/<text>", line=lineno) +        prb = inliner.problematic(text, rawtext, msg) + +        return [prb], [msg] +    else: +        try: +            url = url_for(parts[0]) +            name = parts[1] + +            html = f"""<a href="{url}">{name}</a>""" + +            node = nodes.raw(html, html, format="html", **options) +            return [node], [] +        except Exception as e: +            msg = inliner.reporter.error(str(e), line=lineno) +            prb = inliner.problematic(text, rawtext, msg) + +            return [prb], [msg] diff --git a/requirements.txt b/requirements.txt index f7afea00..bb66b59d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,3 +11,4 @@ Flask-Dance  logmatic-python  flask-wtf  docutils +pygments diff --git a/static/css/pygments-monokai.css b/static/css/pygments-monokai.css new file mode 100644 index 00000000..250c8d44 --- /dev/null +++ b/static/css/pygments-monokai.css @@ -0,0 +1,70 @@ +.code .hll { background-color: #49483e } +.code  { background: #272822; color: #f8f8f2 } +.code .c { color: #75715e } /* Comment */ +.code .err { color: #960050; background-color: #1e0010 } /* Error */ +.code .k { color: #66d9ef } /* Keyword */ +.code .l { color: #ae81ff } /* Literal */ +.code .n { color: #f8f8f2 } /* Name */ +.code .o { color: #f92672 } /* Operator */ +.code .p { color: #f8f8f2 } /* Punctuation */ +.code .ch { color: #75715e } /* Comment.Hashbang */ +.code .cm { color: #75715e } /* Comment.Multiline */ +.code .cp { color: #75715e } /* Comment.Preproc */ +.code .cpf { color: #75715e } /* Comment.PreprocFile */ +.code .c1 { color: #75715e } /* Comment.Single */ +.code .cs { color: #75715e } /* Comment.Special */ +.code .gd { color: #f92672 } /* Generic.Deleted */ +.code .ge { font-style: italic } /* Generic.Emph */ +.code .gi { color: #a6e22e } /* Generic.Inserted */ +.code .gs { font-weight: bold } /* Generic.Strong */ +.code .gu { color: #75715e } /* Generic.Subheading */ +.code .kc { color: #66d9ef } /* Keyword.Constant */ +.code .kd { color: #66d9ef } /* Keyword.Declaration */ +.code .kn { color: #f92672 } /* Keyword.Namespace */ +.code .kp { color: #66d9ef } /* Keyword.Pseudo */ +.code .kr { color: #66d9ef } /* Keyword.Reserved */ +.code .kt { color: #66d9ef } /* Keyword.Type */ +.code .ld { color: #e6db74 } /* Literal.Date */ +.code .m { color: #ae81ff } /* Literal.Number */ +.code .s { color: #e6db74 } /* Literal.String */ +.code .na { color: #a6e22e } /* Name.Attribute */ +.code .nb { color: #f8f8f2 } /* Name.Builtin */ +.code .nc { color: #a6e22e } /* Name.Class */ +.code .no { color: #66d9ef } /* Name.Constant */ +.code .nd { color: #a6e22e } /* Name.Decorator */ +.code .ni { color: #f8f8f2 } /* Name.Entity */ +.code .ne { color: #a6e22e } /* Name.Exception */ +.code .nf { color: #a6e22e } /* Name.Function */ +.code .nl { color: #f8f8f2 } /* Name.Label */ +.code .nn { color: #f8f8f2 } /* Name.Namespace */ +.code .nx { color: #a6e22e } /* Name.Other */ +.code .py { color: #f8f8f2 } /* Name.Property */ +.code .nt { color: #f92672 } /* Name.Tag */ +.code .nv { color: #f8f8f2 } /* Name.Variable */ +.code .ow { color: #f92672 } /* Operator.Word */ +.code .w { color: #f8f8f2 } /* Text.Whitespace */ +.code .mb { color: #ae81ff } /* Literal.Number.Bin */ +.code .mf { color: #ae81ff } /* Literal.Number.Float */ +.code .mh { color: #ae81ff } /* Literal.Number.Hex */ +.code .mi { color: #ae81ff } /* Literal.Number.Integer */ +.code .mo { color: #ae81ff } /* Literal.Number.Oct */ +.code .sa { color: #e6db74 } /* Literal.String.Affix */ +.code .sb { color: #e6db74 } /* Literal.String.Backtick */ +.code .sc { color: #e6db74 } /* Literal.String.Char */ +.code .dl { color: #e6db74 } /* Literal.String.Delimiter */ +.code .sd { color: #e6db74 } /* Literal.String.Doc */ +.code .s2 { color: #e6db74 } /* Literal.String.Double */ +.code .se { color: #ae81ff } /* Literal.String.Escape */ +.code .sh { color: #e6db74 } /* Literal.String.Heredoc */ +.code .si { color: #e6db74 } /* Literal.String.Interpol */ +.code .sx { color: #e6db74 } /* Literal.String.Other */ +.code .sr { color: #e6db74 } /* Literal.String.Regex */ +.code .s1 { color: #e6db74 } /* Literal.String.Single */ +.code .ss { color: #e6db74 } /* Literal.String.Symbol */ +.code .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ +.code .fm { color: #a6e22e } /* Name.Function.Magic */ +.code .vc { color: #f8f8f2 } /* Name.Variable.Class */ +.code .vg { color: #f8f8f2 } /* Name.Variable.Global */ +.code .vi { color: #f8f8f2 } /* Name.Variable.Instance */ +.code .vm { color: #f8f8f2 } /* Name.Variable.Magic */ +.code .il { color: #ae81ff } /* Literal.Number.Integer.Long */ diff --git a/templates/main/base.html b/templates/main/base.html index cbdd937b..cfe41099 100644 --- a/templates/main/base.html +++ b/templates/main/base.html @@ -17,6 +17,7 @@              <link rel="shortcut icon" href="{{ static_file('favicon.ico') }}">              <link rel="stylesheet" href="{{ static_file('uikit_blurple.css') }}"/>              <link rel="stylesheet" href="{{ static_file('style.css') }}"/> +            <link rel="stylesheet" href="{{ static_file('css/pygments-monokai.css') }}"/>              <!-- OpenGraph metadata -->              <meta property="og:title" content="Python Discord | {% block og_title %}{% endblock %}"> diff --git a/templates/wiki/base.html b/templates/wiki/base.html index 02ab1b55..4bb227df 100644 --- a/templates/wiki/base.html +++ b/templates/wiki/base.html @@ -16,6 +16,7 @@              <link rel="shortcut icon" href="{{ static_file('favicon.ico') }}">              <link rel="stylesheet" href="{{ static_file('uikit_blurple.css') }}"/>              <link rel="stylesheet" href="{{ static_file('style.css') }}"/> +            <link rel="stylesheet" href="{{ static_file('css/pygments-monokai.css') }}"/>              <!-- OpenGraph metadata -->              <meta property="og:title" content="Python Discord | {% block og_title %}{% endblock %}"> @@ -30,7 +31,7 @@          <div class="uk-offcanvas-content uk-flex uk-flex-column">              {% include "main/navigation.html" %}              <div class="uk-flex uk-flex-row uk-flex-1"> -                <div class="uk-card uk-card-body uk-flex-left uk-flex"> +                <div class="uk-card uk-card-body uk-flex-left uk-flex uk-card-primary">                      <ul class="uk-nav-default uk-nav-parent-icon" uk-nav>                          {% if (can_edit or debug) and current_page == "page" %}                              <li> diff --git a/templates/wiki/page_edit.html b/templates/wiki/page_edit.html index 7664511e..b797577d 100644 --- a/templates/wiki/page_edit.html +++ b/templates/wiki/page_edit.html @@ -14,7 +14,7 @@              <button class="uk-button uk-button-secondary" type="button" value="Preview" id="preview">Preview</button>          </div>          <div class="uk-width-auto"> -            <input class="uk-button uk-button-primary" type="submit" value="Save" /> +            <input class="uk-button uk-button-primary" type="submit" id="submit" value="Save" />          </div>          <div class="uk-width-1-1">              <div id="editor" class="uk-textarea" style="resize: vertical; min-height: 15rem;">{{ rst }}</div> @@ -24,10 +24,12 @@          <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>      </form> -    <h2>Preview</h2> +    <div class="uk-container uk-container-small" style="padding: 1rem 1rem 0.1rem;"> +        <h2 id="preview-title">{{ title }}</h2> -    <div class="uk-alert" id="preview-div" style="padding: 1rem 1rem 0.1rem;"> -        {{ preview | safe }} +        <div id="preview-div"> +            {{ preview | safe }} +        </div>      </div>      <script type="application/javascript"> @@ -42,6 +44,8 @@                  let response = JSON.parse(this.responseText);                  if (response.error !== undefined) { +                    document.getElementById("submit").disabled = true; +                      if (response.error_lines !== undefined) {                          editor.session.setAnnotations(response.error_lines);                          document.getElementById("preview-div").innerHTML ="<h3>Error - see editor margin</h3>"; @@ -50,7 +54,9 @@                          document.getElementById("preview-div").innerHTML ="<h3>Error</h3><p>" + response.error + "<p>";                      }                  } else { +                    document.getElementById("submit").disabled = false;                      document.getElementById("preview-div").innerHTML = response.data; +                      editor.session.setAnnotations([]);                  }              }); @@ -81,6 +87,10 @@                  clearTimeout(timer);              }              timer = setTimeout(function() {document.getElementById("preview").click()}, 1000); -        }) +        }); + +        document.getElementById("title").oninput = function() { +            document.getElementById("preview-title").textContent = document.getElementById("title").value; +        }      </script>  {% endblock %}
\ No newline at end of file | 
