Skip to content

Commit

Permalink
elj-enlive-template first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
paulosuzart committed Mar 26, 2012
0 parents commit b53ba86
Show file tree
Hide file tree
Showing 13 changed files with 280 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .gitignore
@@ -0,0 +1,10 @@
/target
/lib
/classes
/checkouts
pom.xml
*.jar
*.class
.lein-deps-sum
.lein-failures
.lein-plugins
36 changes: 36 additions & 0 deletions README.md
@@ -0,0 +1,36 @@
# clj-enlive-template

A Leiningen template for projects using [Webnoir](http://www.webnoir.org/) plus [enlive](https://github.com/cgrand/enlive).

Enlive lets you work with `css` selectors agains your views, what IMO is a big advantage. It allows for working with pure html instead of hiccup - a great framework - vectors.

It comes with sample snippets as well as a main template to help you setup you own.

In future versions it will offer more common functions and view helper functions. Maybe korma or other persistence mecanishm.

## Usage

Don't forget to use either [lein2](http://leiningen.org/) or [lein-newnew](https://github.com/Raynes/lein-newnew). And then:

lein plugin install clj-enlive-template 0.0.1
lein new clj-enlive-template myproj
cd myproj
lein run

Done!

See the instructions in `myproj/README.md`

## Caveats for enlive

You may notice in the sample `_login` snippet that it takes as argument, the error list coming from `webnoir.validation/get-errors` instead of accessing it directly. Noir dynamic are not bound during the processing of the snippet.

The same happens with cookies.


## License

Copyright © 2012 [Paulo Suzart](http://paulosuzart.github.com/) ([@paulosuzart](http://twitter.com/paulosuzart)).

Distributed under the Eclipse Public License, the same as Clojure.

6 changes: 6 additions & 0 deletions project.clj
@@ -0,0 +1,6 @@
(defproject clj-enlive-template "0.0.1"
:description "lein-newnew template for web noir + enlive web apps"
:url "https://github.com/paulosuzart/clj-enlive-template"
:eval-in-leiningen true
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"})
22 changes: 22 additions & 0 deletions src/leiningen/new/clj_enlive_template.clj
@@ -0,0 +1,22 @@
(ns leiningen.new.clj-enlive-template
(:require [clojure.java.io :as io])
(:use leiningen.new.templates))

(def render (renderer "clj_enlive_template"))

(defn clj-enlive-template
"FIXME: write documentation"
[name]
(let [data {:name name
:sanitized (sanitize name)}]
(->files data
["project.clj" (render "project.clj" data)]
["README.md" (render "README.md" data)]
["resources/public/css/reset.css" (render "reset.css" data)]
["resources/public/css/default.css" (render "default.css" data)]
["src/{{sanitized}}/views/common.clj" (render "common.clj" data)]
["src/{{sanitized}}/views/login.clj" (render "login.clj" data)]
["src/{{sanitized}}/server.clj" (render "server.clj" data)]
["src/{{sanitized}}/views/layout/main.html" (render "main.html" data)]
["src/{{sanitized}}/views/_login.html" (render "_login.html" data)]
)))
35 changes: 35 additions & 0 deletions src/leiningen/new/clj_enlive_template/README.md
@@ -0,0 +1,35 @@
# {{name}}

A simple project for creating web apps using [Webnoir](http://www.webnoir.org/) plus [enlive](https://github.com/cgrand/enlive).

## Usage

```bash
lein deps
lein run
```


## Some tips (remove this section)

Then browse to `http://localhost:8090/login`. This page does nothing. It just has tow fileds backaed by a enlive snippet and `noir.validation`.'

As a convention, I would recommend you to keep the following structure to your projetc:

|-{{name}}
|---views
|-----layout # put main templates here
|-------main.html
|-----_login.html # put an _ in front of snippet files
|-----commont.clj # common view functions
|-----login.clj # defpages to handle /login/*
|-----foo # defpages to handle /foo/*


## License

Copyright (C) 2012 FIXME

Distributed under the Eclipse Public License, the same as Clojure.


11 changes: 11 additions & 0 deletions src/leiningen/new/clj_enlive_template/_login.html
@@ -0,0 +1,11 @@
<form method="post" id="login_form">
<div id="errors">
<span class="error"/>
</div>
<input type="hidden" id="to_url" name="to_url"/>
<label for="username">Username</label>
<input type="text" id="username" name="username"/>
<label for="password">Password</label>
<input type="text" id="password" name="password"/>
<input type="submit" value="Login"/>
</form>
18 changes: 18 additions & 0 deletions src/leiningen/new/clj_enlive_template/common.clj
@@ -0,0 +1,18 @@
(ns {{name}}.views.common
(:require [net.cgrand.enlive-html :as h]))

(defn show-errors [msgs]
(h/clone-for [i msgs]
[:span.error]
(h/content i)))


(h/deftemplate lay "{{name}}/views/layout/main.html"
[content]

[:#wrapper]
(h/content content))

(defn do-layout [content]
(lay content))

6 changes: 6 additions & 0 deletions src/leiningen/new/clj_enlive_template/default.css
@@ -0,0 +1,6 @@
body { padding: 75px 80px; background: #454545; color: #b2b2b2; font-family: "Helvetica Neue", "Verdana", sans-serif;}
a {text-decoration:none; color: #b2b2b2; }

#wrapper { margin:auto; width: 1024px; }

.alert { border-radius:10px; background: #3f634d; border: 2px solid #3c8455; padding: 15px; }
53 changes: 53 additions & 0 deletions src/leiningen/new/clj_enlive_template/login.clj
@@ -0,0 +1,53 @@
(ns {{name}}.views.login
(:require [net.cgrand.enlive-html :as h]
[noir.validation :as v])
(:use [noir.core :only [defpage render noir-routes]]
[noir.response :only [redirect]]
[{{name}}.views.common :only [show-errors do-layout]]))


(defn valid?
"Validates the form content."
[{:keys [username password]}]

;; you may internationalize these messages.
(v/rule (v/min-length? username 5)
[:username "Ooops. At least 5 chars for username."])

(v/rule (v/min-length? password 3)
[:password "Password should have at least 3 chars."])

(not (and (v/errors? :username :password))))


;; Snippet used at `/login`. Display the login form.
;; `errors` are passed as argument because
;; `noir.validation/get-errors` can not be called from inside
;; enlive template. The vars gets ubound.
(h/defsnippet _login "{{name}}/views/_login.html" [:#login_form]
[username password & [errors]]

[:div#errors]
(show-errors errors)

[:input#username]
(h/set-attr :value username)

[:input#password]
(h/set-attr :value password))


(defpage "/login" {:as login}
(time (do-layout (_login (:username login)
(:password login)
(:error login)))))

(defpage [:post "/login"] {:as login}
(if (valid? login)
(do-layout (format "Yeah!! Welcome %s" (:username login)))
(render "/login" (assoc login :error (v/get-errors)))))

;; I know you'll forget to browse to /login.
;; This route will do the job ;).
(defpage "/" {}
(redirect "/login"))
13 changes: 13 additions & 0 deletions src/leiningen/new/clj_enlive_template/main.html
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta name="description" content="Simple clojure webnoir project generated by Paulo Suzart's clj-enlive-template"/>
<title>{{name}}</title>
<link type="text/css" rel="stylesheet" href="/css/reset.css">
<link type="text/css" rel="stylesheet" href="/css/default.css">
<body>
<div id="wrapper">
<!--content goes here-->
</div>
</body>
</html>
7 changes: 7 additions & 0 deletions src/leiningen/new/clj_enlive_template/project.clj
@@ -0,0 +1,7 @@
(defproject {{name}} "0.1.0-SNAPSHOT"
:description "FIXME: write this!"
:url "http://exampl.com/FIXME"
:dependencies [[org.clojure/clojure "1.3.0"]
[noir "1.3.0-beta1"]
[enlive "1.0.0"]]
:main ^{:skip-aot true} {{name}}.server)
53 changes: 53 additions & 0 deletions src/leiningen/new/clj_enlive_template/reset.css
@@ -0,0 +1,53 @@
html {
margin:0;
padding:0;
border:0;
}

body, div, span, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, code,
del, dfn, em, img, q, dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, dialog, figure, footer, header,
hgroup, nav, section {
margin: 0;
padding: 0;
border: 0;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
font-family: inherit;
vertical-align: baseline;
}

article, aside, dialog, figure, footer, header,
hgroup, nav, section {
display:block;
}

body {
line-height: 1.5;
background: white;
}

table {
border-collapse: separate;
border-spacing: 0;
}

caption, th, td {
text-align: left;
font-weight: normal;
float:none !important;
}
table, th, td {
vertical-align: middle;
}

blockquote:before, blockquote:after, q:before, q:after { content: ''; }
blockquote, q { quotes: "" ""; }

a img { border: none; }

10 changes: 10 additions & 0 deletions src/leiningen/new/clj_enlive_template/server.clj
@@ -0,0 +1,10 @@
(ns {{name}}.server
(:require [noir.server :as server]))

(server/load-views "src/{{name}}/views")

(defn -main [& m]
(let [mode (keyword (or (first m) :dev))
port (Integer. (get (System/getenv) "PORT" "8090"))]
(server/start port {:mode mode
:ns '{{name}}})))

0 comments on commit b53ba86

Please sign in to comment.