Browse Source

documentation added + more sophisticated settings file reader

master
Christian Mueller 14 years ago
parent
commit
b5a23b6f09
  1. 8
      src/NoteHub/crossover/lib.clj
  2. 18
      src/NoteHub/settings.clj
  3. 32
      src/NoteHub/storage.clj
  4. 6
      src/NoteHub/views/common.clj
  5. 14
      src/NoteHub/views/css_generator.clj
  6. 38
      src/NoteHub/views/pages.clj

8
src/NoteHub/crossover/lib.clj

@ -1,9 +1,11 @@
(ns NoteHub.crossover.lib (ns NoteHub.crossover.lib
(:refer-clojure :exclude [hash])) (:refer-clojure :exclude [hash]))
; very simple hash function %) (defn hash
; (doesn't work for UTF-16!) "A simple hash-function, which computes a hash from the text field
(defn hash [f s] content and given session number. It is intended to be used as a spam
protection / captcha alternative. (Probably doesn't work for URF-16)"
[f s]
(let [short-mod #(mod % 32767) (let [short-mod #(mod % 32767)
char-codes (map f char-codes (map f
(filter #(not (contains? #{"\n" "\r"} %)) (map str s)))] (filter #(not (contains? #{"\n" "\r"} %)) (map str s)))]

18
src/NoteHub/settings.clj

@ -0,0 +1,18 @@
(ns NoteHub.settings
(:require [clojure.string :as cs]))
(defn get-setting
"Takes a settings key, a default value and a converter function and returns a corresponding
settings value. The default value is returned back when no setting value was found.
The converter function can be provided to convert the setting from string to a needed format."
[key & more]
(let [default (first more)
converter (second more)
file-content (slurp "settings")
lines (cs/split file-content #"\n")
pairs (map #(map cs/trim %) (map #(cs/split % #"=") lines))
config-map (apply hash-map (mapcat #(list (keyword (first %)) (second %)) pairs))
value (config-map key)]
(if value
(if (fn? converter) (converter value) value)
default)))

32
src/NoteHub/storage.clj

@ -1,24 +1,32 @@
(ns NoteHub.storage (ns NoteHub.storage
(:use [NoteHub.config]) (:use [NoteHub.settings]
[noir.options :only [dev-mode?]])
(:require [clj-redis.client :as redis])) (:require [clj-redis.client :as redis]))
; Initialize the data base
(def db (def db
(redis/init (redis/init
(when noir.options/dev-mode? (when dev-mode?
{:url (config-map :db-url)}))) {:url (get-setting :db-url)})))
; DB hierarchy levels
(def note "note") (def note "note")
(def views "views") (def views "views")
; Concatenates all fields to a string
(defn- build-key [[year month day] title] (defn- build-key [[year month day] title]
(print-str year month day title)) (print-str year month day title))
(defn set-note [date title text] (defn set-note
"Creates a note with the given title and text in the given date namespace"
[date title text]
(let [key (build-key date title)] (let [key (build-key date title)]
(redis/hset db note key text))) (redis/hset db note key text)))
(defn get-note [date title] (defn get-note
"Gets the note from the given date namespaces for the specified title"
[date title]
(let [key (build-key date title) (let [key (build-key date title)
text (redis/hget db note key)] text (redis/hget db note key)]
(when text (when text
@ -26,13 +34,19 @@
(redis/hincrby db views key 1) (redis/hincrby db views key 1)
text)))) text))))
(defn get-views [date title] (defn get-views
"Returns the number of views for the specified date and note title"
[date title]
(redis/hget db views (build-key date title))) (redis/hget db views (build-key date title)))
(defn note-exists? [date title] (defn note-exists?
"Returns true if the note with the specified title and date exists"
[date title]
(redis/hexists db note (build-key date title))) (redis/hexists db note (build-key date title)))
(defn delete-note [date title] (defn delete-note
"Deletes the note with the specified coordinates"
[date title]
(let [key (build-key date title)] (let [key (build-key date title)]
(do (do
(redis/hdel db views key) (redis/hdel db views key)

6
src/NoteHub/views/common.clj

@ -5,6 +5,7 @@
[hiccup.page :only [include-js html5]] [hiccup.page :only [include-js html5]]
[hiccup.element :only [javascript-tag]])) [hiccup.element :only [javascript-tag]]))
; Creates the main html layout
(defpartial generate-layout (defpartial generate-layout
[params title & content] [params title & content]
(html5 (html5
@ -28,8 +29,9 @@
(include-js "/cljs/main.js")] (include-js "/cljs/main.js")]
[:body content]))) [:body content])))
(defn layout [& args] (defn layout
"Generates the main html layout"
[& args]
(if (map? (first args)) (if (map? (first args))
(apply generate-layout args) (apply generate-layout args)
(apply generate-layout {} args))) (apply generate-layout {} args)))

14
src/NoteHub/views/css_generator.clj

@ -1,16 +1,18 @@
(ns NoteHub.views.css-generator (ns NoteHub.views.css-generator
(:use [cssgen] (:use [cssgen]
[NoteHub.settings]
[cssgen.types])) [cssgen.types]))
(defn gen-fontlist [& fonts] (defn- gen-fontlist [& fonts]
(apply str (apply str
(interpose "," (interpose ","
(map #(str "'" % "'") (map #(str "'" % "'")
(filter identity fonts))))) (filter identity fonts)))))
; CSS Mixins
(def page-width (def page-width
(mixin (mixin
:width :800px)) :width (get-setting :page-width :800px keyword)))
(def helvetica-neue (def helvetica-neue
(mixin (mixin
@ -20,6 +22,7 @@
"Arial" "Arial"
"Lucida Grande" "Lucida Grande"
"sans-serif"))) "sans-serif")))
(def central-element (def central-element
(mixin (mixin
page-width page-width
@ -28,7 +31,8 @@
:margin-left "auto" :margin-left "auto"
:margin-right "auto")) :margin-right "auto"))
(defn color [theme tone] ; Resolves the theme name & tone parameter to a concrete color
(defn- color [theme tone]
(get-in {:dark {:background :#333 (get-in {:dark {:background :#333
:foreground :#ccc :foreground :#ccc
:background-halftone :#444 :background-halftone :#444
@ -38,7 +42,9 @@
:background-halftone :#efefef :background-halftone :#efefef
:foreground-halftone :#888 }} [theme tone])) :foreground-halftone :#888 }} [theme tone]))
(defn global-css [params] (defn global-css
"Generates the entire CSS rules of the app"
[params]
(let [theme (params :theme) (let [theme (params :theme)
theme (if theme (keyword theme) :default) theme (if theme (keyword theme) :default)
header-fonts (gen-fontlist (params :header-font) "Noticia Text" "PT Serif" "Georgia") header-fonts (gen-fontlist (params :header-font) "Noticia Text" "PT Serif" "Georgia")

38
src/NoteHub/views/pages.clj

@ -3,6 +3,7 @@
(:require [NoteHub.crossover.lib :as lib]) (:require [NoteHub.crossover.lib :as lib])
(:use (:use
[NoteHub.storage] [NoteHub.storage]
[NoteHub.settings]
[clojure.string :rename {replace sreplace} :only [split replace lower-case]] [clojure.string :rename {replace sreplace} :only [split replace lower-case]]
[clojure.core.incubator :only [-?>]] [clojure.core.incubator :only [-?>]]
[hiccup.form] [hiccup.form]
@ -16,23 +17,22 @@
[java.util Calendar] [java.util Calendar]
[org.pegdown PegDownProcessor])) [org.pegdown PegDownProcessor]))
; Fix a maximal title length used in the link
(def max-title-length 80)
; Markdown -> HTML mapper ; Markdown -> HTML mapper
(defn md-to-html [md-text] (defn md-to-html [md-text]
(.markdownToHtml (PegDownProcessor.) md-text)) (.markdownToHtml (PegDownProcessor.) md-text))
(defn get-flash-key [] ; Creates a random session number
(defn- get-flash-key []
(let [k (encrypt (str (rand-int Integer/MAX_VALUE)))] (let [k (encrypt (str (rand-int Integer/MAX_VALUE)))]
(do (flash-put! k true) (do (flash-put! k true)
(print-str k)))) (print-str k))))
; This function answers to a corresponding AJAX request ; Converts given markdwon to html and wraps with layout
(defremote get-preview-md [session-key md] (defn- wrap [params md-text]
(when (flash-get session-key) (if md-text
{:session-key (get-flash-key) (let [title (-?> md-text (split #"\n") first (sreplace #"[_\*#]" ""))]
:preview (md-to-html md)})) (common/layout params title [:article (md-to-html md-text)]))
(status 404 (get-page 404))))
; Template for the error sites ; Template for the error sites
(defn page-setter [code message] (defn page-setter [code message]
@ -41,6 +41,7 @@
[:article [:article
[:h1 message]]))) [:h1 message]])))
; Sets a message for each corresponding HTTP status
(page-setter 404 "Nothing Found.") (page-setter 404 "Nothing Found.")
(page-setter 400 "Bad request.") (page-setter 400 "Bad request.")
(page-setter 500 "OMG, Server Exploded.") (page-setter 500 "OMG, Server Exploded.")
@ -48,6 +49,13 @@
; Routes ; Routes
; ====== ; ======
; This function answers to a AJAX request: it gets a sesion key and markdown text.
; IT return html version of the provided markdown and a new session key
(defremote get-preview-md [session-key md]
(when (flash-get session-key)
{:session-key (get-flash-key)
:preview (md-to-html md)}))
; Landing Page ; Landing Page
(defpage "/" {} (defpage "/" {}
(common/layout "Free Markdown Hosting" (common/layout "Free Markdown Hosting"
@ -74,21 +82,18 @@
[:div#preview-start-line.hidden] [:div#preview-start-line.hidden]
[:article#preview])) [:article#preview]))
(defn wrap [params md-text] ; Display the note
(if md-text
(let [title (-?> md-text (split #"\n") first (sreplace #"[_\*#]" ""))]
(common/layout params title [:article (md-to-html md-text)]))
(status 404 (get-page 404))))
(defpage "/:year/:month/:day/:title" {:keys [year month day title theme header-font text-font] :as params} (defpage "/:year/:month/:day/:title" {:keys [year month day title theme header-font text-font] :as params}
(wrap (wrap
(select-keys params [:theme :header-font :text-font]) (select-keys params [:theme :header-font :text-font])
(get-note [year month day] title))) (get-note [year month day] title)))
; Provides Markdown of the specified note
(defpage "/:year/:month/:day/:title/export" {:keys [year month day title]} (defpage "/:year/:month/:day/:title/export" {:keys [year month day title]}
(let [md-text (get-note [year month day] title)] (let [md-text (get-note [year month day] title)]
(if md-text md-text (status 404 (get-page 404))))) (if md-text md-text (status 404 (get-page 404)))))
; Provides the number of views of the specified note
(defpage "/:year/:month/:day/:title/stat" {:keys [year month day title]} (defpage "/:year/:month/:day/:title/stat" {:keys [year month day title]}
(let [views (get-views [year month day] title)] (let [views (get-views [year month day] title)]
(if views (if views
@ -119,7 +124,8 @@
(-> 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)
proposed-title (apply str (take max-title-length title-uncut)) proposed-title (apply str (take (get-setting :max-title-length 80 #(Integer/parseInt %))
title-uncut))
date [year month day] date [year month day]
title (first (drop-while #(note-exists? date %) title (first (drop-while #(note-exists? date %)
(cons proposed-title (cons proposed-title

Loading…
Cancel
Save