Browse Source

theming moved to JS completely

master
Christian Mueller 12 years ago
parent
commit
226d8133da
  1. 3
      resources/public/js/main.js
  2. 160
      resources/public/js/themes.js
  3. 2
      resources/public/style.less
  4. 66
      src/NoteHub/views/common.clj
  5. 82
      src/NoteHub/views/pages.clj
  6. 1
      test/NoteHub/test/views/pages.clj

3
resources/public/js/main.js

@ -13,7 +13,8 @@ function md2html(input){
return marked(input); return marked(input);
} }
function loadPage() { function onLoad() {
applyTheme();
$note = $("note"); $note = $("note");
$action = $("action"); $action = $("action");
$preview = $("preview"); $preview = $("preview");

160
resources/public/js/themes.js

@ -1,62 +1,104 @@
var themes = { var themes = {
"dark": { "dark": {
background: { background: {
normal: '#333', normal: '#333',
halftone: '#444' halftone: '#444'
}, },
foreground: { foreground: {
normal: '#ccc', normal: '#ccc',
halftone: '#bbb' halftone: '#bbb'
}, },
link: { link: {
fresh: '#6b8', fresh: '#6b8',
visited: '#496', visited: '#496',
hover: '#7c9' hover: '#7c9'
} }
}, },
"solarized-light": { "solarized-light": {
background: { background: {
normal: '#fdf6e3', normal: '#fdf6e3',
halftone: '#eee8d5' halftone: '#eee8d5'
}, },
foreground: { foreground: {
normal: '#657b83', normal: '#657b83',
halftone: '#839496' halftone: '#839496'
}, },
link: { link: {
fresh: '#b58900', fresh: '#b58900',
visited: '#cb4b16', visited: '#cb4b16',
hover: '#dc322f' hover: '#dc322f'
} }
}, },
"solarized-dark": { "solarized-dark": {
background: { background: {
normal: '#073642', normal: '#073642',
halftone: '#002b36' halftone: '#002b36'
}, },
foreground: { foreground: {
normal: '#93a1a1', normal: '#93a1a1',
halftone: '#eee8d5' halftone: '#eee8d5'
}, },
link: { link: {
fresh: '#cb4b16', fresh: '#cb4b16',
visited: '#b58900', visited: '#b58900',
hover: '#dc322f' hover: '#dc322f'
} }
}, },
"default": { "default": {
background: { background: {
normal: '#fff', normal: '#fff',
halftone: '#efefef' halftone: '#efefef'
}, },
foreground: { foreground: {
normal: '#333', normal: '#333',
halftone: '#888' halftone: '#888'
}, },
link: { link: {
fresh: '#097', fresh: '#097',
visited: '#054', visited: '#054',
hover: '#0a8' hover: '#0a8'
}
} }
}
}; };
function applyTheme() {
if (location.search.length > 0) {
var ui = { theme: "default" };
location.search.slice(1).split("&").reduce(function(acc, e){
var p = e.split("=");
acc[p[0]] = p[1];
return acc
}, ui);
var vars = {
'@background': themes[ui.theme].background.normal,
'@background_halftone': themes[ui.theme].background.halftone,
'@foreground': themes[ui.theme].foreground.normal,
'@foreground_halftone': themes[ui.theme].foreground.halftone,
'@link_fresh': themes[ui.theme].link.fresh,
'@link_visited': themes[ui.theme].link.visited,
'@link_hover': themes[ui.theme].link.hover
};
if(ui["header-font"] || ui["text-font"]) {
var fontURL = "http://fonts.googleapis.com/" +
"css?family=PT+Serif:700|Noticia+Text:700%s" +
"&subset=latin,cyrillic";
var injection = ["header-font", "text-font"].reduce(function(acc, font){
if(ui[font]) {
vars['@' + font.replace(/-/, "_")] = ui[font].replace(/\+/g," ");
return acc + "|" + ui[font];
} else return acc;
}, "");
fontURL = fontURL.replace(/%s/, injection);
var fileref = document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", fontURL)
document.getElementsByTagName("head")[0].appendChild(fileref)
}
less.modifyVars(vars);
}
}

2
resources/public/style.less

@ -118,9 +118,9 @@ html, body {
margin: 2em; margin: 2em;
} }
article { article {
font-family: @text_font, 'Georgia';
.central-element; .central-element;
margin-top: 5em; margin-top: 5em;
font-family: @text_font, 'Georgia';
text-align: justify; text-align: justify;
font-size: @font_size; font-size: @font_size;
} }

66
src/NoteHub/views/common.clj

@ -1,66 +0,0 @@
(ns NoteHub.views.common
(:use
[NoteHub.settings :only [get-message]]
[noir.core :only [defpartial]]
[noir.options :only [dev-mode?]]
[hiccup.util :only [escape-html]]
[ring.util.codec :only [url-encode]]
[hiccup.core]
[hiccup.page :only [include-js html5]]
[hiccup.element :only [javascript-tag]]))
(defn url
"Creates a local url from the given substrings"
[& args]
(apply str (interpose "/" (cons "" (map url-encode args)))))
; Creates the main html layout
(defpartial generate-layout
[params title & content]
; for the sake of security: escape all symbols of the param values
(let [params (into {} (for [[k v] params] [k (escape-html v)]))
theme (:theme params "default")
header-font (:header-font params)
text-font (:text-font params)]
(html5
[:head
[:title (print-str (get-message :name) "—" title)]
[:meta {:charset "UTF-8"}]
; generating a link to google's webfonts
[:link {:href
(clojure.string/replace
(str "http://fonts.googleapis.com/css?family="
(apply str
(interpose "|" ["PT+Serif:700" "Noticia+Text:700" header-font text-font]))
"&subset=latin,cyrillic") " " "+")
:rel "stylesheet"
:type "text/css"}]
[:link {:rel "stylesheet/less" :type "text/css" :href "/style.less"}]
(html
(include-js "/js/less.js")
(include-js "/js/md5.js")
(include-js "/js/marked.js")
(include-js "/js/main.js")
(include-js "/js/themes.js")
(javascript-tag (str "less.modifyVars({
'@background': themes['" theme "'].background.normal,
'@background_halftone': themes['" theme "'].background.halftone,
'@foreground': themes['" theme "'].foreground.normal,
'@foreground_halftone': themes['" theme "'].foreground.halftone,
'@link_fresh': themes['" theme "'].link.fresh,
'@link_visited': themes['" theme "'].link.visited,
'@link_hover': themes['" theme "'].link.hover"
(when header-font (str ", '@header_font': '" header-font "'"))
(when text-font (str ",'@text_font': '" text-font "'"))
"});")))
; google analytics code should appear in prod mode only
(if-not (dev-mode?) (include-js "/js/google-analytics.js"))]
[:body {:onload "loadPage()"} content])))
(defn layout
"Generates the main html layout"
[& args]
; if some parameter weren't added we provide an empty map
(if (map? (first args))
(apply generate-layout args)
(apply generate-layout {} args)))

82
src/NoteHub/views/pages.clj

@ -4,22 +4,55 @@
[NoteHub.storage :as storage] [NoteHub.storage :as storage]
[cheshire.core :refer :all]) [cheshire.core :refer :all])
(:use (:use
[NoteHub.settings] [NoteHub.settings]
[NoteHub.views.common] [clojure.string :rename {replace sreplace}
[clojure.string :rename {replace sreplace} :only [escape split replace blank? split-lines lower-case]]
:only [escape split replace blank? split-lines lower-case]] [clojure.core.incubator :only [-?>]]
[clojure.core.incubator :only [-?>]] [noir.util.crypt :only [encrypt]]
[noir.util.crypt :only [encrypt]] [hiccup.form]
[hiccup.form] [hiccup.core]
[hiccup.core] [noir.options :only [dev-mode?]]
[hiccup.element] [ring.util.codec :only [url-encode]]
[noir.response :only [redirect status content-type]] [hiccup.element]
[noir.core :only [defpage defpartial]] [hiccup.util :only [escape-html]]
[noir.statuses])) [hiccup.page :only [include-js html5]]
[noir.response :only [redirect status content-type]]
[noir.core :only [defpage defpartial]]
[noir.statuses]))
(when-not (storage/valid-publisher? api/domain) (when-not (storage/valid-publisher? api/domain)
(storage/register-publisher api/domain)) (storage/register-publisher api/domain))
; Creates the main html layout
(defpartial generate-layout
[params title & content]
; for the sake of security: escape all symbols of the param values
(let [params (into {} (for [[k v] params] [k (escape-html v)]))
theme (:theme params "default")
header-font (:header-font params)
text-font (:text-font params)]
(html5
[:head
[:title (print-str (get-message :name) "—" title)]
[:meta {:charset "UTF-8"}]
[:link {:rel "stylesheet/less" :type "text/css" :href "/style.less"}]
(html
(include-js "/js/less.js")
(include-js "/js/md5.js")
(include-js "/js/marked.js")
(include-js "/js/main.js")
(include-js "/js/themes.js"))
; google analytics code should appear in prod mode only
(if-not (dev-mode?) (include-js "/js/google-analytics.js"))]
[:body {:onload "onLoad()"} content])))
(defn layout
"Generates the main html layout"
[& args]
(if (map? (first args))
(apply generate-layout args)
(apply generate-layout {} args)))
; Sets a custom message for each needed HTTP status. ; Sets a custom message for each needed HTTP status.
; The message to be assigned is extracted with a dynamically generated key ; The message to be assigned is extracted with a dynamically generated key
(doseq [code [400 403 404 500]] (doseq [code [400 403 404 500]]
@ -32,16 +65,21 @@
(defn- response [code] (defn- response [code]
(status code (get-page code))) (status code (get-page code)))
(defn url
"Creates a local url from the given substrings"
[& args]
(apply str (interpose "/" (cons "" (map url-encode args)))))
; Converts given markdown to html and wraps with the main layout ; Converts given markdown to html and wraps with the main layout
(defn- wrap [short-url params md-text] (defn- wrap [short-url params md-text]
(when md-text (when md-text
(layout params (params :title) (layout params (params :title)
[:article.bottom-space.markdown md-text] [:article.bottom-space.markdown md-text]
(let [links (map #(link-to (let [links (map #(link-to
(if (= :short-url %) (if (= :short-url %)
(url short-url) (url short-url)
(str (params :title) "/" (name %))) (str (params :title) "/" (name %)))
(get-message %)) (get-message %))
[:stats :edit :export :short-url]) [:stats :edit :export :short-url])
space (apply str (repeat 4 " ")) space (apply str (repeat 4 " "))
separator (str space "·" space) separator (str space "·" space)
@ -89,9 +127,9 @@
; Displays the note ; Displays the note
(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
(storage/create-short-url params) (storage/create-short-url params)
(select-keys params [:title :theme :header-font :text-font]) (select-keys params [:title :theme :header-font :text-font])
(:note (api/get-note (api/build-key [year month day] title))))) (:note (api/get-note (api/build-key [year month day] title)))))
; Provides Markdown of the specified note ; 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]}
@ -156,8 +194,8 @@
psk (storage/get-psk pid)] psk (storage/get-psk pid)]
(if (storage/valid-publisher? pid) (if (storage/valid-publisher? pid)
(let [resp (api/update-note noteID note pid (let [resp (api/update-note noteID note pid
(api/get-signature (str pid psk noteID note password)) (api/get-signature (str pid psk noteID note password))
password)] password)]
(if (get-in resp [:status :success]) (if (get-in resp [:status :success])
(redirect (:longURL resp)) (redirect (:longURL resp))
(response 403))) (response 403)))
@ -167,7 +205,7 @@
(defpage "/api" args (defpage "/api" args
(let [title (get-message :api-title)] (let [title (get-message :api-title)]
(layout title [:article.markdown (slurp "API.md")]))) (layout title [:article.markdown (slurp "API.md")])))
(defpage [:get "/api/note"] {:keys [version noteID]} (defpage [:get "/api/note"] {:keys [version noteID]}
(generate-string (api/get-note noteID))) (generate-string (api/get-note noteID)))

1
test/NoteHub/test/views/pages.clj

@ -2,7 +2,6 @@
(:use [NoteHub.views.pages] (:use [NoteHub.views.pages]
[NoteHub.api :only [build-key get-signature get-date]] [NoteHub.api :only [build-key get-signature get-date]]
[noir.util.test] [noir.util.test]
[NoteHub.views.common :only [url]]
[NoteHub.storage] [NoteHub.storage]
[clojure.test])) [clojure.test]))

Loading…
Cancel
Save