Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added article deletion/undeletion

  • Loading branch information...
commit e20b495299149707625044c0303d600c1a14b57f 1 parent 34d2767
Vladimir Sedach authored
2  TODO
... ... @@ -1,4 +1,4 @@
1   -* article deletion (404 on subsequent access but still have history)
  1 +* Scrub content before indexing
2 2 * create article button
3 3 * fix BS with clhs-lookup pathnames and Symbol-Table.text
4 4 * make sure ASDF-Install still works
72 cliki-convert/cliki-convert.lisp
@@ -22,7 +22,32 @@
22 22 do (setf content (fixup-tag regex content action)))
23 23 content))
24 24
25   -(defun load-old-articles (old-article-dir &key verbose)
  25 +(defun maybe-delete-article (article args)
  26 + (apply #'cliki2::delete-article article args))
  27 +
  28 +(defun import-revision (article content args)
  29 + (apply #'cliki2::add-revision article "import from CLiki" content args))
  30 +
  31 +(defun import-revisions (account article revision-paths)
  32 + (let ((timestamp-skew 0))
  33 + (dolist (path revision-paths)
  34 + (let* ((date (+ (incf timestamp-skew) (file-write-date path)))
  35 + (unix-date (local-time:timestamp-to-unix
  36 + (local-time:universal-to-timestamp date)))
  37 + (content (convert-article-revision (read-file path)))
  38 + (args (list :author account
  39 + :author-ip "0.0.0.0"
  40 + :date date))
  41 + (revision
  42 + (or (when (and (eq path (car (last revision-paths)))
  43 + (search "*(delete this page)"
  44 + content :test #'char-equal))
  45 + (maybe-delete-article article args))
  46 + (import-revision article content args))))
  47 + (sb-posix:utimes (cliki2::revision-path revision)
  48 + unix-date unix-date)))))
  49 +
  50 +(defun load-old-articles (old-article-dir)
26 51 "WARNING: This WILL blow away your old store."
27 52 (close-store)
28 53
@@ -33,11 +58,12 @@
33 58
34 59 (open-store (merge-pathnames "store/" cliki2::*datadir*))
35 60
36   - (let ((old-articles (make-hash-table :test 'equalp))) ;; equalp is case insensitive
  61 + (let ((old-articles (make-hash-table :test 'equalp))) ;; case insensitive
37 62 (dolist (file (cl-fad:list-directory old-article-dir))
38   - (let ((file-name (hunchentoot:url-decode
39   - (substitute #\% #\= (pathname-name file))
40   - hunchentoot::+latin-1+)))
  63 + (let ((file-name (cliki2::cut-whitespace
  64 + (hunchentoot:url-decode
  65 + (substitute #\% #\= (pathname-name file))
  66 + hunchentoot::+latin-1+))))
41 67 (setf (gethash file-name old-articles)
42 68 (merge 'list
43 69 (list file)
@@ -46,40 +72,20 @@
46 72 :key (lambda (x)
47 73 (parse-integer (or (pathname-type x) "0")
48 74 :junk-allowed t))))))
49   - ;; discard deleted pages
50   - (loop for article being the hash-key of old-articles do
51   - (when (search "*(delete this page)"
52   - (read-file (car (last (gethash article old-articles))))
53   - :test #'char-equal)
54   - (remhash article old-articles)))
  75 +
55 76 ;; import into store
56 77 (let ((cliki-import-user (make-instance 'cliki2::account
57 78 :name "CLiki-importer"
58 79 :email "noreply@cliki.net"
59 80 :password-salt "000000"
60 81 :password-digest "nohash")))
61   - (loop for i from 0
62   - for article-title being the hash-key of old-articles
63   - for files being the hash-value of old-articles do
64   - (let ((article (make-instance 'cliki2::article :title article-title))
65   - (timestamp-skew 0)) ;; some revisions have identical timestamps
66   - (when verbose
67   - (format t "~A%; Convert ~A~%"
68   - (floor (* (/ i (hash-table-count old-articles)) 100))
69   - article-title))
70   - (dolist (file files)
71   - (let* ((date (+ (incf timestamp-skew) (file-write-date file)))
72   - (revision (cliki2::add-revision
73   - article
74   - "import from CLiki"
75   - (convert-article-revision (read-file file))
76   - :author cliki-import-user
77   - :author-ip "0.0.0.0"
78   - :date date)))
79   - (let ((unix-time (local-time:timestamp-to-unix
80   - (local-time:universal-to-timestamp date))))
81   - (sb-posix:utimes (cliki2::revision-path revision)
82   - unix-time unix-time))))))))
  82 + (loop for article-title being the hash-key of old-articles
  83 + for revision-paths being the hash-value of old-articles do
  84 + (import-revisions
  85 + cliki-import-user
  86 + (make-instance 'cliki2::article :title article-title)
  87 + revision-paths))))
  88 +
83 89 (cliki2::init-recent-revisions)
84 90 (snapshot))
85 91
3  cliki2.asd
@@ -32,5 +32,8 @@
32 32 (:file "diff")
33 33 (:file "search")
34 34 (:file "recent-changes")
  35 + (:file "deleted-articles")
  36 + (:file "history")
35 37 (:file "tools")
  38 + (:file "dispatcher")
36 39 (:file "start")))))
134 src/article.lisp
... ... @@ -1,16 +1,17 @@
1 1 (in-package #:cliki2)
2 2 (in-readtable cliki2)
3 3
4   -;;; delete article (only logged-in users can delete, view, and undelete deleted articles)
5   -
6 4 (defun cut-whitespace (str)
7 5 (string-trim #(#\Space #\Tab #\Newline #\Return)
8 6 (ppcre:regex-replace-all "\\s+" str " ")))
9 7
10 8 ;;; article categories
11 9
  10 +(defun canonicalize (title)
  11 + (string-downcase (cut-whitespace title)))
  12 +
12 13 (defun category-keyword (category-title)
13   - (intern (string-upcase (cut-whitespace category-title)) '#:cliki2.categories))
  14 + (intern (canonicalize category-title) '#:cliki2.categories))
14 15
15 16 (defun content-categories (content)
16 17 (let (categories)
@@ -42,7 +43,7 @@
42 43 canonical-title (string-downcase title))))
43 44
44 45 (defun find-article (title)
45   - (article-with-canonical-title (string-downcase (cut-whitespace title))))
  46 + (article-with-canonical-title (canonicalize title)))
46 47
47 48 (defun latest-revision (article)
48 49 (car (revisions article)))
@@ -50,11 +51,11 @@
50 51 (defun article-description (article)
51 52 (ppcre:scan-to-strings ".*?(\\.(\\s|$)|\\n|$)" (cached-content article)))
52 53
53   -(defmethod link-to ((article article))
  54 +(defmethod link-to ((article store-object))
54 55 (link-to (canonical-title article)))
55 56
56 57 (defmethod link-to ((article-titled string))
57   - #?[/${(uri-encode (string-downcase (cut-whitespace article-titled)))}])
  58 + #?[/${(uri-encode (canonicalize article-titled))}])
58 59
59 60 (defun %print-article-link (title class)
60 61 #H[<a href="${(link-to title)}" class="${class}">${title}</a>])
@@ -92,8 +93,9 @@
92 93 (author (or *account*
93 94 (get-anonymous-account (real-remote-addr))))
94 95 (author-ip (real-remote-addr))
95   - (date (get-universal-time)))
96   - (let ((new-revision (make-instance 'revision
  96 + (date (get-universal-time))
  97 + (revision-type 'revision))
  98 + (let ((new-revision (make-instance revision-type
97 99 :article article
98 100 :author author
99 101 :author-ip author-ip
@@ -125,12 +127,17 @@
125 127 (loop for category in it for divider = nil then t do
126 128 (when divider #H" | ") (pprint-category-link category))
127 129 #H[</div>])
128   - (setf *footer*
129   - (let ((title (title (article revision))))
130   - #?[
131   -<li><a href="${(link-to (article revision))}">Current version</a></li>
132   -<li><a href="$(#/site/history?title={title})">History</a></li>
133   -<li>${(link-to-edit revision "Edit")}</li>])))
  130 + (setf
  131 + *footer*
  132 + (let ((title (title (article revision))))
  133 + (with-output-to-string (*html-stream*)
  134 + #H[<li><a href="${(link-to (article revision))}">Current version</a></li>
  135 + <li><a href="$(#/site/history?title={title})">History</a></li>]
  136 + (unless (youre-banned?)
  137 + #H[<li>${(link-to-edit revision "Edit")}</li>]
  138 + (when *account*
  139 + #H[<li><form method="post" action="$(#/site/delete?title={title})">
  140 + <input class="del" type="submit" value="Delete" /></form></li>]))))))
134 141
135 142 (defun find-revision (string-id)
136 143 (let ((revision (store-object-with-id (parse-integer string-id))))
@@ -146,90 +153,12 @@
146 153 (defun pprint-revision-link (revision)
147 154 #H[<a class="internal" href="${(link-to revision)}">${(rfc-1123-date (date revision))}</a>])
148 155
149   -;;; article history
150   -
151   -(defpage /site/history () (title)
152   - (awhen (find-article title)
153   - (setf *title* #?'History of article: "${title}"')
154   - #H[<h1>History of article ] (pprint-article-link title) #H[</h1>
155   - <form method="post" action="$(#/site/do-compare-revisions)">
156   - <input type="submit" value="Compare selected versions" />
157   - <table id="pagehistory">]
158   -
159   - (loop for rhead on (revisions it)
160   - for revision = (car rhead)
161   - for author = (author revision)
162   - for first = t then nil do
163   - (flet ((radio (x)
164   - #H[<td><input type="radio" name="${x}" value="${(store-object-id revision)}" /></td>]))
165   - #H[<tr><td>]
166   - (awhen (cadr rhead)
167   - #H[(<a href="$(#/site/compare-revisions?old={(store-object-id it)}&diff={(store-object-id revision)})">prev</a>)])
168   - #H[</td>]
169   - (radio "old") (radio "diff")
170   - #H[<td>] (pprint-revision-link revision)
171   - #H[ ${(format-account-link author)} (<em>${(summary revision)}</em>) ]
172   - (when first
173   - #H[(<a href="$(#/site/undo?r={(store-object-id revision)})">undo</a>)])
174   - #H[</td></tr>]))
175   -
176   - #H[</table>
177   - <input type="submit" value="Compare selected versions" />
178   - </form>]
179   -
180   - (setf *footer* #?[<li><a href="${(link-to it)}">Current version</a></li>])))
181   -
182   -(defun check-banned ()
183   - (when (youre-banned?) #H[Your account/IP is banned from editing]))
184   -
185   -(defpage /site/undo () (r)
186   - (let* ((revision (find-revision r))
187   - (article (article revision)))
188   - (cond ((check-banned))
189   - ((eq revision (latest-revision article))
190   - (add-revision article
191   - #?"undid last revision by ${(name (author revision))}"
192   - (revision-content (second (revisions article))))
193   - (redirect (link-to article)))
194   - (t #H[Can't undo this revision because it is not the latest.
195   - <a href="$(#/site/history?title={(title article)})">Go back to history page</a>.]))))
196   -
197   -;;; diff
198   -
199   -(defhandler /site/do-compare-revisions (old diff)
200   - #/site/compare-revisions?old={old}&diff={diff})
201   -
202   -(defpage /site/compare-revisions () (old diff)
203   - (let ((oldr (find-revision old))
204   - (diffr (find-revision diff)))
205   - (when (> (date oldr) (date diffr))
206   - (rotatef oldr diffr))
207   - (setf *title* (title (article oldr)))
208   - #H[<h1>${(title (article oldr))}</h1>
209   - <table class="diff">
210   - <colgroup>
211   - <col class="diff-marker"> <col class="diff-content">
212   - <col class="diff-marker"> <col class="diff-content">
213   - </colgroup>
214   - <tbody>
215   - <tr>
216   - <th colspan="2"> Version ] (pprint-revision-link oldr)
217   - #H[ (${(link-to-edit oldr "edit")})</th>
218   - <th colspan="2"> Version ] (pprint-revision-link diffr)
219   - #H[ (${(link-to-edit diffr "edit")})]
220   - (when (eq diffr (latest-revision (article diffr)))
221   - #H[ (<a href="$(#/site/undo?r={(store-object-id diffr)})">undo</a>)])
222   - #H[</th>
223   - </tr>
224   - ${(diff:format-diff-string 'wiki-diff (revision-path oldr) (revision-path diffr))}
225   - </tbody>
226   - </table>]))
227   -
228 156 ;;; edit article
229 157
230 158 (defpage /site/edit-article () (title content summary from-revision save)
231 159 (let ((maybe-article (find-article title)))
232 160 (cond ((check-banned))
  161 + ((find-deleted-article title) (redirect (link-to title)))
233 162 (save (add-revision maybe-article summary content)
234 163 (redirect (link-to maybe-article)))
235 164 (t (setf *title* #?"Editing ${title}")
@@ -257,22 +186,3 @@
257 186 (when content
258 187 #H[<h1>Article preview:</h1>]
259 188 (generate-html-from-markup content))))))
260   -
261   -;;; article dispatcher
262   -
263   -(defun guess-article-name ()
264   - (uri-decode (subseq (script-name*) 1)))
265   -
266   -(defun render-article (article)
267   - (let ((*header* #?[<link rel="alternate" type="application/rss+xml" title="edits"
268   - href="$(#/site/article-feed/rss.xml?title={(title article)})">]))
269   - (render-page (title article)
270   - (render-revision (latest-revision article) (cached-content article)))))
271   -
272   -(defun article-dispatcher (request)
273   - (declare (ignore request))
274   - (awhen (find-article (guess-article-name))
275   - (lambda () (render-article it))))
276   -
277   -(define-easy-handler (root :uri "/") ()
278   - (render-article (find-article "index")))
80 src/deleted-articles.lisp
... ... @@ -0,0 +1,80 @@
  1 +(in-package #:cliki2)
  2 +(in-readtable cliki2)
  3 +
  4 +(defclass deleted-article (store-object)
  5 + ((title :initarg :title
  6 + :reader title)
  7 + (canonical-title :initarg :canonical-title
  8 + :reader canonical-title
  9 + :index-type string-unique-index
  10 + :index-reader deleted-article-with-title)
  11 + (revisions :initarg :revisions
  12 + :reader revisions))
  13 + (:metaclass persistent-class))
  14 +
  15 +(defun find-deleted-article (title)
  16 + (deleted-article-with-title (canonicalize title)))
  17 +
  18 +(defun find-article-any (title)
  19 + (or (find-article title) (find-deleted-article title)))
  20 +
  21 +(defmethod pprint-article-summary-li ((article deleted-article) separator)
  22 + #H[<li>] (pprint-article-link (title article)) #H[ ${separator} </li>])
  23 +
  24 +(defun %move-revisions (old-article new-article)
  25 + (dolist (r (revisions old-article))
  26 + (setf (slot-value r 'article) new-article)))
  27 +
  28 +(defclass revision-undelete (revision) ()
  29 + (:metaclass persistent-class))
  30 +
  31 +(deftransaction tx-delete-article (article)
  32 + (let ((deleted (make-instance 'deleted-article
  33 + :title (title article)
  34 + :canonical-title (canonical-title article)
  35 + :revisions (revisions article))))
  36 + (%move-revisions article deleted)))
  37 +
  38 +(defun delete-article (article &rest args)
  39 + (prog1 (apply #'add-revision article "Deleted article" "" args)
  40 + (tx-delete-article article)
  41 + (delete-object article)))
  42 +
  43 +(deftransaction tx-undelete-article (deleted)
  44 + (let ((article (make-instance 'article :title (title deleted))))
  45 + (setf (slot-value article 'revisions) (revisions deleted))
  46 + (%move-revisions deleted article)
  47 + article))
  48 +
  49 +(defun undelete-article (deleted)
  50 + (let ((article (tx-undelete-article deleted)))
  51 + (add-revision article "Undeleted article"
  52 + (revision-content (second (revisions article)))
  53 + :revision-type 'revision-undelete)
  54 + (delete-object deleted)
  55 + article))
  56 +
  57 +(defhandler /site/delete (title)
  58 + (awhen (and (not (youre-banned?))
  59 + (not (find-deleted-article title))
  60 + (find-article title))
  61 + (delete-article it))
  62 + (link-to title))
  63 +
  64 +(deftransaction tx-permadelete (deleted-article)
  65 + (dolist (r (revisions deleted-article))
  66 + (setf *recent-revisions* (remove r *recent-revisions*))
  67 + (delete-object r)))
  68 +
  69 +(defhandler /site/permadelete (title)
  70 + (awhen (and (not (youre-banned?))
  71 + (account-is? *account* :moderator :administrator)
  72 + (find-deleted-article title))
  73 + (tx-permadelete it)
  74 + (delete-object it))
  75 + #/)
  76 +
  77 +(defhandler /site/undelete (title)
  78 + (awhen (and (not (youre-banned?)) (find-deleted-article title))
  79 + (undelete-article it))
  80 + (link-to title))
60 src/dispatcher.lisp
... ... @@ -0,0 +1,60 @@
  1 +(in-package #:cliki2)
  2 +(in-readtable cliki2)
  3 +
  4 +(defun guess-article-name ()
  5 + (uri-decode (subseq (script-name*) 1)))
  6 +
  7 +(defun delete-button (how article value)
  8 + #H[<li><form method="post"
  9 + action="$(#/site/{how}delete?title={(title article)})">
  10 + <input class="del" type="submit" value="${value}" />
  11 + </form>
  12 + </li>])
  13 +
  14 +(defun show-deleted-article-page (article)
  15 + (setf (return-code*)
  16 + 404
  17 + *footer*
  18 + (with-output-to-string (*html-stream*)
  19 + #H[<li><a href="$(#/site/history?title={(title article)})">History</a></li>]
  20 + (unless (youre-banned?)
  21 + (delete-button "un" article "Undelete")
  22 + (when (account-is? *account* :moderator :administrator)
  23 + (delete-button "perma" article "Delete permanently")))))
  24 + #H[Article was deleted.])
  25 +
  26 +(defun render-article (article)
  27 + (let ((*header* #?[<link rel="alternate" type="application/rss+xml" title="edits"
  28 + href="$(#/site/article-feed/rss.xml?title={(title article)})">]))
  29 + (render-page (title article)
  30 + (if (typep article 'deleted-article)
  31 + (show-deleted-article-page article)
  32 + (render-revision (latest-revision article) (cached-content article))))))
  33 +
  34 +(defun article-dispatcher (request)
  35 + (declare (ignore request))
  36 + (aif (find-article-any (guess-article-name))
  37 + (lambda () (render-article it))
  38 + (lambda ()
  39 + (setf (return-code*) 404)
  40 + (with-account
  41 + (render-page "Article not found"
  42 + #H[<h1>Cliki does not have an article with this exact name</h1>
  43 + <a href="$(#/site/edit-article?title={(guess-article-name)})">Create</a>])))))
  44 +
  45 +(define-easy-handler (root :uri "/") ()
  46 + (render-article (find-article "index")))
  47 +
  48 +(defmethod acceptor-status-message :around ((acceptor easy-acceptor)
  49 + status-code &key &allow-other-keys)
  50 + (unless (equal status-code 404)
  51 + (call-next-method)))
  52 +
  53 +(setf *dispatch-table*
  54 + (list
  55 + (hunchentoot:create-folder-dispatcher-and-handler
  56 + "/static/"
  57 + (merge-pathnames #p"static/"
  58 + (asdf:component-pathname (asdf:find-system :cliki2))))
  59 + 'dispatch-easy-handlers
  60 + 'article-dispatcher))
96 src/history.lisp
... ... @@ -0,0 +1,96 @@
  1 +(in-package #:cliki2)
  2 +(in-readtable cliki2)
  3 +
  4 +(defun output-undo-link (revision)
  5 + (unless (youre-banned?)
  6 + #H[<form method="post" action="$(#/site/history-special)">(<input type= "hidden" name="r" value="${(store-object-id revision)}"/><input class="undo" type="submit" name="undo" value="undo" />)</form>]))
  7 +
  8 +(defpage /site/history () (title)
  9 + (awhen (find-article-any title)
  10 + (setf *title* #?'History of article: "${title}"')
  11 +
  12 + #H[<h1>History of article ] (pprint-article-link title) #H[</h1>
  13 + <form method="post" action="$(#/site/history-special)">
  14 + <input type="submit" value="Compare selected versions" />
  15 + <table id="pagehistory">]
  16 +
  17 + (loop for rhead on (revisions it)
  18 + for revision = (car rhead)
  19 + for author = (author revision)
  20 + for first = t then nil do
  21 + (flet ((radio (x)
  22 + #H[<td><input type="radio" name="${x}" value="${(store-object-id revision)}" /></td>]))
  23 + #H[<tr><td>]
  24 + (awhen (cadr rhead)
  25 + #H[(<a href="$(#/site/compare-revisions?old={(store-object-id it)}&diff={(store-object-id revision)})">prev</a>)])
  26 + #H[</td>]
  27 + (radio "old") (radio "diff")
  28 + #H[<td>] (pprint-revision-link revision)
  29 + #H[ ${(format-account-link author)} (<em>${(summary revision)}</em>) ]
  30 + (when first
  31 + (output-undo-link revision))
  32 + #H[</td></tr>]))
  33 +
  34 + #H[</table>
  35 + <input type="submit" value="Compare selected versions" />
  36 + </form>]
  37 +
  38 + (setf *footer* #?[<li><a href="${(link-to it)}">Current version</a></li>])))
  39 +
  40 +(defpage /site/compare-revisions () (old diff)
  41 + (let* ((oldr (find-revision old))
  42 + (diffr (find-revision diff))
  43 + (title (title (article oldr))))
  44 + (when (> (date oldr) (date diffr))
  45 + (rotatef oldr diffr))
  46 + (setf *title* title)
  47 + #H[<h1><a class="internal" href="${(link-to title)}">${title}</a></h1>
  48 + <table class="diff">
  49 + <colgroup>
  50 + <col class="diff-marker"> <col class="diff-content">
  51 + <col class="diff-marker"> <col class="diff-content">
  52 + </colgroup>
  53 + <tbody>
  54 + <tr>
  55 + <th colspan="2"> Version ] (pprint-revision-link oldr)
  56 + #H[ (${(link-to-edit oldr "edit")})</th>
  57 + <th colspan="2"> Version ] (pprint-revision-link diffr)
  58 + #H[ (${(link-to-edit diffr "edit")}) ]
  59 + (when (eq diffr (latest-revision (article diffr)))
  60 + (output-undo-link diffr))
  61 + #H[</th>
  62 + </tr>
  63 + ${(diff:format-diff-string 'wiki-diff (revision-path oldr) (revision-path diffr))}
  64 + </tbody>
  65 + </table>]))
  66 +
  67 +;;; undo
  68 +
  69 +(defun check-banned ()
  70 + (when (youre-banned?) #H[Your account/IP is banned from editing]))
  71 +
  72 +(defpage /site/not-latest "Revision not the latest" (title)
  73 + #H[Can't undo this revision because it is not the latest.
  74 + <a href="$(#/site/history?title={title})">Go back to history page</a>.])
  75 +
  76 +(defun undo (r)
  77 + (let* ((revision (find-revision r))
  78 + (article (article revision))
  79 + (latest-revision (latest-revision article)))
  80 + (cond ((check-banned))
  81 + ((typep article 'deleted-article)
  82 + (link-to (undelete-article article)))
  83 + ((eq revision latest-revision)
  84 + (prog1 (link-to article)
  85 + (if (typep latest-revision 'revision-undelete)
  86 + (delete-article article)
  87 + (add-revision
  88 + article
  89 + #?"undid last revision by ${(name (author revision))}"
  90 + (revision-content (second (revisions article)))))))
  91 + (t #/site/not-latest?title={(title article)}))))
  92 +
  93 +(defhandler /site/history-special (old diff undo r)
  94 + (if undo
  95 + (undo r)
  96 + #/site/compare-revisions?old={old}&diff={diff}))
8 src/html-rendering.lisp
@@ -66,11 +66,3 @@
66 66 (render-header)
67 67 (princ body *html-stream*)
68 68 (render-footer))))
69   -
70   -(defmethod acceptor-status-message :around ((acceptor easy-acceptor) status-code &key &allow-other-keys) ;; blah, hunchentoot 1.2 is annoying
71   - (if (equal status-code 404)
72   - (with-account
73   - (render-page "Article not found"
74   - #H[<h1>Cliki2 does not have an article with this exact name</h1>
75   - <a href="$(#/site/edit-article?title={(guess-article-name)})">Create</a>]))
76   - (call-next-method)))
5 src/http-resource.lisp
@@ -12,4 +12,7 @@
12 12 (render-page ,title ,@body)))
13 13
14 14 (defmacro defhandler (page parameters &body body)
15   - `(%defpage ,page :post ,parameters (redirect (progn ,@body) :code 303)))
  15 + `(%defpage ,page :post ,(mapcar (lambda (p)
  16 + (list p :request-type :both))
  17 + parameters)
  18 + (redirect (progn ,@body) :code 303)))
2  src/markup.lisp
@@ -65,7 +65,7 @@
65 65 (funcall formatter r1)))
66 66 :simple-calls t))
67 67
68   -(defun pprint-article-summary-li (article separator)
  68 +(defmethod pprint-article-summary-li ((article article) separator)
69 69 #H[<li>] (pprint-article-link (title article)) #H[ ${separator}
70 70 ${(sanitize:clean (with-output-to-string (*html-stream*)
71 71 (generate-html-from-markup (article-description article)))
2  src/recent-changes.lisp
@@ -55,7 +55,7 @@
55 55 </item>])))))
56 56
57 57 (%defpage /site/article-feed/rss.xml :get (title)
58   - (awhen (find-article title)
  58 + (awhen (find-article-any title)
59 59 (let ((description #?"CLiki Article ${title} Edits"))
60 60 (rss-doc description #/site/article-feed/rss.xml?title={title} description
61 61 (lambda ()
17 src/start.lisp
@@ -5,15 +5,6 @@
5 5 (close-store)
6 6 (open-store (merge-pathnames "store/" *datadir*))
7 7
8   -(setf *dispatch-table*
9   - (list
10   - (hunchentoot:create-folder-dispatcher-and-handler
11   - "/static/"
12   - (merge-pathnames #p"static/"
13   - (asdf:component-pathname (asdf:find-system :cliki2))))
14   - 'dispatch-easy-handlers
15   - 'article-dispatcher))
16   -
17 8 (init-recent-revisions)
18 9
19 10 (dolist (unreferenced-uri (set-difference %referenced-uris %defined-uris
@@ -21,4 +12,10 @@
21 12 (warn "Reference warning: referencing unknown URI resource ~a in file ~a"
22 13 (car unreferenced-uri) (cdr unreferenced-uri)))
23 14
24   -(hunchentoot:start (make-instance 'hunchentoot:easy-acceptor :port 8080))
  15 +(defvar %acceptor
  16 + (let ((acceptor (make-instance 'hunchentoot:easy-acceptor :port 8080)))
  17 + ;(setf (hunchentoot:acceptor-error-template-directory acceptor) "/home/viper/opt/hunchentoot/www/errors/")
  18 + (hunchentoot:start acceptor)
  19 + acceptor))
  20 +
  21 +
4 src/tools.lisp
@@ -7,6 +7,7 @@
7 7 <li><a href="$(#/site/all-articles)">All CLiki articles</a></li>
8 8 <li><a href="$(#/site/blacklist)">Blacklist of users/IPs</a></li>
9 9 <li><a href="$(#/site/uncategorized)">Uncategorized articles</a></li>
  10 + <li><a href="$(#/site/deleted-articles)">Deleted articles</a></li>
10 11 </ul>])
11 12
12 13 (defpage /site/blacklist "Blacklist" ()
@@ -23,3 +24,6 @@
23 24 (paginate-article-summaries
24 25 start
25 26 (remove-if #'category-list (store-objects-with-class 'article))))
  27 +
  28 +(defpage /site/deleted-articles "Deleted articles" (start)
  29 + (paginate-article-summaries start (store-objects-with-class 'deleted-article)))
28 static/css/style.css
@@ -256,7 +256,7 @@ pre, pre *, .code, .code * { font-family: monospace; }
256 256 #pagehistory a { text-decoration:none; }
257 257
258 258 table.diff { border: none; border-spacing: 4px; table-layout: fixed;}
259   -table.diff a { text-decoration: none; color: #0077bb; font-size: large;}
  259 +table.diff a { text-decoration: none; color: #0077bb; font-size: 18px;}
260 260 table.diff col.diff-content { width: 48%; }
261 261 td.diff-marker {font-size: smaller; text-align: right;}
262 262 td.diff-line-number { font-weight: bold; }
@@ -294,4 +294,30 @@ fieldset {
294 294
295 295 .error-info {
296 296 color:red;
  297 +}
  298 +
  299 +.del {
  300 + border:0;
  301 + margin:0;
  302 + background:none;
  303 + font-size:16px;
  304 + color:white;
  305 + padding: 0 12px;
  306 + height: 35px;
  307 +}
  308 +
  309 +.del:hover {
  310 + cursor:pointer;
  311 +}
  312 +
  313 +.undo {
  314 + border:0;
  315 + margin:0;
  316 + background:none;
  317 + font-size:18px;
  318 + color:#0645AD;
  319 +}
  320 +
  321 +.undo:hover {
  322 + cursor:pointer;
297 323 }

0 comments on commit e20b495

Please sign in to comment.
Something went wrong with that request. Please try again.