aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pysite/views/wiki/edit.py9
-rw-r--r--pysite/views/wiki/render.py33
-rw-r--r--templates/wiki/page_edit.html55
3 files changed, 83 insertions, 14 deletions
diff --git a/pysite/views/wiki/edit.py b/pysite/views/wiki/edit.py
index 483be046..d9ea692f 100644
--- a/pysite/views/wiki/edit.py
+++ b/pysite/views/wiki/edit.py
@@ -1,5 +1,5 @@
# coding=utf-8
-from flask import url_for
+from flask import url_for, request
from werkzeug.utils import redirect
from pysite.base_route import RouteView
@@ -32,4 +32,11 @@ class EditView(RouteView, DBMixin):
@csrf
def post(self, page):
# rst = request.form["rst"]
+ obj = {
+ "slug": page,
+ "title": request.form["title"],
+ "rst": request.form["rst"],
+ "html": ""
+ }
+
return redirect(url_for("wiki.page", page=page), code=303) # Redirect, ensuring a GET
diff --git a/pysite/views/wiki/render.py b/pysite/views/wiki/render.py
index d177a8b3..73c38731 100644
--- a/pysite/views/wiki/render.py
+++ b/pysite/views/wiki/render.py
@@ -1,5 +1,8 @@
# coding=utf-8
+import re
+
from docutils.core import publish_parts
+from docutils.utils import SystemMessage
from flask import jsonify
from schema import Schema
@@ -11,6 +14,8 @@ SCHEMA = Schema([{
"data": str
}])
+MESSAGE_REGEX = re.compile(r"<string>:(\d+): \([A-Z]+/\d\) (.*)")
+
class RenderView(APIView):
path = "/render" # "path" means that it accepts slashes
@@ -26,9 +31,35 @@ class RenderView(APIView):
data = data[0]["data"]
try:
html = publish_parts(
- source=data, writer_name="html5", settings_overrides={"traceback": True, "halt_level": 2}
+ source=data, writer_name="html5", settings_overrides={"halt_level": 2}
)["html_body"]
return jsonify({"data": html})
+ except SystemMessage as e:
+ lines = str(e)
+ data = {
+ "error": lines,
+ "error_lines": []
+ }
+
+ if "\n" in lines:
+ lines = lines.split("\n")
+ else:
+ lines = [lines]
+
+ for message in lines:
+ match = MESSAGE_REGEX.match(message)
+
+ if match:
+ data["error_lines"].append(
+ {
+ "row": int(match.group(1)) - 1,
+ "column": 0,
+ "type": "error",
+ "text": match.group(2)
+ }
+ )
+
+ return jsonify(data)
except Exception as e:
return jsonify({"error": str(e)})
diff --git a/templates/wiki/page_edit.html b/templates/wiki/page_edit.html
index 97a5161c..e83676fd 100644
--- a/templates/wiki/page_edit.html
+++ b/templates/wiki/page_edit.html
@@ -2,19 +2,32 @@
{% block title %}Wiki | Home{% endblock %}
{% block og_title %}Wiki | Home{% endblock %}
{% block og_description %}Landing page for the wiki{% endblock %}
+{% block extra_head %}
+<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.3.3/ace.js" type="application/javascript"></script>
+{% endblock %}
{% block content %}
<div class="uk-container uk-section">
- <form action="{{ url_for("wiki.edit", page=page) }}" method="post">
- <label for="title">Title: </label>
- <input name="title" id="title" value="{{ title }}" class="uk-input" />
- <label for="rst">Document: </label>
- <textarea name="rst" id="rst" class="uk-textarea">{{ rst }}</textarea>
- <button value="Preview" id="preview">Preview</button>
- <button type="submit" value="Save">Save</button>
+ <form uk-grid class="uk-grid-small" action="{{ url_for("wiki.edit", page=page) }}" method="post">
+ <div class="uk-width-expand">
+ <input name="title" id="title" placeholder="Page Title" value="{{ title }}" class="uk-input" />
+ </div>
+ <div class="uk-width-auto">
+ <button class="uk-button uk-button-secondary" type="button" value="Preview" id="preview">Preview</button>
+ </div>
+ <div class="uk-width-auto">
+ <button class="uk-button uk-button-primary" type="submit" value="Save">Save</button>
+ </div>
+ <div class="uk-width-1-1">
+{# <label for="rst">Document: </label>#}
+ <div id="rst" class="uk-textarea" style="resize: vertical; min-height: 10rem;">{{ rst }}</div>
+ </div>
+
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
</form>
- <div id="preview-div" style="border: 1px solid grey;">
+ <h2 class="uk-h2">Preview</h2>
+
+ <div id="preview-div">
<p>Preview will appear here.</p>
</div>
</div>
@@ -26,15 +39,21 @@
document.getElementById("preview").onclick = function(event) {
let oReq = new XMLHttpRequest();
- let data = document.getElementById("rst").value;
oReq.addEventListener("load", function() {
let response = JSON.parse(this.responseText);
if (response.error !== undefined) {
- console.log("Error: " + response.error)
+ if (response.error_lines !== undefined) {
+ editor.session.setAnnotations(response.error_lines);
+ document.getElementById("preview-div").innerHTML ="<h3>Error - see editor margin</h3>";
+ } else {
+ console.log("Error: " + response.error);
+ document.getElementById("preview-div").innerHTML ="<h3>Error</h3><p>" + response.error + "<p>";
+ }
} else {
document.getElementById("preview-div").innerHTML = response.data;
+ editor.session.setAnnotations([]);
}
});
@@ -43,9 +62,21 @@
oReq.setRequestHeader("Content-type", "application/json");
oReq.setRequestHeader("X-CSRFToken", csrf_token);
- oReq.send(JSON.stringify({"data": data}));
+ oReq.send(JSON.stringify({"data": editor.getValue()}));
return false;
- }
+ };
+
+ let editor = ace.edit("rst");
+ let timer;
+
+ editor.session.setMode("ace/mode/rst");
+ editor.setTheme("ace/theme/iplastic");
+ editor.on("input", function() {
+ if (timer !== undefined) {
+ clearTimeout(timer);
+ }
+ timer = setTimeout(function() {document.getElementById("preview").click()}, 1000);
+ })
</script>
{% endblock %} \ No newline at end of file