Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

jsonp response, session/swap\!, base-url. Closes #42. Closes #39. Clo…

…ses #32.

Signed-off-by: Chris Granger <ibdknox@gmail.com>
  • Loading branch information...
commit 1cef73139d43880ca58236e132b4b54127c8c76b 1 parent 4323f25
@ibdknox authored
View
193 resources/public/css/noir.css
@@ -0,0 +1,193 @@
+body {
+ background: url(/img/noir-bg.png);
+ color: #d1d9e1;
+ padding: 60px 80px;
+ font-family: 'Helvetica Neue',Helvetica,Verdana;
+}
+#wrapper {
+ margin: 0 auto;
+ width: 1000px;
+}
+#content {
+ float: left;
+ display: inline;
+ width: 100%;
+ padding-bottom: 100px;
+}
+a {
+ text-decoration: underline;
+ color: #91979d;
+}
+a:hover {
+ color: #6bffbd;
+}
+h1 {
+ margin-bottom: 0px;
+ color: #d1d9e1;
+}
+h2 {
+ margin-top: 10px;
+ margin-left: 60px;
+ font-size: 18px;
+ font-weight: normal;
+}
+code {
+ float: left;
+ display: inline;
+ border-radius: 8px;
+ padding: 10px;
+ background: #474949;
+ border: 2px solid #616363;
+ font-family: Monaco, Consolas, 'Courier New';
+}
+.announce {
+ float: left;
+ display: inline;
+ width: 970px;
+ text-align: center;
+ font-size: 20px;
+ margin-top: 20px;
+ margin-bottom: 110px;
+ border-radius: 8px;
+ padding: 10px;
+ background: #3f634d;
+ border: 2px solid #3c8455;
+ padding: 15px;
+}
+#header {
+ float: left;
+ display: inline;
+ width: 100%;
+ margin-bottom: 50px;
+}
+#header h1 {
+ float: left;
+ display: inline;
+}
+
+#header ul {
+ float: right;
+ display: inline;
+ list-style: none;
+ margin-top: 30px;
+}
+#header ul li {
+ float: left;
+ display: inline;
+}
+#header ul li a {
+ text-decoration: none;
+ float: left;
+ display: inline;
+ border-radius: 8px;
+ padding: 10px;
+ background: #474949;
+ border: 2px solid #616363;
+ padding: 8px;
+ margin-left: 10px;
+}
+#header ul li a:hover {
+ background: #3f634d;
+ border: 2px solid #3c8455;
+}
+ul.content {
+ float: left;
+ display: inline;
+}
+ul.content li {
+ float: left;
+ display: inline;
+ margin-bottom: 55px;
+ width: 100%;
+}
+ul.content li .left {
+ float: left;
+ display: inline;
+ width: 55%;
+ text-align: left;
+}
+ul.content li .left p {
+ padding: 0;
+ margin: 0;
+ font-size: 18px;
+}
+
+ul.content li .right {
+ float: left;
+ display: inline;
+ margin-right: 5%;
+ width: 40%;
+}
+ul.content li .right code {
+ width: 100%;
+}
+
+ul.content li .right p {
+ max-width: 440px;
+}
+#not-found {
+ text-align: center;
+ width: 600px;
+ margin: 0px auto;
+ margin-top: 200px;
+}
+#not-found h1 {
+ color: #6bffbd;
+ font-size: 32px;
+ margin-bottom: 20px;
+}
+#exception {
+ max-width: 900px;
+}
+#exception h1 {
+ font-size: 24px;
+}
+
+#exception ul {
+ margin: 0;
+ padding: 0;
+ margin-top: 20px;
+ list-style: none;
+}
+
+#exception table {
+ width: 100%;
+ margin-top: 20px;
+ border-collapse: collapse;
+}
+
+#exception tr {
+ border-radius: 8px;
+ padding: 10px;
+ background: #474949;
+ border: 2px solid #616363;
+ margin-bottom: 10px;
+ width: 100%;
+}
+
+#exception td {
+ padding: 10px;
+}
+
+#exception .dt {
+ text-align: right;
+}
+
+#exception .dd {
+ color: #91979d;
+ margin: 0;
+ padding-left: 5%;
+}
+
+#exception h1 span {
+ font-size: 18px;
+ font-weight: normal;
+ color: #91979d;
+}
+
+#exception .mine {
+ border-radius: 8px;
+ padding: 10px;
+ background: #3f634d;
+ border: 2px solid #3c8455;
+}
View
14 src/noir/core.clj
@@ -73,14 +73,14 @@
The default method is GET."
[& args]
- (let [{fn-name# :fn-name action# :action url# :url destruct# :destruct body# :body} (parse-args args)]
+ (let [{:keys [fn-name action url destruct body]} (parse-args args)]
`(do
- (defn ~fn-name# {::url ~url#
- ::action (quote ~action#)
- ::args (quote ~destruct#)} [~destruct#]
- ~@body#)
- (swap! route-funcs assoc ~(keyword fn-name#) ~fn-name#)
- (swap! noir-routes assoc ~(keyword fn-name#) (~action# ~url# {params# :params} (~fn-name# params#))))))
+ (defn ~fn-name {::url ~url
+ ::action (quote ~action)
+ ::args (quote ~destruct)} [~destruct]
+ ~@body)
+ (swap! route-funcs assoc ~(keyword fn-name) ~fn-name)
+ (swap! noir-routes assoc ~(keyword fn-name) (~action ~url {params# :params} (~fn-name params#))))))
(defmacro defpartial
"Create a function that returns html using hiccup. The function is callable with the given name."
View
2  src/noir/options.clj
@@ -2,7 +2,7 @@
"Allows access to Noir's server options"
(:refer-clojure :exclude [get]))
-(declare ^:dynamic *options*)
+(def ^:dynamic *options* nil)
(def default-opts {:ns (gensym)
:mode :dev})
View
7 src/noir/response.clj
@@ -21,6 +21,13 @@
{:headers {"Content-Type" "application/json"}
:body (json/generate-string content)})
+(defn jsonp
+ "Generates JSON for the given content and creates a javascript response for calling
+ func-name with it."
+ [func-name content]
+ {:headers {"Content-Type" "application/javascript"}
+ :body (str func-name "(" (json/generate-string content) ");")})
+
(defn status
"Wraps the content in the given status code"
[code content]
View
1  src/noir/server.clj
@@ -48,6 +48,7 @@
:mode - either :dev or :prod
:ns - the root namepace of your project
:jetty-options - any extra options you want to send to jetty like :ssl?
+ :base-url - the root url to prepend to generated links and resources
:resource-root - an alternative name for the public folder
:session-store - an alternate store for session handling
:cookie-attrs - custom session cookie attributes"
View
8 src/noir/server/handler.clj
@@ -4,6 +4,7 @@
ring.middleware.reload-modified)
(:import java.net.URLDecoder)
(:require [compojure.route :as c-route]
+ [hiccup.core :as hiccup]
[noir.core :as noir]
[noir.content.defaults :as defaults]
[noir.cookies :as cookie]
@@ -30,6 +31,12 @@
(wrap-reload-modified handler ["src"])
handler))
+(defn- wrap-base-url [handler]
+ (let [url (options/get :base-url)]
+ (fn [req]
+ (binding [hiccup/*base-url* url]
+ (handler req)))))
+
(defn- wrap-custom-middleware [handler]
(reduce (fn [cur [func args]] (apply func cur args))
handler
@@ -61,6 +68,7 @@
(binding [options/*options* (options/compile-options opts)]
(->
handler
+ (wrap-base-url)
(session/wrap-noir-session)
(cookie/wrap-noir-cookies)
(validation/wrap-noir-validation)
View
12 src/noir/session.clj
@@ -2,7 +2,7 @@
"Stateful session handling functions. Uses a memory-store by
default, but can use a custom store by supplying a :session-store
option to server/start. All keys are stored as strings."
- (:refer-clojure :exclude [get remove])
+ (:refer-clojure :exclude [get remove swap!])
(:use ring.middleware.session
ring.middleware.session.memory)
(:require [noir.options :as options]))
@@ -13,7 +13,7 @@
(defn put!
"Associates the key with the given value in the session"
[k v]
- (swap! *noir-session* assoc (name k) v))
+ (clojure.core/swap! *noir-session* assoc (name k) v))
(defn get
"Get the key's value from the session, returns nil if it doesn't exist."
@@ -21,6 +21,12 @@
([k default]
(clojure.core/get @*noir-session* (name k) default)))
+(defn swap!
+ "Replace the current session's value with the result of executing f with
+ the current value and args."
+ [f & args]
+ (apply clojure.core/swap! *noir-session* f args))
+
(defn clear!
"Remove all data from the session and start over cleanly."
[]
@@ -29,7 +35,7 @@
(defn remove!
"Remove a key from the session"
[k]
- (swap! *noir-session* dissoc (name k)))
+ (clojure.core/swap! *noir-session* dissoc (name k)))
(defn flash-put!
"Store a value with a lifetime of one retrieval (on the first flash-get,
View
2  src/noir/util/test.clj
@@ -48,5 +48,5 @@
"Send a request to the Noir handler. Unlike with-noir, this will run
the request within the context of all middleware."
[route & [params]]
- (let [handler (server/gen-handler)]
+ (let [handler (server/gen-handler options/*options*)]
(handler (make-request route params))))
View
14 test/noir/test/core.clj
@@ -1,6 +1,8 @@
(ns noir.test.core
(:use [noir.core]
- [compojure.core]
+ [compojure.core]
+ [hiccup.core :only [html]]
+ [hiccup.page-helpers :only [link-to]]
[noir.util.test])
(:use [clojure.test])
(:require [noir.util.crypt :as crypt]
@@ -203,6 +205,16 @@
(deftest url-for-throws
(is (thrown? Exception (url-for route-one-arg))))
+(defpage "/base-url" []
+ (html
+ (link-to "/hey" "link")))
+
+(deftest base-url
+ (binding [options/*options* {:base-url "/woohoo"}]
+ (-> (send-request "/base-url")
+ (has-status 200)
+ (has-body "<a href=\"/woohoo/hey\">link</a>"))))
+
(defpage "/with space" []
"space")
Please sign in to comment.
Something went wrong with that request. Please try again.