ClojureHomePage is a Clojure Web Framework that provides the following.
- Run Clojure inside a HTML file with the
<clj></clj>tags - Request params ex. ($p userid)
- Common web headers ex. ($ user-agent)
- Web Headers ex. ($$ cache-control)
- Environmental variables ex. (env java.vm.name)
- Have multiple method handlers under a single route (get, post, put, delete, and head)
- Routes can be defined in seperate files and namespaces
- Style templates can be written in CHTML ex. chp.template/using-template
- Create SQL database schemas ex. lein schema
- Perform SQL database migrations ex. lein migrate
- Perform migration rollbacks ex. lein rollback
- Manipulate SQL databases with KormaSQL
- Generate Page views (new,view,edit,list)
- Generate JavaScript / ECMAScript
- Generate HTML
- Generate CSS
Documentation
CHTML, Routing, and Sessions
Ring
Code Generation, Modules, and JSON API
- Generating views from a table
- View bindings
- View bindings Example
- Enable admin account
- Database and Bindings tutorial
- HTML Generation
- CSS Generation
- JavaScript Generation
- CHP Modules
- Module Packages
- JSON API
- Auto Documenting API
SQL Configuration, Migrations, and Manipulation
General Information
- Install
- UML Relationships
- Namespace Dependencies
- Unit Tests
- Removing example files
- License
- How?
- Tutorial
Example CHTML & Routes
Routes can be stored in two places
- File: src/chp/handler.clj
- Folder: src/chp/routes/
The following link is the chtml page that is used in the example below. test-page.chtml
More CHTML examples are located in chp-root
Routes Example
(defchp app-routes ;; Load CHP File (chp-route "/chtml" (binding [*title* "Test Page Example"] (or (root-parse "test-page.chtml") "error"))) (chp-route "/chp" ;; root-parse = root-path "/" file (or (root-parse "chp-info.chtml") "error")) (chp-route "/session" (or (root-parse "session-example.chtml") "error")) ;; Named params (chp-route "/index/:id" (format "ID is %s" (escape ($p id)))) (chp-route "/index/:id/:action" (format "Action is %s" (escape ($p action)))) ;; Multiple handlers under a single route (chp-route "/testing" (or (chp-when :post "POST METHOD RETURN") (chp-when :get (str (format "chp-body wasn't used to access %s from %s with %s" ($ uri) ($ ip) ($ user-agent)) (format "<p>Tracking you? DNT HTTP Header = %s</p>" ($$ dnt)) (format "<p>HTTP Header cache-control = %s</p>" ($$ cache-control)))) "Not Found")) ;; Multiple handlers under a single route (chp-route "/" (let [display (str (format "Method %s <br />" (escape ($ method))) (format "URI %s <br />" (escape ($ uri))) (format "Params %s <br />" (escape ($ params))) (format "Header Values <p>%s</p>" (with-out-str (doseq [[k v] (escape-map ($ headers))] (println k "=" v "<br />")))) (format "Server Name %s <br /> Server IP %s" ($ server-name) ($ server-ip)))] (chp-body {:-get (str "Get => " display) :-post (str "Post => " display) :-not-found "Sorry, but this page doesn't exist"}))) ;; Bind to templates (chp-route "/template" (using-template "example.chtml" {:body "chp-info.chtml" :test-tag "test-page.chtml"})) (route/resources "/") (route/not-found "Not Found")) (def app (chp-site example-routes app-routes))
Session handling, Cookies, and Compojure
Sessions are handled with the lib-noir.session namespace under the session alias.
This session example can be accessed at site.com/session
You have viewed this page <clj> (let [k :view-count inc-view (if (nil? (session/get k)) (k (session/put! k 1)) (k (session/update-in! [k] inc)))] (print inc-view)) </clj> time(s).
Because CHP is based on Compojure, you can use Compojure and Ring extensions. These middleware extensions should be added to the chp-routing function of the chp.core namespace. Below is what the function currently looks like.
(defn chp-routing [& -chp-routes] ;;; (-> (apply routes ...) middleware-wrap xyz-wrap) (let [auto-middleware (fn [x] (let [wrapped (atom x)] (doseq [m (load-middleware)] (swap! wrapped m)) @wrapped))] (-> (apply routes (reduce into [] -chp-routes)) wrap-noir-flash wrap-noir-session auto-middleware)))
Already included, but not loaded by default (except noir.session), the lib-noir library is a great helper library for Clojure web development.
Ring configuration
The default configuration for CHP is located in project.clj
:ring {:port 8000
:auto-reload? true
:auto-refresh? true
:reload-paths ["src/chp/"
"chp-root/"
"resources/middleware/"
"resources/public/"]
:handler chp.handler/app}Auto-loading Middleware
Middleware is automatically loaded from '''resources/middleware/*.clj''' when the server starts. The middleware is evaluated in the chp.core namespace with the load-middleware fn. All middleware is reloaded when triggering the ring-autoload.
$ cat resources/middleware/example.clj
;; This file is automatically loaded as middleware ;; and should only contain one function. (defn example-middleware [handler] (fn [request] (let [resp (handler request) headers (:headers resp)] (println "resources/middleware/example.clj says " "- Incoming request >> " headers) resp)))
DB Configuration and Creation
A Korma SQL and Lobos compatible SQL connection configuration file is located at resources/config/db.clj
The SQL database tables are located in resources/schema/. These files can contain an unlimited amount of create calls and get evaluated by the lein alias lein schema
$ lein schema Creating Table => resources/schema/example.clj OKAY Creating Table => resources/schema/user.clj OKAY
The Lobos library handles the table syntax. Below is the user table from user.clj.
(create *db* (table :user (integer :id :primary-key :auto-inc) (varchar :name 20) (varchar :password 100) (unique [:name]))) (create *db* (table :some_other_table (integer :id :primary-key :auto-inc) (varchar :name 20) (varchar :password 100) (unique [:name])))
DB Migrations
Perform migration
$ lein migrate add-topic-table add-topic-subject-table add-tag-table
Lobos migration files
$ cat resources/migrations/01-add-topic-tables.clj
(defmigration add-topic-table (up [] (create (tbl :topic (varchar :title 50 :unique) (text :content)))) (down [] (drop (table :topic)))) (defmigration add-topic-subject-table (up [] (create (tbl :topicSubject (varchar :title 50 :unique) (integer :id :auto-inc :primary-key)))) (down [] (drop (table :topicSubject))))
$ cat resources/migrations/02-add-tag-table.clj
(defmigration add-tag-table (up [] (create (tbl :tag (varchar :title 25) (integer :id :auto-inc :primary-key)))) (down [] (drop (table :tag))))
Tables after migration
example=# \dt List of relations Schema | Name | Type | Owner --------+------------------+-------+------- public | example | table | on public | lobos_migrations | table | on public | tag | table | on public | topic | table | on public | topicSubject | table | on public | user | table | on (6 rows)
Rollbacks
$ lein rollback add-tag-table $ lein rollback add-topic-subject-table
Tables after rollback
example-# \dt List of relations Schema | Name | Type | Owner --------+------------------+-------+------- public | example | table | on public | lobos_migrations | table | on public | topic | table | on public | user | table | on (4 rows) example-#
ClojureHomePage uses the SQLKorma DSL by default. korma.db is required as kdb and korma.core is required as kc
Get column syntax example
The $cljdb macro binds a row and allows the $db macro to retrieve columns of the row. Example, ($cljdb table-keyword where-clause & code-body)
Here's how to use these macros
chp.test.core> ($cljdb :user {:id 2} (format "%s id is %d" ($db name) ($db id))) "admin id is 2" chp.test.core> (kc/select {:table "user"} (kc/fields :name :id)) [{:id 2, :name "admin"}]
Generating Table Views
$ lein gen user resources/generation-templates/routes/name.clj -> src/chp/routes/user.clj resources/generation-templates/chtml/new.chtml -> chp-root/user/new.chtml resources/generation-templates/chtml/edit.chtml -> chp-root/user/edit.chtml resources/generation-templates/chtml/view.chtml -> chp-root/user/view.chtml resources/generation-templates/chtml/list.chtml -> chp-root/user/list.chtml URL DATA BOUND TO => resources/bindings/user.clj site.com/new/user site.com/list/user site.com/edit/user/:id site.com/view/user/:id $ cat resources/bindings/user.clj
;; Example bindings for resources/schema/user.clj ;; All values will be retrieved by the id column ;; table must match the filename withut the clj extension ;; user.clj -> user {:table :user ;; List view value ;; (chp.builder/binding-list :user 0 10) ;; /chp/list/user :list (list :name :id) ;; View view values ;; (chp.builder/binding->view :user 1) ;; site.com/chp/view/user/:id :view (list :name :password :admin) ;; Edit view values ;; (chp.builder/binding->edit :user 1) ;; site.com/chp/edit/user/:id ;; site.com/chp/new/user ;; edit is a hash-set with table columns ;; as the key and the chp.html namespace ;; function used to display the value. :edit {:name #(text-field :name (escape %)) :password #(password-field :password (escape %)) :admin #(check-box :admin (Boolean/valueOf %))} ;; enforce data type with fn to check and ;; or convert before going into database. ;; The function must take one arg. ;; :name is limited to a string of 20 chars ;; :password is limited to 100 chars ;; :admin mut be a boolean value :edit-enforce {:name #(->> % str seq (take 20) (apply str)) :password #(->> % str seq (take 100) (apply str)) :admin #(Boolean/valueOf %)}}
Builder Bindings
The example user.clj bindings below will be used to make the new, list, view, and edit pages of the user table in schema/user.clj.
;; Example bindings for resources/schema/user.clj ;; All values will be retrieved by the id column ;; table must match the filename withut the clj extension ;; user.clj -> user {:table :user ;; List view value ;; (chp.builder/binding-list :user 0 10) ;; /chp/list/user :list (list :name :id) ;; View view values ;; (chp.builder/binding->view :user 1) ;; site.com/chp/view/user/:id :view (list :name :password :admin) ;; Edit view values ;; (chp.builder/binding->edit :user 1) ;; site.com/chp/edit/user/:id ;; site.com/chp/new/user ;; edit is a hash-set with table columns ;; as the key and the chp.html namespace ;; function used to display the value. :edit {:name #(text-field :name (escape %)) :password #(password-field :password (escape %)) :admin #(check-box :admin (Boolean/valueOf %))} ;; enforce data type with fn to check and ;; or convert before going into database. ;; The function must take one arg. :edit-enforce {:name str :password str :admin #(Boolean/valueOf %)}}
Builder binding views example
$ cd chp
$ cat resources/schema/user.clj (create *db* (table :user (integer :id :primary-key :auto-inc) (varchar :name 20) (varchar :password 100) (boolean :admin) (unique [:name])))
$ lein schema Creating Table => resources/schema/example.clj OKAY Creating Table => resources/schema/user.clj OKAY $ lein gen user resources/generation-templates/routes/name.clj -> src/chp/routes/user.clj resources/generation-templates/chtml/new.chtml -> chp-root/user/new.chtml resources/generation-templates/chtml/edit.chtml -> chp-root/user/edit.chtml resources/generation-templates/chtml/view.chtml -> chp-root/user/view.chtml resources/generation-templates/chtml/list.chtml -> chp-root/user/list.chtml URL DATA BOUND TO => resources/bindings/user.clj site.com/new/user site.com/list/user site.com/edit/user/:id site.com/view/user/:id $ psql example psql (9.2.4) Type "help" for help. example=# INSERT INTO "user" (name,password,admin) VALUES ('user1','badcleartext',true); example=# \q $ lein ring server & Jun 24, 2013 3:40:47 PM com.mchange.v2.log.MLog <clinit> INFO: MLog clients using java 1.4+ standard logging. 2013-06-24 15:40:47.999:INFO:oejs.Server:jetty-7.6.1.v20120215 2013-06-24 15:40:48.064:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8000 Started server on port 8000 # In another terminal ### $ telnet localhost 8000 Trying ::1... Connected to localhost. Escape character is '^]'. GET /list/user
Viewing table of user
```bash Connection closed by foreign host.$ telnet localhost 8000 Trying ::1... Connected to localhost. Escape character is '^]'. GET /view/user/1
<h1>Viewing 1
</h1>
[name user1]
[password badcleartext]
[admin true]
```bash
Connection closed by foreign host.
$ telnet localhost 8000
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET /edit/user/1
<h1> Editing user #1 </h1>
<form action="/edit/user/1
" method="POST">
<label for=":admin">admin</label><br /><input checked="checked" id="admin" name="admin" type="checkbox" value="true" /><br /><br /><label for=":password">password</label><br /><input id="password" name="password" type="password" value="badcleartext" /><br /><br /><label for=":name">name</label><br /><input id="name" name="name" type="text" value="user1" /><br /><br /> <input type="submit" value="save" />
</form>
Connection closed by foreign host.
Enable Admin Account
[user@machine ~]$ cd /tmp/; mkdir admin-example; cd admin-example; [user@machine admin-example]$ git clone https://github.com/runexec/chp.git Cloning into 'chp'... remote: Counting objects: 594, done. remote: Compressing objects: 100% (331/331), done. remote: Total 594 (delta 287), reused 501 (delta 194) Receiving objects: 100% (594/594), 160.96 KiB | 34.00 KiB/s, done. Resolving deltas: 100% (287/287), done. [user@machine admin-example]$ cd chp/ [user@machine chp]$ ls chp-examples/ chp-root/ resources/ src/ test/ tutorial/ project.clj README.md [user@machine chp]$ rm -rf chp-examples/ tutorial/ [user@machine chp]$ cat resources/schema/user.clj
(create *db* (table :user (integer :id :primary-key :auto-inc) (varchar :name 20) (varchar :password 128) (varchar :salt 128) (boolean :admin) (unique [:name])))
[user@machine chp]$ lein schema Creating Table => resources/schema/user.clj OKAY Creating Table => resources/schema/example.clj OKAY [user@machine chp]$ lein migrate Jun 30, 2013 2:47:07 AM com.mchange.v2.log.MLog <clinit> INFO: MLog clients using java 1.4+ standard logging. create-chp-admin
The admin password is located in the migration file resources/migrations/01-add-admin.clj
;; (chp.password/salt-set "your password here")
[user@machine chp]$ cat resources/migrations/01-add-admin.clj
(let [table (kc/create-entity "user")] (comment Assuming resources/schema/user.clj (table :user (integer :id :primary-key :auto-inc) (varchar :name 20) (varchar :password 128) (varchar :salt 128) (boolean :admin) (unique [:name]))) (defmigration create-chp-admin (up [] (let [{:keys [salt password]} (chp.password/salt-set "admin")] (kc/insert table (kc/values {:name "admin" :password password :salt salt :admin true})))) (down [] (kc/delete table (kc/where {:name "admin"})))))
[user@machine chp]$ lein ring server Jun 30, 2013 2:54:20 AM com.mchange.v2.log.MLog <clinit> INFO: MLog clients using java 1.4+ standard logging. 2013-06-30 02:54:21.391:INFO:oejs.Server:jetty-7.6.1.v20120215 2013-06-30 02:54:21.489:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8000 Started server on port 8000 ### In a new shell ### [user@machine chp]$ curl --data "username=admin&password=admin" http://localhost:8000/chp/login <html> <head><title>Login Handler</title></head> <body> Logged in{:user "admin", :logged-in? true} </body> </html> [user@machine chp]$ curl --data "username=admin&password=adminadasdsad" http://localhost:8000/chp/login <html> <head><title>Login Handler</title></head> <body> Login Failed </body> </html>
Basic bindings example
##### get CHP [user@machine ~]$ mkdir blog; cd blog/ [user@machine blog]$ git clone https://github.com/runexec/chp.git Cloning into 'chp'... remote: Counting objects: 456, done. remote: Compressing objects: 100% (224/224), done. remote: Total 456 (delta 208), reused 413 (delta 165) Receiving objects: 100% (456/456), 144.89 KiB | 80.00 KiB/s, done. Resolving deltas: 100% (208/208), done. [user@machine blog]$ cd chp/; ls chp-examples/ chp-root/ resources/ src/ test/ tutorial/ project.clj README.md ##### Remove extra directories [user@machine chp]$ rm -rf chp-examples/ tutorial/ ##### Create Database configuration and db [user@machine chp]$ cd resources/config/ [user@machine config]$ emacs -nw -q db.clj [user@machine config]$ psql example -c 'CREATE DATABASE "blog";' CREATE DATABASE ##### Create tables [user@machine config]$ cd ../schema/ [user@machine schema]$ cat user.clj (create *db* (table :user (integer :id :primary-key :auto-inc) (varchar :name 20) (varchar :password 128) (varchar :salt 128) (boolean :admin) (unique [:name]))) [user@machine schema]$ emacs -nw news.clj [user@machine schema]$ cat news.clj (create *db* (table :news (integer :id :primary-key :auto-inc) (integer :userid) (varchar :title 100) (text :body) (unique [:title]))) [user@machine schema]$ lein schema Creating Table => resources/schema/user.clj OKAY Creating Table => resources/schema/news.clj OKAY ##### Create binding [user@machine bindings]$ emacs -nw news.clj [user@machine bindings]$ cat news.clj {:table :news :list (list :title :id) :view (list :title :body) :edit {:title #(text-field :title (escape %)) :body #(text-area :body (escape %))} :edit-enforce {:title #(->> % str seq (take 100) (apply str)) :body str}} ##### Create Views [user@machine bindings]$ lein gen news Jul 14, 2013 9:59:55 AM com.mchange.v2.log.MLog <clinit> INFO: MLog clients using java 1.4+ standard logging. resources/generation-templates/routes/name.clj -> src/chp/routes/news.clj resources/generation-templates/chtml/new.chtml -> chp-root/news/new.chtml resources/generation-templates/chtml/edit.chtml -> chp-root/news/edit.chtml resources/generation-templates/chtml/view.chtml -> chp-root/news/view.chtml resources/generation-templates/chtml/list.chtml -> chp-root/news/list.chtml URL DATA BOUND TO => resources/bindings/news.clj site.com/new/news site.com/list/news site.com/edit/news/:id site.com/view/news/:id ##### Add Routes to chp/src/chp/handler.clj
(:require [chp.routes.news :refer [news-table-routes]]) (def app (chp-site news-table-routes example-routes user-table-routes chp-builder-paths app-routes))
[user@machine bindings]$ lein ring server Jul 06, 2013 9:29:46 PM com.mchange.v2.log.MLog <clinit> INFO: MLog clients using java 1.4+ standard logging. 2013-07-06 21:29:47.735:INFO:oejs.Server:jetty-7.6.1.v20120215 2013-07-06 21:29:48.834:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8000 Started server on port 8000 ##### Create new blog post [user@machine bindings]$ firefox http://localhost:8000/new/news
Clojure and HTML Generation
The following methods presented in the documentation below are accessible from within CHTML files by default. These abstractions are drop-in replacements for the Hiccup API located at http://weavejester.github.io/hiccup/. Please note that these forms DO NOT generate Hiccup code, but HTML.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Form Fields (escape string) (url-encode string) (check-box attr-map? name) (check-box attr-map? name checked?) (check-box attr-map? name checked? value) (drop-down attr-map? name options) (drop-down attr-map? name options selected) (email-field attr-map? name) (email-field attr-map? name value) (file-upload attr-map? name) (form-to attr-map? [method action] & body) (hidden-field attr-map? name) (hidden-field attr-map? name value) (label attr-map? name text) (password-field attr-map? name) (password-field attr-map? name value) (radio-button attr-map? group) (radio-button attr-map? group checked?) (radio-button attr-map? group checked? value) (reset-button attr-map? text) (select-options attr-map? coll) (select-options attr-map? coll selected) (submit-button attr-map? text) (text-area attr-map? name) (text-area attr-map? name value) (text-field attr-map? name) (text-field attr-map? name value) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Common Elements (javascript-tag script) (image attr-map? src) (image attr-map? src alt) (link-to attr-map? url & content) (mail-to attr-map? e-mail & [content]) (ordered-list attr-map? coll) (unordered-list attr-map? coll)
Clojure and CSS Generation
ClojureHomePage uses the Garden CSS generation library by default. The Garden documentation page is located at https://github.com/noprompt/garden
Clojure and JavaScript Generation
ClojureHomePage uses ClojureScript and lein-cljsbuild to generate javascript. CHP uses the directory resources/cljs/ as the default cljs source code directory.
Modules
Modules are optional resources that are shipped with every release.
$ lein mod-enable middleware verbose-log example Copying resources/modules/middleware/verbose-log.clj -> resources/middleware/verbose-log.clj Copying resources/modules/middleware/example.clj -> resources/middleware/example.clj $ lein mod-disable middleware verbose-log Deleting resources/middleware/verbose-log.clj $ lein mod-list resources/modules resources/modules/migrations resources/modules/migrations/01-add-admin.clj resources/modules/cljs resources/modules/middleware resources/modules/middleware/example.clj resources/modules/middleware/operating-status.clj resources/modules/middleware/text-mime-only.clj resources/modules/middleware/verbose-log.clj resources/modules/schema resources/modules/schema/example.clj resources/modules/schema/user.clj resources/modules/schema/blog-post.clj resources/modules/bindings resources/modules/bindings/user.clj
Module Packages
Module packages are stored in resources/packages/. Each package is a clj file that describes what modules to install when calling lein package-run name1 name2 etc...
$ cat resources/packages/admin.clj
;; CHP Admin module ;; {:module-type [:module :module :module etc..]} {:schema [:user] ;; resources/modules/schema/user.clj :migrations [:01-add-admin] ;; resources/modules/migrations/01-add-admin.clj :bindings [:user] ;; resources/modules/bindings/user.clj :middleware [] ;; resources/modules/middleware/ -- nothing :cljs [] ;; resources/modules/cljs/ -- nothing :api []} ;; resources/modules/api/ -- nothing
$ lein package-run admin Loading for :schema Copying resources/modules/schema/user.clj -> resources/schema/user.clj Creating Table => resources/schema/user.clj OKAY Loading for :migrations Copying resources/modules/migrations/01-add-admin.clj -> resources/migrations/01-add-admin.clj Jul 09, 2013 7:52:37 PM com.mchange.v2.log.MLog <clinit> INFO: MLog clients using java 1.4+ standard logging. create-chp-admin Loading for :bindings Copying resources/modules/bindings/user.clj -> resources/bindings/user.clj Loading for :middleware Loading for :cljs Loading for :api
JSON API
To enable the JSON read-only API, create an API config file in resources/api/. Once this configuration file is made, you can access JSON values @ site.com/chp/api/{table-name}
GET params can be used to locate specific values. If the params aren't listed in the configuration, the extra params are ignored.
$ cat resources/api/user.clj
;; API settings for the User table ;; the filename must be the same as the table name ;; {:table :user} => user.clj {:table :user :return [:id :name] ;; The where key holds a map that describes ;; columns that can be used to locate the ;; data. ;; Each column key needs to have a function ;; as the value that accepts one arg. This ;; function needs to convert the arg to the ;; proper data type. ;; The single arg is a string from the uri :where {:id #(Integer. %) :name str :admin #(Boolean. %)}}
$ curl http://localhost:8000/chp/api/user; echo " << done" {"data": [{ "name" : "admin", "id" : 1 },{ "name" : "example", "id" : 3 }]} << done $ curl http://localhost:8000/chp/api/user?id=3; echo " << done" {"data": [{ "name" : "example", "id" : 3 }]} << done $ curl http://localhost:8000/chp/api/user?name=admin; echo " << done" {"data": [{ "name" : "admin", "id" : 1 }]} << done $ curl http://localhost:8000/chp/api/userasdasd; echo " << done" An error occured << done
JSON API Documentation Page
After creating an API config file in resources/api/, you can view the dynamically generated API documentation at site.com/chp/api.
Before showing the documentation page, here's what the default user API config looks like.
$ cat resources/api/user.clj
;; API settings for the User table ;; the filename must be the same as the table name ;; {:table :user} => user.clj {:table :user :return [:id :name] ;; The where key holds a map that describes ;; columns that can be used to locate the ;; data. ;; Each column key needs to have a function ;; as the value that accepts one arg. This ;; function needs to convert the arg to the ;; proper data type. ;; The single arg is a string from the uri :where {:id #(Integer. %) :name str :admin #(Boolean. %)}}
And here's what the documentation looks like for all config files in resources/api/
$ curl localhost:8000/chp/api
Available API
user
Data Link: userGetting started
- Download & Run
git clone https://github.com/runexec/chp
cd chp
lein ring server- Edit the default app-routes template located at the bottom of src/chp/handler.clj
UML
Full image size at https://raw.github.com/runexec/chp/master/violet-uml-workings.png
(2013-07-08 JST) NOTICE: This graph is not consistent with the latest update(s) and contains minor errors.
Namespace Dependencies
(Generated by ntable) https://github.com/runexec/ntable
chp/src/chp/routes/example.clj
:use chp.core compojure.core [chp.html :only [escape]]chp/src/chp/routes/user.clj
:use chp.corechp/src/chp/routes/chp.clj
:use chp.core [cheshire.core :only [generate-string]] [chp.api :only [api->where]] [chp.builder :only [binding-exist?]]chp/src/chp/clean.clj
chp/src/chp/migration.clj
:refer-clojure :exclude [complement alter drop bigint boolean char double float time] :use [chp.db :only [*db*]] (lobos core connectivity migration)chp/src/chp/password.clj
chp/src/chp/handler.clj
:use compojure.core chp.html chp.template [chp.core :exclude [korma-db]] [chp.api :only [api->where api-dir]] [chp.db :only [*db*]] [garden.core :only [css]] :require chp.server [compojure.route :as route] [korma.db :as kdb] [korma.core :as kc] [noir.session :as session] [chp.routes.chp :refer [chp-builder-paths]] [chp.routes.example :refer [example-routes]] [chp.routes.user :refer [user-table-routes]]chp/src/chp/html.clj
:require hiccup.core hiccup.util hiccup.form hiccup.elementchp/src/chp/server.clj
chp/src/chp/api.clj
:use [chp.db :only [*db*]] :require [korma.db :as kdb] [korma.core :as kc]chp/src/chp/package.clj
:refer-clojure :exclude [bigint boolean char double float time] :use [chp.schema :only [load-schemas]] [chp.migration :only [chp-migrate]] [chp.module :only [mod-enable]]chp/src/chp/template.clj
:use chp.corechp/src/chp/builder.clj
:use [chp.db :only [*db*]] [chp.core :exclude [korma-db]] chp.html chp.password [chp.login :exclude [korma-db]] :require [korma.core :as kc] [korma.db :as kdb] [noir.session :as session]chp/src/chp/login.clj
:require [korma.db :as kdb] [korma.core :as kc] :use [chp.db :only [*db*]] [chp.password :only [password]]chp/src/chp/core.clj
:use compojure.core [noir.session :only [wrap-noir-flash wrap-noir-session]] [chp.db :only [*db*]] :require chp.server [compojure.handler :as handler] [clojure.string :as string] [korma.db :as kdb] [korma.core :as kc]chp/src/chp/generator.clj
:use [chp.core :only [root-path]]chp/src/chp/module.clj
:require [clojure.java.io :as io]chp/src/chp/db.clj
chp/src/chp/schema.clj
:refer-clojure :exclude [bigint boolean char double float time] :use [chp.db :only [*db*]] [lobos.core :only [create]]
How?
By default, the CHTML files are located in chp-root folder of the project folder.
When a CHTML file is parsed, all public variables of the chp.handler namespace
are accessible during the evaluation of the <clj></clj> tags. Use print
or println within the tags to have the results displayed.
Removing Example Files
$ ls chp-examples/ chp-root/ resources/ src/ target/ test/ tutorial/ project.clj README.md $ lein chp-clean Removing README.md Removing resources/schema Removing resources/schema/example.clj Removing resources/schema/user.clj Removing resources/bindings Removing resources/bindings/user.clj Removing resources/migrations Removing resources/migrations/02-add-tag-table.clj Removing resources/migrations/01-add-topic-tables.clj $ ls chp-root/ resources/ src/ target/ test/ project.clj $ ls resources/ bindings/ cljs/ config/ generation-templates/ migrations/ public/ schema/
License
Copyright © 2013 Runexec
Distributed under the Eclipse Public License, the same as Clojure.
