;;;; -*- coding: utf-8; mode: lisp -*- ;;;; Copyright 2007-2009, Matthias Andreas Benkard. ;;;------------------------------------------------------------------------ ;;; This file is part of The Mulkblog Project. ;;; ;;; The Mulkblog Project is free software. You can redistribute it and/or ;;; modify it under the terms of the Affero General Public License as ;;; published by Affero, Inc.; either version 1 of the License, or ;;; (at your option) any later version. ;;; ;;; The Mulkblog Project 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 ;;; Affero General Public License for more details. ;;; ;;; You should have received a copy of the Affero General Public ;;; License in the COPYING file that comes with The Mulkblog Project; if ;;; not, write to Affero, Inc., 510 Third Street, Suite 225, San ;;; Francisco, CA 94107 USA. ;;;------------------------------------------------------------------------ (in-package #:mulk.journal) (defun link-to (action &key comment-id post-id (absolute nil)) (with-output-to-string (out) (format out "~A" (if absolute "http://matthias.benkard.de/journal" ;; When testing on the local webserver, don't ;; use /journal as a relative URI, because it ;; won't work. (if (eq *site* :mst-plus) (http-getenv "SCRIPT_NAME") "/journal"))) (multiple-value-call #'(lambda (&rest args) (apply #'format out args)) (ecase action (:index "") (:full-index "/?full") (:view-atom-feed (values "/feed")) (:view-comment-feed (cond (post-id (values "/~D/comment-feed" post-id)) (t "/comment-feed"))) (:view (cond (comment-id (values "/~D#comment-~D" post-id comment-id)) (post-id (values "/~D" post-id)) (t "/"))) ((:edit :preview) (values "/~D/preview" post-id)) (:post-comment (values "/~D" post-id)) (:trackback (values "/~D/trackback" post-id)) (:view-atom-entry (values "/~D/atom" post-id)) (:save (values "/~D/save" post-id)) (:moderation-page "/moderate") (:css "/journal.css") (:prettify.css "/prettify/prettify.css") (:prettify.js "/prettify/prettify.js") (:prettify-lisp.js "/prettify/lang-lisp.js") (:pingback "/rpc"))))) (defun show-comment-feed () #.(locally-enable-sql-reader-syntax) (revalidate-cache-or-die "application/atom+xml; charset=UTF-8") (when (eq *mode* :http) (http-add-header "Last-Modified" (http-timestamp (compute-journal-last-modified-date))) (http-add-header "Content-Language" "de") (http-send-headers "application/atom+xml; charset=UTF-8")) (flet ((atom-time (time) (format-date nil "%4yr%-%2mon%-%2day%T%2hr%:%2min%:%2sec%Z" time 0))) (with-xml-output (*standard-output* :encoding "utf-8") (with-tag ("feed" '(("xmlns" "http://www.w3.org/2005/Atom"))) (with-tag ("title") (xml-as-is "Kommentare — Kompottkins Weisheiten")) (emit-simple-tags :updated (atom-time (max (or (single-object (select [max [slot-value 'journal-entry 'date]] :from [journal-entry] :flatp t)) 0) (or (single-object (select [max [slot-value 'journal-entry 'last-modification]] :from [journal-entry] :flatp t)) 0))) :id "urn:uuid:9cd7a24c-10a6-4895-a97b-8df6b426e4a0") (with-tag ("subtitle") (xml-as-is "Geschwafel zum Geschwafel eines libertärsozialistischen Geeks")) (with-tag ("author") (emit-simple-tags :name "Various")) (with-tag ("link" `(("rel" "alternate") ("type" "text/html") ("href" ,(link-to :index :absolute t))))) (with-tag ("link" `(("rel" "self") ("type" "application/atom+xml") ("href" ,(if *post-number* (link-to :view-comment-feed :post-id *post-number* :absolute t) (link-to :view-comment-feed :absolute t)))))) (let ((number 0)) (dolist (journal-comment (select 'journal-comment :where [= [slot-value 'journal-comment 'spam-p] "f"] :order-by '(([date] :desc)) :flatp t)) (with-slots (entry uuid date body author website spam-p id) journal-comment (when (and (not spam-p) (or (not *post-number*) (= (id-of entry) *post-number*))) (incf number) (with-tag ("entry") (emit-simple-tags :title (format nil "Kommentar zu: ~A" (title-of entry)) :id (format nil "urn:uuid:~(~A~)" uuid) :updated (atom-time date) :published (atom-time date)) (with-tag ("link" `(("rel" "alternate") ("type" "text/html") ("href" ,(link-to :view :comment-id id :post-id (id-of entry) :absolute t))))) (when (<= number 8) ;; We only include the body for the most recent ;; posts in order to save bandwidth. (with-tag ("content" `(("type" "xhtml") ("xml:lang" "de") ("xml:base" ,(link-to :index :absolute t)))) (with-tag ("div" '(("xmlns" "http://www.w3.org/1999/xhtml"))) (xml-as-is (with-yaclml-output-to-string (<:as-html (render-comment-body body))))))))))))))) #.(restore-sql-reader-syntax-state)) (defun show-atom-entry () #.(locally-enable-sql-reader-syntax) (revalidate-cache-or-die "application/atom+xml; charset=UTF-8") (when (eq *mode* :http) (http-add-header "Last-Modified" (http-timestamp (compute-journal-last-modified-date))) (http-add-header "Content-Language" "de") (http-send-headers "application/atom+xml; charset=UTF-8")) (with-xml-output (*standard-output* :encoding "utf-8") (show-atom-entry-xml (find-entry *post-number*) :full-content t :include-edit-links t))) (defun show-atom-entry-xml (journal-entry &key full-content include-edit-links) (flet ((atom-time (time) (format-date nil "%4yr%-%2mon%-%2day%T%2hr%:%2min%:%2sec%Z" time 0))) (with-slots (title date body categories last-modification id) journal-entry (with-tag ("entry") (with-tag ("title" `(("type" "html"))) (xml-as-is title)) (emit-simple-tags :id (format nil "urn:uuid:~(~A~)" (uuid-of journal-entry)) :updated (atom-time (or last-modification date)) :published (atom-time date)) (with-tag ("link" `(("rel" "alternate") ("type" "text/html") ("href" ,(link-to :view :post-id id :absolute t))))) (when include-edit-links (with-tag ("link" `(("rel" "service.edit") ("type" "application/atom+xml") ("href" ,(link-to :view-atom-entry :post-id id :absolute t)) ("title" ,title))))) (when full-content ;; Escaped HTML or embedded XHTML? What shall we prefer? #+(or) (with-tag ("content" `(("type" "html") ("xml:lang" "de") ("xml:base" ,(link-to :index :absolute t)))) (xml-out (if (equal (entry-type-of journal-entry) "html") (body-of journal-entry) (journal-markup->html (body-of journal-entry))))) (with-tag ("content" `(("type" "xhtml") ("xml:lang" "de") ("xml:base" ,(link-to :index :absolute t)))) (with-tag ("div" '(("xmlns" "http://www.w3.org/1999/xhtml"))) (xml-as-is (htmlise-entry journal-entry)))))))) #.(restore-sql-reader-syntax-state)) (defun htmlise-entry (journal-entry) (if (equal (entry-type-of journal-entry) "html") (body-of journal-entry) (journal-markup->html (body-of journal-entry)))) (defun show-atom-feed (&key include-edit-links full-content) #.(locally-enable-sql-reader-syntax) (revalidate-cache-or-die "application/atom+xml; charset=UTF-8") (when (eq *mode* :http) (http-add-header "Last-Modified" (http-timestamp (compute-journal-last-modified-date))) (http-add-header "Content-Language" "de") (http-send-headers "application/atom+xml; charset=UTF-8")) (flet ((atom-time (time) (format-date nil "%4yr%-%2mon%-%2day%T%2hr%:%2min%:%2sec%Z" time 0))) (with-xml-output (*standard-output* :encoding "utf-8") (with-tag ("feed" '(("xmlns" "http://www.w3.org/2005/Atom"))) (emit-simple-tags :title "Kompottkins Weisheiten" :updated (atom-time (max (or (single-object (select [max [slot-value 'journal-entry 'date]] :from [journal-entry] :flatp t)) 0) (or (single-object (select [max [slot-value 'journal-entry 'last-modification]] :from [journal-entry] :flatp t)) 0))) :id "urn:uuid:88ad4730-90bc-4cc1-9e1f-d4cdb9ce177c") (with-tag ("subtitle") (xml-as-is "Geschwafel eines libertärsozialistischen Geeks")) (with-tag ("author") (emit-simple-tags :name "Matthias Benkard")) (with-tag ("link" `(("rel" "alternate") ("type" "text/html") ("href" ,(link-to :index :absolute t))))) (with-tag ("link" `(("rel" "self") ("type" "application/atom+xml") ("href" ,(link-to :view-atom-feed :absolute t))))) (when include-edit-links (with-tag ("link" `(("rel" "service.post") ("type" "application/atom+xml") ("href" ,(link-to :view-atom-entry :absolute t))))) (with-tag ("link" `(("rel" "service.feed") ("type" "application/atom+xml") ("href" ,(link-to :view-atom-entry :absolute t))))) #+(or) (with-tag ("link" `(("rel" "service.categories") ("type" "application/atom+xml") ("href" ,(link-to :view-atom-entry :absolute t)))))) (let ((number 0)) (dolist (journal-entry (select 'journal-entry :order-by '(([date] :desc)) :flatp t)) ;; We only include the body for the most recent posts in ;; order to save bandwidth. (show-atom-entry-xml journal-entry :full-content (or (and (last-modification-of journal-entry) (> (last-modification-of journal-entry) (- (get-universal-time) (* 30 24 60 60)))) (<= number 8) full-content) :include-edit-links include-edit-links) (incf number)))))) #.(restore-sql-reader-syntax-state)) (let ((scanner (ppcre:create-scanner "(\\n|\\r|\\r\\n)(\\n|\\r|\\r\\n)+"))) (defun render-comment-body (text) (loop for last-position = 0 then (cadr matches) for matches = (ppcre:all-matches scanner text) then (cddr matches) while (not (endp matches)) do (<:p (<:as-html (subseq text last-position (car matches)))) finally (<:p (<:as-html (subseq text last-position)))))) (defun show-journal-entry (journal-entry &key (comments-p nil)) (with-slots (id title body categories date type) journal-entry (show-journal-entry-with-components id title body categories date type (comments-about journal-entry :ordered-p t :ham-p t) comments-p (trackbacks-about journal-entry :ordered-p t :ham-p t)))) (defun show-journal-entry-with-components (id title body categories posting-date type comments comments-p trackbacks) (unless *full-entry-view* (<:tr (<:td (<:a :href (link-to :view :post-id id) (<:as-is title))) (<:td :style "text-align: right" (<:as-is (format-date nil "%day%.%mon%.%yr%, %hr%:%2min%" posting-date))) (<:td (<:a :href (link-to :view :post-id id) (<:as-is (format nil "~D Kommentar~:*~[e~;~:;e~]" (length comments))))))) (when *full-entry-view* (<:div :class :journal-entry (<::article (<:h1 (<:a :href (link-to :view :post-id id) (<:as-is title))) (<:div :class :journal-entry-header (<::header (<:span :class :journal-entry-date (<::time :pubdate "pubdate" :datetime (format-date nil "%4yr%-%2mon%-%2day%T%2hr%:%2min%:%2sec%Z" posting-date) (<:as-html (format-date nil "%@day-of-week%, den %day%.%mon%.%yr%, %hr%:%2min%." posting-date)))) (unless (null categories) (<:span :class :journal-entry-category (<:as-html (format nil "Abgeheftet unter ...")))))) (<:div :class :journal-entry-body (<:as-is (if (equal type "html") body (journal-markup->html body)))) (<:div :class :journal-entry-footer (<::footer (<:form :class :journal-entry-delete-button-form :style "display: inline;" :method "post" :action (link-to :index) (<:div :style "display: inline;" (<:input :type "hidden" :name "action" :value "delete") (<:input :type "hidden" :name "id" :value (prin1-to-string id)) (<:input :type "submit" :value "Löschen"))) " | " (<:form :class :journal-entry-edit-button-form :style "display: inline;" :method "get" :action (link-to :edit :post-id id) (<:div :style "display: inline;" (<:input :type "hidden" :name "id" :value (prin1-to-string id)) (<:input :type "submit" :value "Bearbeiten"))) " | " (<:a :href (link-to :view-comment-feed :post-id id :absolute t) (<:as-is (format nil "Kommentarfeed (Atom)" (length comments)))) " | " (<:a :href (link-to :view :post-id id) (<:as-is (format nil "~D Kommentar~:*~[e~;~:;e~]" (length comments)))))))) (when (and comments-p (not (null comments))) (<:div :class :journal-comments (<:h2 "Kommentare") (dolist (comment comments) (show-comment comment)))) (when (and comments-p (not (null trackbacks))) (<:div :class :journal-comments (<:h2 "Trackbacks") (dolist (trackback trackbacks) (show-trackback trackback)))) (when comments-p (<:as-is (format nil "" (link-to :view :post-id id :absolute t) (ppcre:regex-replace "--" title "—") (link-to :trackback :post-id id :absolute t))) (<:div :class :journal-new-comment (<:h2 "Neuen Kommentar schreiben") (<:p (<:as-is "Bitte beachten Sie, daß E-Mail-Adressen niemals veröffentlicht werden und nur von Matthias eingesehen werden können.")) (<:p (<:strong "Hinweise: ") "Diese Website verwendet " (<:a :href "http://akismet.com/" "Akismet") " zur Spamerkennung. " (<:as-is "E-Mail-Adressen werden auch gegenüber Akismet unter Verschluß gehalten. Nur unformatierter Text ist erlaubt. Leerzeilen trennen Absätze.")) (<:form :action (link-to :view :post-id id) :method "post" :accept-charset #+(or) "ISO-10646-UTF-1" "UTF-8" :enctype #+(or) "multipart/form-data" "application/x-www-form-urlencoded" (<:div :style "display: none" (<:input :type "hidden" :name "id" :value (prin1-to-string id)) (<:input :type "hidden" :name "action" :value "post-comment")) (<:div :style "display: table" (loop for (name . desc) in '(("author" . "Name (nötig)") ("email" . "E-Mail") ("website" . "Website")) do (<:div :style "display: table-row" (<:div :style "display: table-cell; vertical-align: top" (<:label :for name :style "vertical-align: top" (<:as-is (format nil "~A: " desc)))) (<:div :style "display: table-cell;" (<:input :type "text" :name name :id name)))) (<:div :style "display: table-row" (<:div :style "display: table-cell; vertical-align: top" (<:label :for "comment-body" :style "vertical-align: top" (<:as-html "Kommentar: "))) (<:div :style "display: table-cell" (<:textarea :name "comment-body" :id "comment-body" :rows 10 :cols 40)))) (<:div (<:input :type "submit" :value "Veröffentlichen"))))))) (defun call-with-web-journal (page-title thunk &key canonical-uri) ;; TODO: Check how to make Squid not wait for the CGI script's ;; termination, which makes generating a Last-Modified header ;; feel slower to the end user rather than faster. ;; (when (eq *mode* :http) (http-add-header "Last-Modified" (http-timestamp (compute-journal-last-modified-date))) (http-add-header "Content-Language" "de") (http-add-header "Cache-Control" "public") (http-add-header "X-Pingback" (link-to :pingback :absolute t)) (http-send-headers "text/html; charset=UTF-8")) (") ;; The iPhone's Mobile Safari browser scales all web pages by ;; default in order to make them look as if on a PC-sized monitor. ;; That's great for all those flashy web sites out there that aren't ;; designed to work with small devices. It's not so great when your ;; pages mostly consist of lots of text to read, though. Therefore, ;; let's disable the default scaling here. (<:meta :name "viewport" :content "initial-scale=1.0, width=device-width") (<:title (<:as-is (if page-title (format nil "~A — Kompottkins Weisheiten" page-title) "Kompottkins Weisheiten"))) (<:link :rel "alternate" :type "application/atom+xml" :href (link-to :view-atom-feed) :title "Kompottkins weiser Atom-Feed") (<:link :rel "replies" :type "application/atom+xml" :href (link-to :view-comment-feed) :title "Kompottkins weiser Kommentarfeed") (when *post-number* (let ((entry (find-entry *post-number*))) (<:link :rel "replies" :type "application/atom+xml" :href (link-to :view-comment-feed :post-id *post-number* :absolute t) :title (format nil "Kommentare zu: ~A" (title-of entry))))) (<:link :rel "service.feed" :type "application/atom+xml" :href (link-to :view-atom-entry :absolute t) :title "Kompottkins Weisheiten") (<:as-is (format nil "" (link-to :pingback :absolute t))) (<:link :rel "stylesheet" :type "text/css" :href (link-to :css)) (<:link :rel "openid.server" :href "https://meinguter.name/index.php/serve") (<:link :rel "openid.delegate" :href "https://matthias.benkard.meinguter.name") (when canonical-uri (<:link :rel "canonical" :type "text/html" :href canonical-uri)) ;; Google Code Prettifier. (<:link :rel "stylesheet" :type "text/css" :href (link-to :prettify.css)) (<:script :type "text/javascript" :src (link-to :prettify.js)) (<:script :type "text/javascript" :src (link-to :prettify-lisp.js))) (<:body :onload "prettyPrint()" (<:div :id :main-title-box (<:h1 :id :main-title (<:a :href (link-to :index) "Kompottkins Weisheiten")) (<:div :id :main-subtitle (<:as-is "••• ") (<:as-is (random-elt '("Geschwafel eines libertärsozialistischen Geeks" "NEU! Jetzt ohne regelmäßige Serverabstürze!" "NEU! Jetzt mit mehr als 3 % Uptime!"))) (<:as-is " •••"))) (when (and *journal-warnings* (eq *mode* :http)) (<:div :id :warnings (dolist (warning *journal-warnings*) (<:div :class :journal-warning (<:p (<:strong "Achtung!")) (<:as-is warning))))) (<:div :id :contents (funcall thunk)) (<:div :id :navigation)) (when *debugging-p* (loop for (x . y) in `(("Action" . ,*action*) ("Entry ID" . ,*post-number*) ("Request method" . ,*method*) ("Query" . ,*query*) ("Query string" . ,(http-get-query-string)) ("Subpath" . ,*subpath*) ("Environment" . ,(http-get-env-vars)) #+clisp ("Environment #2" . ,(ext:getenv))) do (<:p (<:hr) (<:h2 (<:as-html x)) (<:p "Type " (<:em (<:as-html (type-of y))) ".") (<:pre (<:as-html (prin1-to-string y)))))))) (defun show-web-journal () #.(locally-enable-sql-reader-syntax) (revalidate-cache-or-die "text/html; charset=UTF-8") (with-web-journal ((if (member *action* '(:view :edit :preview :post-comment :save-entry)) (title-of (find-entry *post-number*)) nil) :canonical-uri (case *action* (:view (link-to :view :post-id *post-number* :absolute t)) ((:index nil) (link-to :index :absolute t)))) (case *action* ((:index nil) (let ((entries (select 'journal-entry :order-by '(([date] :desc)) :flatp t)) (full-journal-view (or (equal (getf *query* :|| nil) "full") (and (listp (getf *query* :|| nil)) (member "full" (getf *query* :|| nil) :test #'equal))))) (dolist (entry (if full-journal-view entries (subseq entries 0 5))) (let ((*full-entry-view* t)) (show-journal-entry entry))) (unless full-journal-view (<:div :class :old-entries (<:h2 (<:as-is "Ältere Einträge")) (<:p (<:a :rel "archives" :href (link-to :full-index) (<:as-is "Alle Einträge vollständig anzeigen (langsam!)."))) (<:table :class :old-entry-table (<:caption (<:as-is "Einträge nach Datum")) (<:thead (<:tr (<:th :scope "col" (<:as-is "Titel")) (<:th :scope "col" (<:as-is "Datum")) (<:th :scope "col" (<:as-is "Kommentare")))) (<:tbody (dolist (entry entries) (let ((*full-entry-view* nil)) (show-journal-entry entry))))))))) ((:view :post-comment :save-entry) (show-journal-entry (find-entry *post-number*) :comments-p t)))) #.(restore-sql-reader-syntax-state)) (defun show-comment (comment) (with-slots (author body date id email website) comment (<:div :class :journal-comment :id (format nil "comment-~D" id) (<:div :class :journal-comment-header (<:as-html (format nil "(~A) " (format-date nil "%day%.%mon%.%yr%, %hr%:%min%" date))) (<:a :href website :rel "nofollow" (<:as-html (format nil "~A" author))) (<:as-html " meint: ")) (<:div :class :journal-comment-body (<:as-html (render-comment-body body)))))) (defun show-trackback (trackback) (with-slots (title excerpt date id url blog-name) trackback (<:div :class :journal-comment :id (format nil "trackback-~D" id) (<:div :class :journal-comment-header (<:as-html (format nil "(~A) " (format-date nil "%day%.%mon%.%yr%, %hr%:%min%" date))) (<:strong (<:as-html (format nil "~A " (or blog-name url)))) (if (null title) (<:a :href url :rel "nofollow" (<:as-html "schreibt hierzu:")) (progn (<:as-html "schreibt hierzu im Artikel ") (<:a :href url :rel "nofollow" (<:as-html (format nil "~A" title))) (<:as-html ":")))) (<:div :class :journal-comment-body (<:as-html (render-comment-body excerpt)))))) (defun show-pingback (pingback) (with-slots (date id url) pingback (<:div :class :journal-comment :id (format nil "pingback-~D" id) (<:div :class :journal-comment-header (<:as-html (format nil "(~A) " (format-date nil "%day%.%mon%.%yr%, %hr%:%min%" date))) (<:as-html "Pingback von ") (<:a :href url :rel "nofollow" (<:as-html url)) (<:as-html "."))))) (defun show-moderation-page () #.(locally-enable-sql-reader-syntax) (revalidate-cache-or-die "text/html; charset=UTF-8") (with-web-journal (nil) (<:h2 (<:as-html "Trackbacks")) (dolist (trackback (select 'journal-trackback :flatp t :order-by '([date]) :where (clsql:sql-null [spam_p]))) (<:hr) (<:form :action (link-to :moderation-page) :method "post" :accept-charset "UTF-8" :enctype "application/x-www-form-urlencoded" :style "display: inline" (<:input :type "hidden" :name "id" :value (prin1-to-string (id-of trackback))) (<:input :type "hidden" :name "type" :value "trackback") (<:input :type "hidden" :name "acceptp" :value "f") (<:input :type "submit" :value "Verwerfen")) (<:form :action (link-to :moderation-page) :method "post" :accept-charset "UTF-8" :enctype "application/x-www-form-urlencoded" :style "display: inline" (<:input :type "hidden" :name "id" :value (prin1-to-string (id-of trackback))) (<:input :type "hidden" :name "type" :value "trackback") (<:input :type "hidden" :name "acceptp" :value "t") (<:input :type "submit" :value "Annehmen")) (<:div (<:as-html "Zu: ") (<:a :href (link-to :view :post-id (id-of (entry-of trackback)) :absolute t) (<:as-html (title-of (entry-of trackback))))) (show-trackback trackback)) (<:h2 (<:as-html "Pingbacks")) (dolist (pingback (select 'journal-pingback :flatp t :order-by '([date]) :where (clsql:sql-null [spam_p]))) (<:hr) (<:form :action (link-to :moderation-page) :method "post" :accept-charset "UTF-8" :enctype "application/x-www-form-urlencoded" :style "display: inline" (<:input :type "hidden" :name "id" :value (prin1-to-string (id-of pingback))) (<:input :type "hidden" :name "type" :value "pingback") (<:input :type "hidden" :name "acceptp" :value "f") (<:input :type "submit" :value "Verwerfen")) (<:form :action (link-to :moderation-page) :method "post" :accept-charset "UTF-8" :enctype "application/x-www-form-urlencoded" :style "display: inline" (<:input :type "hidden" :name "id" :value (prin1-to-string (id-of pingback))) (<:input :type "hidden" :name "type" :value "pingback") (<:input :type "hidden" :name "acceptp" :value "t") (<:input :type "submit" :value "Annehmen")) (<:div (<:as-html "Zu: ") (<:a :href (link-to :view :post-id (id-of (entry-of pingback)) :absolute t) (<:as-html (title-of (entry-of pingback))))) (show-pingback pingback)) (<:h2 (<:as-html "Kommentare")) (dolist (comment (select 'journal-comment :flatp t :order-by '([date]) :where (clsql:sql-null [spam_p]))) (<:hr) (<:form :action (link-to :moderation-page) :method "post" :accept-charset "UTF-8" :enctype "application/x-www-form-urlencoded" :style "display: inline" (<:input :type "hidden" :name "id" :value (prin1-to-string (id-of comment))) (<:input :type "hidden" :name "type" :value "comment") (<:input :type "hidden" :name "acceptp" :value "f") (<:input :type "submit" :value "Verwerfen")) (<:form :action (link-to :moderation-page) :method "post" :accept-charset "UTF-8" :enctype "application/x-www-form-urlencoded" :style "display: inline" (<:input :type "hidden" :name "id" :value (prin1-to-string (id-of comment))) (<:input :type "hidden" :name "type" :value "comment") (<:input :type "hidden" :name "acceptp" :value "t") (<:input :type "submit" :value "Annehmen")) (<:div (<:as-html "Zu: ") (<:a :href (link-to :view :post-id (id-of (entry-of comment)) :absolute t) (<:as-html (title-of (entry-of comment))))) (show-comment comment))) #.(restore-sql-reader-syntax-state)) (defun preview-entry (title body id) (with-web-journal (title) (<:form :action (link-to :save :post-id id) :method "post" :accept-charset "UTF-8" :enctype "application/x-www-form-urlencoded" (when id (<:input :type "hidden" :name "id" :value (prin1-to-string id))) (<:input :type "hidden" :name "title" :value title) (<:input :type "hidden" :name "body" :value body) (<:div (<:input :type "submit" :value "Veröffentlichen"))) (show-journal-entry-with-components (or id -1) title body nil (get-universal-time) "markdown" nil nil nil) ;; Editor here. (<:form :action (link-to :preview :post-id id) :method "post" :accept-charset "UTF-8" :enctype "application/x-www-form-urlencoded" (<:div :style "display: none" (when id (<:input :type "hidden" :name "id" :value (prin1-to-string id)))) (<:div :style "display: table" (<:div :style "display: table-row" (<:div :style "display: table-cell; vertical-align: top" (<:label :for "entry-title-editor" :style "vertical-align: top" (<:as-is "Überschrift: "))) (<:div :style "display: table-cell;" (<:input :type "text" :name "title" :value title :id "entry-title-editor"))) (<:div :style "display: table-row" (<:div :style "display: table-cell; vertical-align: top" (<:label :for "entry-body-editor" :style "vertical-align: top" (<:as-html "Kommentar: "))) (<:div :style "display: table-cell" (<:textarea :name "body" :id "entry-body-editor" :rows 20 :cols 65 (<:as-html body))))) (<:div (<:input :type "submit" :value "Vorschau"))))) (defun show-debugging-page () (http-add-header "Content-Language" "de") (http-send-headers "text/html; charset=UTF-8") (