Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

improved sub application modularization and template rendering layout…

… system, updated examples due to changes
  • Loading branch information...
commit 2db3c3ed93d7c6386dfd809f431879b14b90c712 1 parent 69680ed
kadirpekel authored July 03, 2011

Showing 31 changed files with 165 additions and 82 deletions. Show diff stats Hide diff stats

  1. 13  README.md
  2. 4  examples/coffeekup/views/layout.coffeekup
  3. 17  examples/coffeekup/views/main.coffeekup
  4. 2  examples/connect/app.coffee
  5. 7  examples/connect/layout.eco
  6. 2  examples/helpers/app.coffee
  7. 7  examples/helpers/layout.eco
  8. 7  examples/layout/app.coffee
  9. 2  examples/layout/layout.eco
  10. 6  examples/sandbox/base/index.coffee
  11. 10  examples/sandbox/base/views/layout.eco
  12. 6  examples/sandbox/comments/index.coffee
  13. 1  examples/sandbox/comments/views/list.eco
  14. 6  examples/sandbox/extensions.coffee
  15. 18  examples/sandbox/index.coffee
  16. 6  examples/sandbox/posts/index.coffee
  17. 2  examples/sandbox/server.js
  18. 8  examples/sandbox/settings.coffee
  19. 2  examples/sandbox/{base/views/home.eco → templates/base/index.html}
  20. 18  examples/sandbox/templates/comment_layout.html
  21. 1  examples/sandbox/templates/comments/index.html
  22. 13  examples/sandbox/templates/layout.html
  23. 0  examples/sandbox/{posts/views/list.eco → templates/posts/index.html}
  24. 7  examples/simple_auth/layout.eco
  25. 2  examples/templating/app.coffee
  26. 7  examples/templating/layout.eco
  27. 2  examples/templating/main.eco
  28. 2  examples/templating/nested.eco
  29. 4  examples/websockets/app.coffee
  30. 63  lib/coffeemate.coffee
  31. 2  package.json
13  README.md
Source Rendered
@@ -32,7 +32,7 @@ mate.context.highlight = (color, txt) ->
32 32
 mate.get '/greet/:name', ->
33 33
 	# this is context variable
34 34
 	@greet_msg = "Hello, #{@req.params.name}"
35  
-	@render 'home.eco'
  35
+	@render 'home'
36 36
 
37 37
 # Stream it
38 38
 mate.io.sockets.on 'connection', (socket) ->
@@ -43,6 +43,17 @@ mate.listen 3000
43 43
 ```
44 44
 
45 45
 ``` html
  46
+<!-- layout.eco -->
  47
+<html>
  48
+  <head>
  49
+  </head>
  50
+  <body>
  51
+      <%- @include @body %>
  52
+  </body>
  53
+</html>
  54
+```
  55
+
  56
+``` html
46 57
 <!-- main.eco -->
47 58
 
48 59
 <h1>Welcome to Coffeemate</h1>
4  examples/coffeekup/views/layout.coffeekup
... ...
@@ -0,0 +1,4 @@
  1
+html ->
  2
+  head
  3
+  body ->
  4
+    include @body
17  examples/coffeekup/views/main.coffeekup
... ...
@@ -1,10 +1,7 @@
1  
-html ->
2  
-  head
3  
-  body ->
4  
-    h1 "A cup of coffee demonstration"
5  
-    div ->
6  
-      include "nested1"
7  
-    div ->
8  
-      include "nested2"
9  
-    div ->
10  
-      include "nested3"
  1
+h1 "A cup of coffee demonstration"
  2
+div ->
  3
+  include "nested1"
  4
+div ->
  5
+  include "nested2"
  6
+div ->
  7
+  include "nested3"
2  examples/connect/app.coffee
@@ -4,6 +4,6 @@ mate.logger()
4 4
 mate.static(__dirname + '/public')
5 5
 
6 6
 mate.get '/', ->
7  
-  @render 'main.eco'
  7
+  @render 'main'
8 8
     
9 9
 mate.listen 3000
7  examples/connect/layout.eco
... ...
@@ -0,0 +1,7 @@
  1
+<html>
  2
+  <head>
  3
+  </head>
  4
+  <body>
  5
+      <%- @include @body %>
  6
+  </body>
  7
+</html>
2  examples/helpers/app.coffee
@@ -4,6 +4,6 @@ mate.context.highlight = (msg) ->
4 4
   "<span style=\"background-color:#ff0\">#{msg}</span>"
5 5
     
6 6
 mate.get '/', ->
7  
-  @render 'main.eco'
  7
+  @render 'main'
8 8
 
9 9
 mate.listen 3000
7  examples/helpers/layout.eco
... ...
@@ -0,0 +1,7 @@
  1
+<html>
  2
+  <head>
  3
+  </head>
  4
+  <body>
  5
+      <%- @include @body %>
  6
+  </body>
  7
+</html>
7  examples/layout/app.coffee
... ...
@@ -1,12 +1,7 @@
1 1
 mate = require '../../lib/coffeemate'
2 2
 
3  
-# build your own layout structure
4  
-mate.context.custom_render = (template_name) ->
5  
-  @content = template_name
6  
-  @render 'layout.eco'
7  
-
8 3
 mate.get '/', ->
9 4
   @foo = 'bar'
10  
-  @custom_render 'main.eco'
  5
+  @render 'main'
11 6
 
12 7
 mate.listen 3000
2  examples/layout/layout.eco
@@ -2,7 +2,7 @@
2 2
   <head></head>
3 3
   <body>
4 4
     <div>This is HEADER</div>
5  
-    <div><%- @include @content %></div>
  5
+    <div><%- @include @body %></div>
6 6
     <div>This is FOOTER</div>
7 7
   </body>
8 8
 </html>
6  examples/sandbox/base/index.coffee
... ...
@@ -1,5 +1,3 @@
1  
-mate = require('../../../lib/coffeemate').newInstance()
  1
+mate = require '../../../lib/coffeemate'
2 2
 
3  
-mate.get '/', -> @view 'home'
4  
-
5  
-module.exports = mate
  3
+mate.get '/', -> @render 'base/index'
10  examples/sandbox/base/views/layout.eco
... ...
@@ -1,10 +0,0 @@
1  
-<html>
2  
-  <head>
3  
-  </head>
4  
-  <body>
5  
-    <img src="coffeescript.png" />
6  
-    <%- @include @view %>
7  
-    <hr />
8  
-    <a href="/">home</a>
9  
-  </body>
10  
-</html>
6  examples/sandbox/comments/index.coffee
... ...
@@ -1,5 +1,3 @@
1  
-mate = require('../../../lib/coffeemate').newInstance()
  1
+mate = require '../../../lib/coffeemate'
2 2
 
3  
-mate.get '/', -> @view 'list'
4  
-
5  
-module.exports = mate
  3
+mate.get '/', -> @render 'comments/index', 'comment_layout'
1  examples/sandbox/comments/views/list.eco
... ...
@@ -1 +0,0 @@
1  
-<h1>Comment List</h1>
6  examples/sandbox/extensions.coffee
... ...
@@ -1,6 +0,0 @@
1  
-mate = require '../../lib/coffeemate'
2  
-
3  
-mate.context.view = (viewname, layout) ->
4  
-  viewpath = @container.route.slice(1)
5  
-  @view = "#{viewpath}/views/#{viewname}.eco"
6  
-  @render if layout then "#{viewpath}/views/#{layout}.eco" else  "base/views/layout.eco"
18  examples/sandbox/index.coffee
... ...
@@ -1,19 +1,15 @@
1 1
 mate = require '../../lib/coffeemate'
2 2
 
3  
-# use some of connect middlewares
4  
-mate.logger()
5  
-mate.static("#{__dirname}/public")
6  
-
7  
-# import extensions
8  
-require './extensions'
  3
+# import configuration
  4
+require './settings'
9 5
 
10 6
 # import sub applications
11  
-mate.use '/base', require './base'
12  
-mate.use '/posts', require './posts'
13  
-mate.use '/comments', require './comments'
  7
+mate.sub '/base', -> require './base'
  8
+mate.sub '/posts', -> require './posts'
  9
+mate.sub '/comments', -> require './comments'
14 10
 
15 11
 # redirect root
16 12
 mate.get '/', -> @redirect '/base'
17  
-  
  13
+
18 14
 # start the engines
19  
-mate.listen 3000
  15
+mate.listen 3000
6  examples/sandbox/posts/index.coffee
... ...
@@ -1,5 +1,3 @@
1  
-mate = require('../../../lib/coffeemate').newInstance()
  1
+mate = require '../../../lib/coffeemate'
2 2
 
3  
-mate.get '/', -> @view 'list'
4  
-
5  
-module.exports = mate
  3
+mate.get '/', -> @render 'posts/index'
2  examples/sandbox/server.js
... ...
@@ -0,0 +1,2 @@
  1
+require('coffee-script');
  2
+module.exports = require('./index.coffee');
8  examples/sandbox/settings.coffee
... ...
@@ -0,0 +1,8 @@
  1
+mate = require '../../lib/coffeemate'
  2
+
  3
+mate.options.renderDir = 'templates'
  4
+mate.options.renderExt = '.html'
  5
+
  6
+# use some of connect middlewares
  7
+mate.logger()
  8
+mate.static("#{__dirname}/public")
2  examples/sandbox/base/views/home.eco → examples/sandbox/templates/base/index.html
... ...
@@ -1,2 +1,2 @@
1 1
 <h1>Coffeemate Sandbox</h1>
2  
-<a href="/posts">posts</a>
  2
+<a href="/posts">posts</a>
18  examples/sandbox/templates/comment_layout.html
... ...
@@ -0,0 +1,18 @@
  1
+<html>
  2
+  <head>
  3
+    <style type="text/css">
  4
+      body {
  5
+        background-color: #ff0;
  6
+      }
  7
+    </style>
  8
+  </head>
  9
+  <body>
  10
+    <div id="header"><img src="coffeescript.png" alt="coffeescript" /></div>
  11
+    <hr />
  12
+    <div id="content">
  13
+      <%- @include @body %>
  14
+    </div>
  15
+    <hr />
  16
+    <div id="footer"><a href="/" title="home">home</a></div>
  17
+  </body>
  18
+</html>
1  examples/sandbox/templates/comments/index.html
... ...
@@ -0,0 +1 @@
  1
+<h1>Comment List</h1>
13  examples/sandbox/templates/layout.html
... ...
@@ -0,0 +1,13 @@
  1
+<html>
  2
+  <head>
  3
+  </head>
  4
+  <body>
  5
+    <div id="header"><img src="coffeescript.png" alt="coffeescript" /></div>
  6
+    <hr />
  7
+    <div id="content">
  8
+      <%- @include @body %>
  9
+    </div>
  10
+    <hr />
  11
+    <div id="footer"><a href="/" title="home">home</a></div>
  12
+  </body>
  13
+</html>
0  examples/sandbox/posts/views/list.eco → examples/sandbox/templates/posts/index.html
File renamed without changes
7  examples/simple_auth/layout.eco
... ...
@@ -0,0 +1,7 @@
  1
+<html>
  2
+  <head>
  3
+  </head>
  4
+  <body>
  5
+      <%- @include @body %>
  6
+  </body>
  7
+</html>
2  examples/templating/app.coffee
@@ -2,6 +2,6 @@ mate = require '../../lib/coffeemate'
2 2
 
3 3
 mate.get '/:page?', ->
4 4
   @foo = 'bar'        # this is a context variable
5  
-  @render 'main.eco'
  5
+  @render 'main'
6 6
 
7 7
 mate.listen 3000
7  examples/templating/layout.eco
... ...
@@ -0,0 +1,7 @@
  1
+<html>
  2
+  <head>
  3
+  </head>
  4
+  <body>
  5
+      <%- @include @body %>
  6
+  </body>
  7
+</html>
2  examples/templating/main.eco
... ...
@@ -1,3 +1,3 @@
1 1
 <h1>this is main template for path: <%= @req.url %></h1>
2 2
 <div>This is foo: <%= @foo %></div>
3  
-<div><%- @include 'nested.eco' %></div>
  3
+<div><%- @include 'nested' %></div>
2  examples/templating/nested.eco
... ...
@@ -1,3 +1,3 @@
1 1
 <h2>this is nested template</h2>
2 2
 <div>This is foo: <%= @foo %></div>
3  
-<div><%- @include 'leaf.eco' %></div>
  3
+<div><%- @include 'leaf' %></div>
4  examples/websockets/app.coffee
... ...
@@ -1,7 +1,9 @@
1 1
 mate = require '../../lib/coffeemate.coffee'
2 2
 
  3
+mate.options.renderLayout = no
  4
+
3 5
 mate.get '/', ->
4  
-  @render 'main.eco'
  6
+  @render 'main'
5 7
 
6 8
 mate.io.sockets.on 'connection', (socket, i=0) ->
7 9
   setInterval (-> socket.emit 'news', "Breaking news #{i++}"), 500
63  lib/coffeemate.coffee
@@ -9,6 +9,7 @@ fs        = require 'fs'
9 9
 path      = require 'path'
10 10
 connect   = require 'connect'
11 11
 eco       = require 'eco'
  12
+util      = require 'util'
12 13
 
13 14
 # Context object that instantiated in every request to
14 15
 # form router handlers' and templates'  @/this reference
@@ -28,7 +29,7 @@ class CoffeemateContext
28 29
   redirect: (location) ->
29 30
     @resp.writeHead 301, location: location
30 31
     @resp.end()
31  
-
  32
+      
32 33
   # This method renders the template that read from given templateName
33 34
   # using eco template engine as default.
34 35
   # It uses sync file read operation to obtain template contents
@@ -41,14 +42,23 @@ class CoffeemateContext
41 42
       @container.options.renderDir,
42 43
       "#{templateName}#{@container.options.renderExt}"
43 44
     template = fs.readFileSync templatePath
44  
-    @container.options.renderFunc "#{template}", @
  45
+    content = @container.options.renderFunc "#{template}", @
45 46
 
46 47
   # This method renders the template that read from given templateName
47 48
   # and writes the output to the client socket stream
48 49
   #
  50
+  # You can explicitly set 'layoutName' if want to override the default 
  51
+  # 'renderLayoutName' option value
  52
+  #
49 53
   # @param {String} templateName
50  
-  # @api public  
51  
-  render: (templateName) ->
  54
+  # @param {String} layoutName
  55
+  # @api public
  56
+  render: (templateName, layoutName) ->
  57
+    if @container.options.renderLayout
  58
+      layoutName ?= @container.options.renderLayoutName
  59
+      @[@container.options.renderLayoutPlaceholder] = templateName
  60
+      @resp.end @include layoutName
  61
+      return
52 62
     @resp.end @include templateName
53 63
 
54 64
 # Coffeemate core object
@@ -70,13 +80,33 @@ class Coffeemate extends connect.HTTPServer
70 80
   #
71 81
   # @api public
72 82
   constructor: ->
73  
-    @options = renderFunc: eco.render, renderDir: '', renderExt: ''
74  
-    @routes = []
  83
+    @options =
  84
+      renderFunc: eco.render,
  85
+      renderDir: '',
  86
+      renderExt: '.eco',
  87
+      renderLayout: yes,
  88
+      renderLayoutName: 'layout',
  89
+      renderLayoutPlaceholder: 'body'
  90
+    @routeMap = {}
  91
+    @baseUrl = '/'
75 92
     connect.HTTPServer.call @, []
76 93
     
77 94
     # enable socket.io if available
78 95
     try @io = require('socket.io').listen @
79  
-      
  96
+  
  97
+  # This method helps you define sub applications under given base path.
  98
+  # The context of callback is coffeemate instance itself and any router definition
  99
+  # in this context will be constructed based on the baseUrl
  100
+  #
  101
+  # @param {String} baseUrl
  102
+  # @param {String} callback
  103
+  # @api public
  104
+  sub: (baseUrl, callback) ->
  105
+    previousBaseUrl = @baseUrl
  106
+    @baseUrl = baseUrl
  107
+    callback.call @
  108
+    @baseUrl = previousBaseUrl
  109
+    module
80 110
 
81 111
   # Factory method for creating new Coffeemate instances
82 112
   # 
@@ -96,27 +126,27 @@ class Coffeemate extends connect.HTTPServer
96 126
     arg.buildRouter() for arg in args when arg instanceof Coffeemate
97 127
     connect.HTTPServer::use.apply @, args
98 128
   
99  
-  # sugarize coffeekup!
  129
+  # Enable special coffeekup templating magic!
100 130
   #
101 131
   # @api public
102 132
   coffeekup: (locals) ->
103 133
     renderFunc = require('coffeekup').render
104  
-    
105 134
     locals ?= {}
106 135
     locals.include ?= (partialName) ->
107 136
       text ck_options.context.include partialName    
108  
-    
109 137
     @options.renderFunc = (tmpl, ctx) -> renderFunc tmpl, context: ctx, locals: locals
110 138
 
111 139
   # Build connect router middleware from internal route stack and automatically use it.
112 140
   # 
113 141
   # @api private
114 142
   buildRouter: ->
115  
-    @use @middleware.router (app) =>
116  
-      for route in @routes
117  
-        do (route) =>
118  
-          app[route.method] route.pattern, (req, resp) =>
119  
-            route.callback.apply new CoffeemateContext(@, req, resp)
  143
+    self = @
  144
+    for root, routes of @routeMap
  145
+      @use root, @middleware.router (app) ->
  146
+        for route in routes
  147
+          do (route) ->
  148
+            app[route.method] route.pattern, (req, resp) ->
  149
+              route.callback.apply new CoffeemateContext(self, req, resp)
120 150
 
121 151
   # Override 'connect.HTTPServer.listen' to create a pre-hook space for
122 152
   # preparing router definitions
@@ -139,7 +169,8 @@ for item of Coffeemate::middleware
139 169
 for method in Coffeemate::middleware.router.methods
140 170
   do (method) ->
141 171
     Coffeemate::[method] = (pattern, callback) ->
142  
-      @routes.push method: method, pattern: pattern, callback: callback
  172
+      @routeMap[@baseUrl] ?= []
  173
+      @routeMap[@baseUrl].push method: method, pattern: pattern, callback: callback
143 174
       @
144 175
 
145 176
 # Handle uncaught exceptions explicitly to prevent node exiting
2  package.json
... ...
@@ -1,5 +1,5 @@
1 1
 { "readme": "http://github.com/coffeemate/coffeematel#readme"
2  
-, "version": "0.3.0"
  2
+, "version": "0.4.0"
3 3
 , "description": "the coffee creamer!"
4 4
 , "main": "lib/coffeemate.coffee"
5 5
 , "author": "Kadir Pekel <kadirpekel@gmail.com>"

0 notes on commit 2db3c3e

Please sign in to comment.
Something went wrong with that request. Please try again.