|
|
|
@ -1,16 +1,34 @@ |
|
|
|
(ns NoteHub.views.pages |
|
|
|
(ns NoteHub.views.pages |
|
|
|
(:require [NoteHub.views.common :as common]) |
|
|
|
(:require [NoteHub.views.common :as common]) |
|
|
|
(:use |
|
|
|
(:use |
|
|
|
[NoteHub.storage :rename {get s-get set s-set} :only [set get]] |
|
|
|
[NoteHub.storage] |
|
|
|
[noir.response :only [redirect]] |
|
|
|
|
|
|
|
[clojure.string :rename {replace sreplace} :only [split replace lower-case]] |
|
|
|
[clojure.string :rename {replace sreplace} :only [split replace lower-case]] |
|
|
|
[noir.core :only [defpage render]] |
|
|
|
[clojure.core.incubator :only [-?>]] |
|
|
|
[hiccup.form] |
|
|
|
[hiccup.form] |
|
|
|
|
|
|
|
[noir.response :only [redirect]] |
|
|
|
|
|
|
|
[noir.core :only [defpage render]] |
|
|
|
|
|
|
|
[noir.statuses] |
|
|
|
[noir.fetch.remotes]) |
|
|
|
[noir.fetch.remotes]) |
|
|
|
(:import [org.pegdown PegDownProcessor])) |
|
|
|
(:import [org.pegdown PegDownProcessor])) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Fix a maximal title length used in the link |
|
|
|
(def max-title-length 80) |
|
|
|
(def max-title-length 80) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Markdown -> HTML mapper |
|
|
|
|
|
|
|
(defremote md-to-html [draft] |
|
|
|
|
|
|
|
(.markdownToHtml (PegDownProcessor.) draft)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Template for the 404 error |
|
|
|
|
|
|
|
(set-page! 404 |
|
|
|
|
|
|
|
(let [message "Page Not Found."] |
|
|
|
|
|
|
|
(common/layout message |
|
|
|
|
|
|
|
[:article |
|
|
|
|
|
|
|
[:h1 message]]))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Routes |
|
|
|
|
|
|
|
; ====== |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Landing Page |
|
|
|
(defpage "/" {} |
|
|
|
(defpage "/" {} |
|
|
|
(common/layout "Free Markdown Hosting" |
|
|
|
(common/layout "Free Markdown Hosting" |
|
|
|
[:div#hero |
|
|
|
[:div#hero |
|
|
|
@ -19,41 +37,44 @@ |
|
|
|
[:br] |
|
|
|
[:br] |
|
|
|
[:a.landing-button {:href "/new"} "New Page"]])) |
|
|
|
[:a.landing-button {:href "/new"} "New Page"]])) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; New Note Page |
|
|
|
(defpage "/new" {} |
|
|
|
(defpage "/new" {} |
|
|
|
(common/layout "New Markdown Note" |
|
|
|
(common/layout "New Markdown Note" |
|
|
|
[:div.central-body |
|
|
|
[:div.central-element |
|
|
|
(form-to [:post "/post-note"] |
|
|
|
(form-to [:post "/post-note"] |
|
|
|
(text-area {:class "max-width"} :draft) |
|
|
|
(text-area {:class "max-width"} :draft) |
|
|
|
[:div#buttons.hidden |
|
|
|
[:div#buttons.hidden |
|
|
|
(submit-button {:style "float: left" :class "button"} "Publish") |
|
|
|
(submit-button {:style "float: left" :class "button"} "Publish") |
|
|
|
[:button#preview-button.button {:type :button :style "float: right"} "Preview"]])] |
|
|
|
[:button#preview-button.button {:type :button :style "float: right"} "Preview"]])] |
|
|
|
[:div#preview-start] |
|
|
|
[:div#preview-start-line.hidden] |
|
|
|
[:article#preview.central-body])) |
|
|
|
[:article#preview])) |
|
|
|
|
|
|
|
|
|
|
|
(defn get-storage-key [year month day title] |
|
|
|
|
|
|
|
(apply str (interpose "-" ["note" year month day (hash [year month day title])]))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(defremote md-to-html [draft] |
|
|
|
|
|
|
|
(.markdownToHtml (PegDownProcessor.) draft)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Note URL |
|
|
|
(defpage "/:year/:month/:day/:title" {:keys [year month day title]} |
|
|
|
(defpage "/:year/:month/:day/:title" {:keys [year month day title]} |
|
|
|
(let [key (get-storage-key year month day title) |
|
|
|
(let [date [year month day] |
|
|
|
post (s-get key) |
|
|
|
key (hash (conj date title)) |
|
|
|
title (sreplace (-> post (split #"\n") first) #"[_\*#]" "")] |
|
|
|
post (get-note date key) |
|
|
|
|
|
|
|
title (-?> post (split #"\n") first (sreplace #"[_\*#]" ""))] |
|
|
|
|
|
|
|
(if post |
|
|
|
(common/layout title |
|
|
|
(common/layout title |
|
|
|
[:article.central-body |
|
|
|
[:article |
|
|
|
; TODO: deal with 404! |
|
|
|
(md-to-html post)]) |
|
|
|
(md-to-html post)]))) |
|
|
|
(get-page 400)))) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; New Note Posting |
|
|
|
(defpage [:post "/post-note"] {:keys [draft]} |
|
|
|
(defpage [:post "/post-note"] {:keys [draft]} |
|
|
|
(let [[year month day] (split (.format (java.text.SimpleDateFormat. "yyyy-MM-dd") (java.util.Date.)) #"-") |
|
|
|
(let [[year month day] (split |
|
|
|
|
|
|
|
(.format |
|
|
|
|
|
|
|
(java.text.SimpleDateFormat. "yyyy-MM-dd") |
|
|
|
|
|
|
|
(java.util.Date.)) #"-") |
|
|
|
untrimmed-line (filter #(or (= \- %) (Character/isLetterOrDigit %)) |
|
|
|
untrimmed-line (filter #(or (= \- %) (Character/isLetterOrDigit %)) |
|
|
|
(-> draft (split #"\n") first (sreplace " " "-") lower-case)) |
|
|
|
(-> draft (split #"\n") first (sreplace " " "-") lower-case)) |
|
|
|
trim (fn [s] (apply str (drop-while #(= \- %) s))) |
|
|
|
trim (fn [s] (apply str (drop-while #(= \- %) s))) |
|
|
|
title-uncut (-> untrimmed-line trim reverse trim reverse) |
|
|
|
title-uncut (-> untrimmed-line trim reverse trim reverse) |
|
|
|
title (apply str (take max-title-length title-uncut)) |
|
|
|
title (apply str (take max-title-length title-uncut)) |
|
|
|
; TODO: deal with collisions! |
|
|
|
; TODO: deal with collisions! |
|
|
|
key (get-storage-key year month day title)] |
|
|
|
date [year month day] |
|
|
|
|
|
|
|
key (hash (conj date title))] |
|
|
|
(do |
|
|
|
(do |
|
|
|
(s-set key draft) |
|
|
|
(set-note date key draft) |
|
|
|
(redirect (apply str (interpose "/" ["" year month day title])))))) |
|
|
|
(redirect (apply str (interpose "/" ["" year month day title])))))) |
|
|
|
|