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 @@ @@ -1,9 +1,11 @@
(ns NoteHub.crossover.lib
(:refer-clojure :exclude [hash]))
; very simple hash function %)
; (doesn't work for UTF-16!)
(defn hash [f s]
(defn hash
"A simple hash-function, which computes a hash from the text field
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)
char-codes (map f
(filter #(not (contains? #{"\n" "\r"} %)) (map str s)))]

18
src/NoteHub/settings.clj

@ -0,0 +1,18 @@ @@ -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 @@ @@ -1,24 +1,32 @@
(ns NoteHub.storage
(:use [NoteHub.config])
(:use [NoteHub.settings]
[noir.options :only [dev-mode?]])
(:require [clj-redis.client :as redis]))
; Initialize the data base
(def db
(redis/init
(when noir.options/dev-mode?
{:url (config-map :db-url)})))
(when dev-mode?
{:url (get-setting :db-url)})))
; DB hierarchy levels
(def note "note")
(def views "views")
; Concatenates all fields to a string
(defn- build-key [[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)]
(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)
text (redis/hget db note key)]
(when text
@ -26,13 +34,19 @@ @@ -26,13 +34,19 @@
(redis/hincrby db views key 1)
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)))
(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)))
(defn delete-note [date title]
(defn delete-note
"Deletes the note with the specified coordinates"
[date title]
(let [key (build-key date title)]
(do
(redis/hdel db views key)

6
src/NoteHub/views/common.clj

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

14
src/NoteHub/views/css_generator.clj

@ -1,16 +1,18 @@ @@ -1,16 +1,18 @@
(ns NoteHub.views.css-generator
(:use [cssgen]
[NoteHub.settings]
[cssgen.types]))
(defn gen-fontlist [& fonts]
(defn- gen-fontlist [& fonts]
(apply str
(interpose ","
(map #(str "'" % "'")
(filter identity fonts)))))
; CSS Mixins
(def page-width
(mixin
:width :800px))
:width (get-setting :page-width :800px keyword)))
(def helvetica-neue
(mixin
@ -20,6 +22,7 @@ @@ -20,6 +22,7 @@
"Arial"
"Lucida Grande"
"sans-serif")))
(def central-element
(mixin
page-width
@ -28,7 +31,8 @@ @@ -28,7 +31,8 @@
:margin-left "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
:foreground :#ccc
:background-halftone :#444
@ -38,7 +42,9 @@ @@ -38,7 +42,9 @@
:background-halftone :#efefef
: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)
theme (if theme (keyword theme) :default)
header-fonts (gen-fontlist (params :header-font) "Noticia Text" "PT Serif" "Georgia")

38
src/NoteHub/views/pages.clj

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

Loading…
Cancel
Save