mirror of
https://github.com/journeyman-cc/smeagol.git
synced 2026-04-12 18:05:06 +00:00
That proved a little more convoluted than expected, but now works well.
This commit is contained in:
parent
06773bd6f7
commit
ebfefd3edb
6 changed files with 390 additions and 56 deletions
|
|
@ -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]].
|
||||
|
|
|
|||
296
resources/public/content/stylesheet.css
Normal file
296
resources/public/content/stylesheet.css
Normal 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;
|
||||
}
|
||||
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
22
resources/templates/edit-css.html
Normal file
22
resources/templates/edit-css.html
Normal 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 %}
|
||||
|
|
@ -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 %}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue