That proved a little more convoluted than expected, but now works well.

This commit is contained in:
simon 2016-08-21 12:19:54 +01:00
parent 06773bd6f7
commit ebfefd3edb
6 changed files with 390 additions and 56 deletions

View file

@ -57,4 +57,4 @@ Alternatively, if you want to deploy to a servlet container (which I would stron
## Editing the framing content
You can edit the [[\_left-bar]], the [[\_edit-left-bar]], and the [[\_header]].
You can edit the [stylesheet](/edit-css?page=stylesheet), the [[\_left-bar]], the [[\_edit-left-bar]], and the [[\_header]].

View file

@ -0,0 +1,296 @@
/*
## Smeagol: a very simple Wiki engine
## Copyright and licence
Copyright (C) 2014 Simon Brooke
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
USA.
# The Stylesheet
*/
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
/* ids generally in document order */
/* top-of-page navigation, not editable, provided by Smeagol */
#nav{
margin: 0;
padding: 0;
top: 0;
width: 100%;
_position: absolute;
_top: expression(document.documentElement.scrollTop);
z-index: 149;
background:rgba(40,40,40,0.8);
}
#user {
font-height: 66%;
float: right;
padding: 0.1em 0.75em;
margin: 0;
color: white;
}
#user a {
color: silver;
}
/* only needed for fly-out menu effect on tablet and phone stylesheets */
#nav-icon {
display: none;
}
#nav-menu {
margin: 0;
padding: 0;
}
#nav ul li {
padding: 0;
margin: 0;
display: inline;
}
#nav ul li a {
color: white;
text-decoration: none;
font-weight: bold;
padding: 0.1em 0.75em;
margin: 0;
}
#nav ul li.active a { background: silver;}
li.nav-item a:hover { background: rgb( 240, 240, 240) }
li.nav-item a:active { background: gray; color: white; }
/* Overall container div, holds all content of page. Yes, I know it shouldn't have fixed width */
#main-container{
}
/* header for all pages in the Wiki - editable, provided by users. Within main-container */
#header {
margin-top: 0;
width:100%;
background-color: gray;
color: white;
}
#header h1 {
margin-top: 0;
}
/* left bar for all pages in the Wiki - editable, provided by users. Within main-container */
#left-bar {
width: 17%;
height: 100%;
float: left;
}
/* content of the current in the Wiki - editable, provided by users. Within main-container */
#content {
border: thin solid silver;
width: 80%;
float: right;
padding-bottom: 5em;
}
/* cookies information box, fixed, in right margin, just above footer */
#cookies {
width: 30%;
float: right;
position: fixed;
bottom: 1.5em;
right: 0;
z-index: 150;
background: transparent;
}
/* about-cookies box: permanently visible part of cookies information box */
#about-cookies {
clear: right;
width: 10em;
font-size: 66%;
float: right;
text-align: right;
padding: 0.25em 2em;
color: white;
background:rgba(40,40,40,0.8);
}
/* more-about-cookies box, normally hidden */
#more-about-cookies {
display: none;
padding: 0.25em 2em;
color: white;
background:rgba(40,40,40,0.8);
border-bottom: thin solid white;
}
/* but magically appears on mouseover */
#cookies:hover #more-about-cookies {
display: block;
}
/* footer of the page - not-editable, provided by Smeagol */
#footer {
clear: both;
font-size: smaller;
text-align: center;
color:white;
background:rgba(128,128,128,0.95);
width: 100%;
margin: 0;
padding: 0.25em 0;
bottom:0;
position:fixed;
vertical-align: top;
z-index:150;
_position:absolute;
_top:expression(eval(document.documentElement.scrollTop+
(document.documentElement.clientHeight-this.offsetHeight)));
}
.change {
background-color: rgb( 223, 223, 223);
border: thin solid silver;
}
.error {
width: 100%;
background-color: red;
color: white;
}
.message {
border: thin solid red;
}
.minor-controls {
list-style: none;
float: right;
padding: 0.25em 2em;
color: white;
background:rgba(40,40,40,0.8);
font-size: 66%;
}
.minor-controls li {
display: inline;
}
.minor-controls a {
float: right;
padding: 0.25em 2em;
color: white;
}
.warn {
color: maroon;
}
.widget {
background-color: silver;
border: thin solid white;
margin-top: 0;
margin-bottom: 0;
width: 100%;
}
.wiki {
margin: 0;
}
form {
border: thin solid silver;
}
del {
color: red;
}
div.content, form, p, pre, h1, h2, h3, h4, h5 {
padding: 0.25em 5%;
}
dl, menu, ol, table, ul {
margin: 0.25em 5%;
}
input {
background-color: white;
}
input.action {
background-color: green;
}
input.action-dangerous {
color: white;
background-color: red;
}
input.required:after {
content: " \*";
color: red;
}
ins {
color: green;
}
label {
width: 20%;
min-width: 20em;
border-right: thin solid gray;
}
menu li {
display: inline;
}
menu li::before {
content: "|| ";
}
table {
border: 2px solid black;
border-collapse: collapse;
}
table.music-ruled tr:nth-child(odd) {
background-color: silver;
}
th, td {
text-align: left;
vertical-align: top;
padding: 0.15em 1.5em;
border: 1px solid gray;
}
th {
background-color: silver;
}

View file

@ -3,11 +3,8 @@
<head>
<title>{{title}}</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="{{servlet-context}}/css/phone.css" media="only screen and (max-device-width: 480px)" rel="stylesheet" type="text/css" />
<link href="{{servlet-context}}/css/tablet.css" media="only screen and (min-device-width: 481px) and (max-device-width: 1024px)" rel="stylesheet" type="text/css" />
<link href="{{servlet-context}}/css/standard.css" media="screen and (min-device-width: 1025px)" rel="stylesheet" type="text/css" />
<link href="{{servlet-context}}/content/stylesheet.css" media="screen and (min-device-width: 1025px)" rel="stylesheet" type="text/css" />
<link href="{{servlet-context}}/css/print.css" media="print" rel="stylesheet" type="text/css" />
<link href="{{servlet-context}}/css/states.css" rel="stylesheet" type="text/css" />
{% block extra-headers %}
{% endblock %}
</head>
@ -22,7 +19,6 @@
<img id="nav-icon" src="{{servlet-context}}/img/threelines.png" alt="Menu"/>
<ul id="nav-menu" class="nav">
<li class="{{wiki-selected}}"><a href="{{servlet-context}}/">Home</a></li>
<li class="{{edit-selected}}"><a href="{{servlet-context}}/edit?page={{title}}">Edit this page</a></li>
<li class="{{auth-selected}}"><a href="{{servlet-context}}/auth">
{% if user %}
Log out
@ -39,7 +35,6 @@
</div>
<div id="main-container" class="container">
{% if message %}
<div id="message">
<p class="message">{{message}}</p>

View file

@ -0,0 +1,22 @@
{% extends "templates/base.html" %}
{% block content %}
<div id="content" class="edit">
<form action="{{servlet-context}}/edit-css" method="POST">
<input type="hidden" name="page" value="{{page}}"/>
<textarea name="src" id="src" rows="25" cols="80">{{content}}</textarea>
<p class="widget">
<label for="summary">What have you changed?</label>
<input name="summary" id="summary" type="text"
value="{%if exists%}{%else%}New file {{title}}{%endif%}" required/>
</p>
<p class="widget">
<label for="submit">When you have finished editing</label>
<input name="submit" id="submit" type="submit" class="action" value="Save!"/>
</p>
</form>
</div>
<script>
var simplemde = new SimpleMDE();
</script>
{% endblock %}

View file

@ -1,9 +1,11 @@
{% extends "templates/base.html" %}
{% block content %}
<div id="content" class="wiki">
<div class="minor-controls">
<a href="history?page={{page}}">History</a>
</div>
<ul class="minor-controls">
<li><a href="{{servlet-context}}/edit?page={{title}}">Edit this page</a></li>
<li><a href="history?page={{page}}">History</a></li>
</ul>
{{content|safe}}
</div>
{% endblock %}

View file

@ -2,11 +2,12 @@
:author "Simon Brooke"}
smeagol.routes.wiki
(:require [clojure.walk :refer :all]
[clojure.java.io :as cjio]
[clojure.string :as cs]
[compojure.core :refer :all]
[clj-jgit.porcelain :as git]
[cemerick.url :refer (url url-encode url-decode)]
[markdown.core :as md]
[clojure.java.io :as cjio]
[noir.io :as io]
[noir.response :as response]
[noir.util.route :as route]
@ -44,11 +45,14 @@
(defn local-links
"Rewrite text in `html-src` surrounded by double square brackets as a local link into this wiki."
[^String html-src]
(clojure.string/replace html-src #"\[\[[^\[\]]*\]\]"
(cs/replace html-src #"\[\[[^\[\]]*\]\]"
#(let [text (clojure.string/replace %1 #"[\[\]]" "")
encoded (url-encode text)]
(timbre/debug (format "URL encode: '%s' -> '%s'" text encoded))
(format "<a href='wiki?page=%s'>%s</a>" encoded text))))
encoded (url-encode text)
;; I use '\_' to represent '_' in wiki markup, because
;; '_' is meaningful in Markdown. However, this needs to
;; be stripped out when interpreting local links.
munged (cs/replace encoded #"%26%2395%3B" "_")]
(format "<a href='wiki?page=%s'>%s</a>" munged text))))
(defn get-git-repo
@ -63,10 +67,10 @@
(defn process-source
"Process `source-text` and save it to the specified `file-path`, committing it
to Git and finally redirecting to wiki-page."
[params]
[params suffix]
(let [source-text (:src params)
page (:page params)
file-name (str page ".md")
file-name (str page suffix)
file-path (str (io/resource-path) "/content/" file-name)
exists? (.exists (clojure.java.io/as-file file-path))
git-repo (get-git-repo)
@ -77,30 +81,43 @@
(spit file-path source-text)
(if (not exists?) (git/git-add git-repo file-name))
(git/git-commit git-repo summary {:name user :email email})
(response/redirect (str "/wiki?page=" (url-encode page)))
))
(response/redirect
(str
"/wiki?page="
(if
(= suffix ".md")
(url-encode page)
"Introduction")))))
(defn edit-page
"Render a page in a text-area for editing. This could have been done in the same function as wiki-page,
and that would have been neat, but I couldn't see how to establish security if that were done."
[request]
([request]
(edit-page request "Introduction" ".md" "edit.html" "/content/_edit-left-bar.md"))
([request default suffix template left-bar]
(let [params (keywordize-keys (:params request))
src-text (:src params)
page (or (:page params) "Introduction")
file-path (str (io/resource-path) "content/" page ".md")
page (or (:page params) default)
file-path (str (io/resource-path) "content/" page suffix)
exists? (.exists (cjio/as-file file-path))]
(if (not exists?) (timbre/info (format "File '%s' not found; creating a new file" file-path)))
(cond src-text (process-source params)
(cond src-text (process-source params suffix)
true
(layout/render "edit.html"
(layout/render template
{:title (str "Edit " page)
:page page
:left-bar (local-links (util/md->html "/content/_edit-left-bar.md"))
:left-bar (local-links (util/md->html left-bar))
:header (local-links (util/md->html "/content/_header.md"))
:content (if exists? (io/slurp-resource (str "/content/" page ".md")) "")
:content (if exists? (io/slurp-resource (str "/content/" page suffix)) "")
:user (session/get :user)
:exists exists?}))))
:exists exists?})))))
(defn edit-css-page
"Render a stylesheet in a text-area for editing.."
[request]
(edit-page request "stylesheet" ".css" "edit-css.html" "/content/_edit-left-bar.md"))
(defn wiki-page
@ -236,6 +253,8 @@
(GET "/" request (wiki-page request))
(GET "/edit" request (route/restricted (edit-page request)))
(POST "/edit" request (route/restricted (edit-page request)))
(GET "/edit-css" request (route/restricted (edit-css-page request)))
(POST "/edit-css" request (route/restricted (edit-css-page request)))
(GET "/history" request (history-page request))
(GET "/version" request (version-page request))
(GET "/changes" request (diff-page request))