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,31 +35,30 @@
</div>
<div id="main-container" class="container">
{% if message %}
<div id="message">
<p class="message">{{message}}</p>
</div>
{% endif %}
{% if error %}
<div id="error">
<p class="error">{{error}}</p>
</div>
{% endif %}
{% if message %}
<div id="message">
<p class="message">{{message}}</p>
</div>
{% endif %}
{% if error %}
<div id="error">
<p class="error">{{error}}</p>
</div>
{% endif %}
{% block content %}
{% endblock %}
{% block content %}
{% endblock %}
</div>
<div id="cookies">
<div id="more-about-cookies">
This website stores session information as a 'cookie' on your browser. This helps us show you the content
you want to see. This cookie does not identify you, and cannot be read by other websites. It is deleted by
your browser as soon as you leave this site. This website does not use any third party cookies, so your
visit here cannot be tracked by other websites.
</div>
<div id="about-cookies">
About cookies
</div>
<div id="more-about-cookies">
This website stores session information as a 'cookie' on your browser. This helps us show you the content
you want to see. This cookie does not identify you, and cannot be read by other websites. It is deleted by
your browser as soon as you leave this site. This website does not use any third party cookies, so your
visit here cannot be tracked by other websites.
</div>
<div id="about-cookies">
About cookies
</div>
</div>
<div id="footer">
<div id="credits">

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]
(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) 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 suffix)
true
(layout/render template
{:title (str "Edit " page)
:page page
: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 suffix)) "")
:user (session/get :user)
:exists exists?})))))
(defn edit-css-page
"Render a stylesheet in a text-area for editing.."
[request]
(let [params (keywordize-keys (:params request))
src-text (:src params)
page (or (:page params) "Introduction")
file-path (str (io/resource-path) "content/" page ".md")
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)
true
(layout/render "edit.html"
{:title (str "Edit " page)
:page page
:left-bar (local-links (util/md->html "/content/_edit-left-bar.md"))
:header (local-links (util/md->html "/content/_header.md"))
:content (if exists? (io/slurp-resource (str "/content/" page ".md")) "")
:user (session/get :user)
:exists exists?}))))
(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))