Comparar commits
113 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 82891ea148 | |||
| cd1aa92d07 | |||
| 2a4f3525d9 | |||
| 944f99abe0 | |||
| e083321a9d | |||
| a0a1a543e8 | |||
| cf74bc655d | |||
| 0587278cda | |||
| b333dccc2e | |||
| a71201bd55 | |||
| cec677062b | |||
| 327d5b0f88 | |||
| 20cf8f81a2 | |||
| 4d5a1b5f4d | |||
| 9d5a6f9412 | |||
| 7e92012415 | |||
| 6ee83ba8d0 | |||
| 70a99ade67 | |||
| 634503b8ba | |||
| 2a4cbb1174 | |||
| ca7d0f3e34 | |||
| 9cb2645d1c | |||
| acf0a652b7 | |||
| 2701dfd80b | |||
| 047499dcd1 | |||
| fa37e5a35f | |||
| 4adbb4971f | |||
| 8ed99f6bb8 | |||
| fbf547d127 | |||
| f4b4c03cb5 | |||
| 6b9a079bbf | |||
| 7238afbf4b | |||
| 0186659469 | |||
| 50d14230f5 | |||
| 29fe71c8f7 | |||
| 5fe033cef1 | |||
| 6490f0c193 | |||
| 09ccd043f2 | |||
| 825e8b6f0c | |||
| 1726dfb3b3 | |||
| 8a7ac0a6af | |||
| d66ce086d4 | |||
| 2bbf6cb8f9 | |||
| 4a52e641cf | |||
| b4c90def81 | |||
| 50c0277e7f | |||
| 5a5f23fc88 | |||
| ae8f9e1137 | |||
| 2b92e4053b | |||
| 8717e2e970 | |||
| d0a9b0cb81 | |||
| 844eb5f7e9 | |||
| 41913fd8b9 | |||
| 2a5ccd8826 | |||
| 497402311f | |||
| d52090619b | |||
| 9d0d6e412b | |||
| 9b5605a944 | |||
| 51f4c965b5 | |||
| 046bee8844 | |||
| 971739089a | |||
| f962f34e53 | |||
| 34a88d029d | |||
| d3b2e6057d | |||
| 12a58361b4 | |||
| 0085b0a33b | |||
| bf9505a4ce | |||
| 4c94457380 | |||
| af313e5e8c | |||
| eb7b96efe1 | |||
| 5fe35bf97e | |||
| 12bc374ea9 | |||
| 68c57e08ae | |||
| f73c3fc404 | |||
| 4d926d3840 | |||
| 817ff41b0d | |||
| f1614a5946 | |||
| 17c1207d76 | |||
| a92667fdad | |||
| f03694e21e | |||
| 83fcf8b594 | |||
| 7afb895f1b | |||
| 98e566ad69 | |||
| 7d0470d285 | |||
| f8879ac5d1 | |||
| 9f263e357b | |||
| ae33e7b673 | |||
| b766234b93 | |||
| a2899a0acd | |||
| 43da20a6b3 | |||
| 25cf42250a | |||
| 6b6ec3f19f | |||
| 1a2e4342e2 | |||
| 1ce1abf216 | |||
| 704c933927 | |||
| 8207e7088f | |||
| 46fdf10c97 | |||
| 61b82480b0 | |||
| 4ce5c7650e | |||
| 965cbf63be | |||
| d4d76cda58 | |||
| f2d08aa2e3 | |||
| a82b1b9270 | |||
| c1617508c6 | |||
| e125ae2c48 | |||
| 3f9cbbbffb | |||
| 6f7141a266 | |||
| 99e3130f3c | |||
| 774f96fcb9 | |||
| 17ab8e81aa | |||
| b02b384f14 | |||
| 3ec970bb67 | |||
| 22e338fbd4 |
@@ -7,3 +7,6 @@
|
||||
[submodule "lib/support/js-oo"]
|
||||
path = lib/support/js-oo
|
||||
url = git://github.com/visionmedia/js-oo.git
|
||||
[submodule "lib/support/sass"]
|
||||
path = lib/support/sass
|
||||
url = git://github.com/visionmedia/sass.js.git
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
|
||||
0.1.0 / 2010-02-03
|
||||
==================
|
||||
|
||||
* Changed; Hooks (before / after) pass request as arg as well as evaluated in their context
|
||||
* Updated node support to 0.1.27 Closes #169
|
||||
* Updated dirname(__filename) -> __dirname
|
||||
* Updated libxmljs support to v0.2.0
|
||||
* Added session support with memory store / reaping
|
||||
* Added quick uid() helper
|
||||
* Added multi-part upload support
|
||||
* Added Sass.js support / submodule
|
||||
* Added production env caching view contents and static files
|
||||
* Added static file caching. Closes #136
|
||||
* Added cache plugin with memory stores
|
||||
* Added support to StaticFile so that it works with non-textual files.
|
||||
* Removed dirname() helper
|
||||
* Removed several globals (now their modules must be required)
|
||||
|
||||
0.0.2 / 2010-01-10
|
||||
==================
|
||||
|
||||
|
||||
+9
-2
@@ -1,6 +1,8 @@
|
||||
|
||||
NODE = node
|
||||
|
||||
all: test
|
||||
|
||||
init:
|
||||
@git submodule init && git submodule update
|
||||
|
||||
@@ -13,8 +15,13 @@ test-independant: init
|
||||
test-dependant: init spec/support/libxmljs/libxmljs.node
|
||||
@$(NODE) spec/node.js dependant
|
||||
|
||||
app:
|
||||
@$(NODE) examples/app.js
|
||||
app: app-chat
|
||||
|
||||
app-chat:
|
||||
@$(NODE) examples/chat/app.js
|
||||
|
||||
app-upload:
|
||||
@$(NODE) examples/upload/app.js
|
||||
|
||||
benchmark:
|
||||
@$(NODE) benchmarks/collection.js
|
||||
|
||||
+7
-6
@@ -11,6 +11,7 @@
|
||||
|
||||
* Sexy DSL with robust sinatra-like routing
|
||||
* High performance
|
||||
* Session support
|
||||
* Mime helpers
|
||||
* Redirection helpers
|
||||
* Nested parameter parsing
|
||||
@@ -21,7 +22,7 @@
|
||||
* Light-weight JavaScript class implementation via js-oo
|
||||
* Collections and chainable iterators
|
||||
* ElementCollections / markup parsing via libxmljs and css selector traversal support via css2xpath
|
||||
* View support (ejs, haml, mustache)
|
||||
* View support (ejs, haml, sass, etc)
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -49,16 +50,15 @@ Or with the [gh](http://github.com/visionmedia/gh) utility:
|
||||
|
||||
## Examples
|
||||
|
||||
require.paths.unshift('lib')
|
||||
Below is a minimal app example when express is already within your load path.
|
||||
|
||||
require('express')
|
||||
require('express/plugins')
|
||||
|
||||
configure(function(){
|
||||
use(MethodOverride)
|
||||
use(ContentLength)
|
||||
use(Redirect)
|
||||
set('root', dirname(__filename))
|
||||
enable('cache views')
|
||||
set('root', __dirname)
|
||||
})
|
||||
|
||||
get('/hello', function(){
|
||||
@@ -104,7 +104,7 @@ Run individual suites:
|
||||
...
|
||||
|
||||
Express is currently being developed with node --version:
|
||||
v0.1.24-13-ge2abc5f
|
||||
v0.1.27
|
||||
|
||||
## More Information
|
||||
|
||||
@@ -117,6 +117,7 @@ Express is currently being developed with node --version:
|
||||
* TJ Holowaychuk (visionmedia) <tj@vision-media.ca>
|
||||
* Ciaran Jessup (ciaranj) <ciaranj@gmail.com>
|
||||
* Gareth Jones (csausdev) <gareth.jones@sensis.com.au>
|
||||
* Aaron Heckmann (aheckmann) <aaron.heckmann+github@gmail.com>
|
||||
|
||||
## License
|
||||
|
||||
|
||||
+29
-8
@@ -8,20 +8,37 @@ require('express')
|
||||
print = puts
|
||||
|
||||
engine = {
|
||||
ejs: require('support/ejs/ejs'),
|
||||
haml: require('support/haml/lib/haml')
|
||||
ejs: require('ejs'),
|
||||
haml: require('haml'),
|
||||
sass: require('sass')
|
||||
}
|
||||
|
||||
options = { locals: { article: { title: 'Foo', body: 'bar' }}}
|
||||
|
||||
ejs = ' \n\
|
||||
<h1><%= article.title %></h1> \n\
|
||||
<p><%= article.body %></p> \n\
|
||||
ejs = ' \n\
|
||||
<div id="primary"> \n\
|
||||
<div class="block first"> \n\
|
||||
<h1><%= article.title %></h1> \n\
|
||||
<p><%= article.body %></p> \n\
|
||||
</div> \n\
|
||||
</div> \n\
|
||||
'
|
||||
|
||||
haml = ' \n\
|
||||
%h1= article.title\n\
|
||||
%p= article.body \n\
|
||||
haml = ' \n\
|
||||
#primary \n\
|
||||
.block.first \n\
|
||||
%h1= article.title \n\
|
||||
%p= article.body \n\
|
||||
'
|
||||
|
||||
sass = ' \n\
|
||||
red: #ff0000 \n\
|
||||
body \n\
|
||||
ul \n\
|
||||
li \n\
|
||||
a \n\
|
||||
:color !red \n\
|
||||
:list-style none \n\
|
||||
'
|
||||
|
||||
suite('Template Engines', 1000, function(){
|
||||
@@ -32,4 +49,8 @@ suite('Template Engines', 1000, function(){
|
||||
benchmark('haml', function(){
|
||||
engine.haml.render(haml, options)
|
||||
})
|
||||
|
||||
benchmark('sass', function(){
|
||||
engine.sass.render(sass)
|
||||
})
|
||||
})
|
||||
@@ -4,15 +4,20 @@ require('express')
|
||||
require('express/plugins')
|
||||
|
||||
configure(function(){
|
||||
var fiveMinutes = 300000,
|
||||
oneMinute = 60000
|
||||
use(MethodOverride)
|
||||
use(ContentLength)
|
||||
use(CommonLogger)
|
||||
set('root', dirname(__filename))
|
||||
enable('cache views')
|
||||
use(Cookie)
|
||||
use(Session, { lifetime: fiveMinutes, reapInterval: oneMinute })
|
||||
set('root', __dirname)
|
||||
enable('cache static files')
|
||||
//enable('cache view contents')
|
||||
})
|
||||
|
||||
var messages = [],
|
||||
StaticFile = require('express/static').File
|
||||
utils = require('express/utils')
|
||||
|
||||
get('/', function(){
|
||||
this.redirect('/chat')
|
||||
@@ -21,13 +26,20 @@ get('/', function(){
|
||||
get('/chat', function(){
|
||||
this.render('chat.haml.html', {
|
||||
locals: {
|
||||
messages: messages
|
||||
title: 'Chat',
|
||||
messages: messages,
|
||||
name: this.session.name,
|
||||
usersOnline: Session.store.length()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
post('/chat', function(){
|
||||
messages.push(escape(this.param('message')).replace(/:\)/g, '<img src="http://icons3.iconfinder.netdna-cdn.com/data/icons/ledicons/emoticon_smile.png">'))
|
||||
this.session.name = this.param('name')
|
||||
messages
|
||||
.push(utils.escape(this.param('name')) + ': ' + utils.escape(this.param('message'))
|
||||
.replace(/(http:\/\/[^\s]+)/g, '<a href="$1" target="express-chat">$1</a>')
|
||||
.replace(/:\)/g, '<img src="http://icons3.iconfinder.netdna-cdn.com/data/icons/ledicons/emoticon_smile.png">'))
|
||||
this.halt(200)
|
||||
})
|
||||
|
||||
@@ -44,7 +56,11 @@ get('/chat/messages', function(){
|
||||
})
|
||||
|
||||
get('/public/*', function(file){
|
||||
this.sendfile(dirname(__filename) + '/public/' + file)
|
||||
this.sendfile(__dirname + '/public/' + file)
|
||||
})
|
||||
|
||||
get('/*.css', function(file){
|
||||
this.render(file + '.sass.css', { layout: false })
|
||||
})
|
||||
|
||||
get('/error/view', function(){
|
||||
@@ -59,4 +75,8 @@ get('/simple', function(){
|
||||
return 'Hello :)'
|
||||
})
|
||||
|
||||
get('/favicon.ico', function(){
|
||||
this.halt()
|
||||
})
|
||||
|
||||
run()
|
||||
|
Antes Largura: | Altura: | Tamanho: 5.2 KiB Depois Largura: | Altura: | Tamanho: 5.2 KiB |
@@ -5,7 +5,7 @@ $(function(){
|
||||
var message = $('input[name=message]'),
|
||||
name = $('input[name=name]')
|
||||
if (message.val())
|
||||
$.post('/chat', { message: $.trim(name.val()) + ': ' + message.val() }, function(){
|
||||
$.post('/chat', { name: name.val(), message: message.val() }, function(){
|
||||
message.val('')
|
||||
})
|
||||
else
|
||||
@@ -5,6 +5,6 @@
|
||||
%li= msg
|
||||
%form{ method: 'post' }
|
||||
%input{ type: 'hidden', name: '_method', value: 'put' }
|
||||
%input{ type: 'text', name: 'name', value: 'guest' }
|
||||
%input{ type: 'text', name: 'name', value: name || 'guest' }
|
||||
%input{ type: 'text', name: 'message' }
|
||||
%input{ type: 'submit', value: 'Send' }
|
||||
@@ -0,0 +1,11 @@
|
||||
%html
|
||||
%head
|
||||
%title= title
|
||||
%script{ src: '/public/javascripts/jquery.js' }
|
||||
%script{ src: '/public/javascripts/app.js' }
|
||||
%link{ rel: 'stylesheet', href: '/style.css' }
|
||||
%body
|
||||
#wrapper= body
|
||||
#online
|
||||
Online:
|
||||
%strong= usersOnline
|
||||
@@ -0,0 +1,81 @@
|
||||
body
|
||||
:font-family "Helvetica Neue", "Lucida Grande", "Arial"
|
||||
:font-size 13px
|
||||
:text-align center
|
||||
=text-stroke 1px rgba(255, 255, 255, 0.1)
|
||||
:color #555
|
||||
|
||||
h1, h2
|
||||
:margin 0
|
||||
:font-size 22px
|
||||
:color #343434
|
||||
h1
|
||||
:text-shadow 1px 2px 2px #ddd
|
||||
:font-size 60px
|
||||
|
||||
img.bubble
|
||||
:position absolute
|
||||
:top -25px
|
||||
:left 120px
|
||||
|
||||
#wrapper
|
||||
:position relative
|
||||
:margin 100px auto
|
||||
:width 500px
|
||||
:text-align left
|
||||
|
||||
ul
|
||||
:margin 0
|
||||
:padding 0
|
||||
:max-height 300px
|
||||
:overflow-x hidden
|
||||
li
|
||||
:margin 5px 0
|
||||
:padding 3px 8px
|
||||
:list-style none
|
||||
:border 1px solid #eee
|
||||
=border-radius 3px
|
||||
=border-radius 3px
|
||||
li:hover
|
||||
:cursor pointer
|
||||
:color #2E2E2E
|
||||
|
||||
input[type=text]
|
||||
:padding 5px
|
||||
:border 1px solid #ddd
|
||||
:outline none
|
||||
=border-radius 2px
|
||||
input[type=text]:focus
|
||||
:border-color #00C3FF
|
||||
|
||||
input[type=submit]
|
||||
=border-radius 2px
|
||||
=box-shadow 0 1px 2px #ddd
|
||||
:padding 6px 10px
|
||||
:border solid 1px #999
|
||||
:background -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ddd))
|
||||
:color #333
|
||||
:text-decoration none
|
||||
:cursor pointer
|
||||
:display inline-block
|
||||
:text-align center
|
||||
:text-shadow 0px 1px 1px #fff
|
||||
:line-height 1
|
||||
input[type=submit]:hover
|
||||
:background -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#E6E4E4))
|
||||
input[type=submit]:active
|
||||
:background -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#c7c7c7))
|
||||
input[name=name]
|
||||
:width 80px
|
||||
|
||||
a
|
||||
:color #1ABFF1
|
||||
=transition-property padding
|
||||
=transition-duration 0.15s
|
||||
a:hover
|
||||
:padding 0 5px
|
||||
a:hover:before
|
||||
:content 'visit: '
|
||||
|
||||
#online
|
||||
:font-size 12px
|
||||
@@ -1,84 +0,0 @@
|
||||
body {
|
||||
font-family: "Helvetica Neue", "Lucida Grande", "Arial";
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
-webkit-text-stroke: 1px rgba(255, 255, 255, 0.1);
|
||||
color: #555;
|
||||
}
|
||||
h1, h2 {
|
||||
margin: 0;
|
||||
font-size: 22px;
|
||||
color: #343434;
|
||||
}
|
||||
h1 {
|
||||
text-shadow: 1px 2px 2px #ddd;
|
||||
font-size: 60px;
|
||||
}
|
||||
img.bubble {
|
||||
position: absolute;
|
||||
top: -25px;
|
||||
left: 120px;
|
||||
}
|
||||
#wrapper {
|
||||
position: relative;
|
||||
margin: 100px auto;
|
||||
width: 500px;
|
||||
text-align: left;
|
||||
}
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
ul li {
|
||||
margin: 5px 0;
|
||||
padding: 3px 8px;
|
||||
list-style: none;
|
||||
border: 1px solid #eee;
|
||||
-webkit-border-radius: 3px;
|
||||
-mox-border-radius: 3px;
|
||||
-webkit-transition-property: color;
|
||||
-webkit-transition-duration: 0.1s;
|
||||
}
|
||||
ul li:hover {
|
||||
cursor: pointer;
|
||||
color: #2E2E2E;
|
||||
}
|
||||
ul {
|
||||
max-height: 300px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
input[type=text] {
|
||||
padding: 5px;
|
||||
border: 1px solid #ddd;
|
||||
outline: none;
|
||||
-webkit-border-radius: 2px;
|
||||
-moz-border-radius: 2px;
|
||||
}
|
||||
input[type=text]:focus {
|
||||
border-color: #00C3FF;
|
||||
}
|
||||
input[type=submit] {
|
||||
-webkit-border-radius: 2px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-box-shadow: 0 1px 2px #ddd;
|
||||
-moz-box-shadow: 0 1px 2px #ddd;
|
||||
padding: 6px 10px;
|
||||
border: solid 1px #999;
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ddd));
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
text-shadow: 0px 1px 1px #fff;
|
||||
line-height: 1;
|
||||
}
|
||||
input[type=submit]:hover {
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#E6E4E4));
|
||||
}
|
||||
input[type=submit]:active {
|
||||
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#c7c7c7));
|
||||
}
|
||||
input[name=name] {
|
||||
width: 80px;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
require.paths.unshift('lib')
|
||||
require('express')
|
||||
require('express/plugins')
|
||||
|
||||
configure(function(){
|
||||
use(MethodOverride)
|
||||
use(ContentLength)
|
||||
use(CommonLogger)
|
||||
set('root', __dirname)
|
||||
enable('cache view contents')
|
||||
})
|
||||
|
||||
get('/', function(){
|
||||
this.redirect('/upload')
|
||||
})
|
||||
|
||||
get('/upload', function(){
|
||||
this.render('upload.haml.html')
|
||||
})
|
||||
|
||||
post('/upload', function(){
|
||||
$(this.param('images')).each(function(image){
|
||||
puts('uploaded ' + image.filename + ' to ' + image.tempfile)
|
||||
})
|
||||
this.redirect('/upload')
|
||||
})
|
||||
|
||||
get('/public/*', function(file){
|
||||
this.sendfile(__dirname + '/public/' + file)
|
||||
})
|
||||
|
||||
get('/*.css', function(file){
|
||||
this.render(file + '.sass.css', { layout: false })
|
||||
})
|
||||
|
||||
run()
|
||||
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -1,8 +1,8 @@
|
||||
%html
|
||||
%head
|
||||
%title Chat
|
||||
%title Upload
|
||||
%script{ src: '/public/javascripts/jquery.js' }
|
||||
%script{ src: '/public/javascripts/app.js' }
|
||||
%link{ rel: 'stylesheet', href: '/public/stylesheets/style.css' }
|
||||
%link{ rel: 'stylesheet', href: '/style.css' }
|
||||
%body
|
||||
#wrapper= body
|
||||
@@ -0,0 +1,66 @@
|
||||
body
|
||||
:font-family "Helvetica Neue", "Lucida Grande", "Arial"
|
||||
:font-size 13px
|
||||
:text-align center
|
||||
:-webkit-text-stroke 1px rgba(255, 255, 255, 0.1)
|
||||
:color #555
|
||||
|
||||
h1, h2
|
||||
:margin 0 0 15px 0
|
||||
:font-size 22px
|
||||
:color #343434
|
||||
h1
|
||||
:text-shadow 1px 2px 2px #ddd
|
||||
:font-size 60px
|
||||
|
||||
#wrapper
|
||||
:position relative
|
||||
:margin 100px auto
|
||||
:width 500px
|
||||
:text-align left
|
||||
|
||||
input[type=file]
|
||||
:padding 5px
|
||||
:border 1px solid #ddd
|
||||
:outline none
|
||||
:-webkit-border-radius 2px
|
||||
:-moz-border-radius 2px
|
||||
input[type=file]:focus
|
||||
:border-color #00C3FF
|
||||
|
||||
input[type=submit]
|
||||
:-webkit-border-radius 2px
|
||||
:-moz-border-radius 2px
|
||||
:-webkit-box-shadow 0 1px 2px #ddd
|
||||
:-moz-box-shadow 0 1px 2px #ddd
|
||||
:padding 6px 10px
|
||||
:border solid 1px #999
|
||||
:background -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ddd))
|
||||
:color #333
|
||||
:text-decoration none
|
||||
:cursor pointer
|
||||
:display inline-block
|
||||
:text-align center
|
||||
:text-shadow 0px 1px 1px #fff
|
||||
:line-height 1
|
||||
input[type=submit]:hover
|
||||
:background -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#E6E4E4))
|
||||
input[type=submit]:active
|
||||
:background -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#c7c7c7))
|
||||
input[name=name]
|
||||
:width 80px
|
||||
|
||||
form
|
||||
.panel
|
||||
:float left
|
||||
:width 100%
|
||||
:clear both
|
||||
|
||||
a
|
||||
:color #1ABFF1
|
||||
:-webkit-transition-property padding
|
||||
:-webkit-transition-duration 0.15s
|
||||
a:hover
|
||||
:padding 0 5px
|
||||
a:hover:before
|
||||
:content 'visit: '
|
||||
@@ -0,0 +1,11 @@
|
||||
%h1 Upload
|
||||
:if typeof images !== 'undefined'
|
||||
.images
|
||||
:each img in images
|
||||
%img{ src: img }
|
||||
%form{ method: 'post', enctype: 'multipart/form-data' }
|
||||
%input{ type: 'file', name: 'images[0]' }
|
||||
%input{ type: 'file', name: 'images[1]' }
|
||||
%input{ type: 'file', name: 'images[2]' }
|
||||
.panel
|
||||
%input{ type: 'submit', value: 'Upload' }
|
||||
+7
-2
@@ -1,3 +1,8 @@
|
||||
|
||||
require('support/js-oo/lib/oo')
|
||||
require('express/core')
|
||||
var path = require('path')
|
||||
require.paths.unshift(__dirname + '/support/js-oo/lib')
|
||||
require.paths.unshift(__dirname + '/support/ejs/lib')
|
||||
require.paths.unshift(__dirname + '/support/haml/lib')
|
||||
require.paths.unshift(__dirname + '/support/sass/lib')
|
||||
require('oo')
|
||||
require('express/core')
|
||||
@@ -29,8 +29,7 @@ function callback(fn) {
|
||||
if (fn === undefined) return
|
||||
if (fn instanceof Function) return fn
|
||||
if (fn.length < 4) return Function('a, b, c', 'return a ' + fn + ' b')
|
||||
if (property.test(fn) ||
|
||||
method.test(fn)) fn = 'a.' + fn
|
||||
if (property.test(fn) || method.test(fn)) fn = 'a.' + fn
|
||||
return Function('a, b, c', 'return ' + fn)
|
||||
}
|
||||
|
||||
|
||||
+61
-7
@@ -6,11 +6,17 @@ process.mixin(require('express/exceptions'))
|
||||
process.mixin(require('express/collection'))
|
||||
process.mixin(require('express/event'))
|
||||
process.mixin(require('express/request'))
|
||||
process.mixin(require('express/helpers'))
|
||||
process.mixin(require('express/plugin'))
|
||||
process.mixin(require('express/mime'))
|
||||
process.mixin(require('express/dsl'))
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var multipart = require('multipart'),
|
||||
File = require('file').File,
|
||||
utils = require('express/utils')
|
||||
|
||||
// --- Route
|
||||
|
||||
Route = Class({
|
||||
@@ -77,7 +83,7 @@ Route = Class({
|
||||
var self = this
|
||||
this.keys = []
|
||||
if (path instanceof RegExp) return path
|
||||
return new RegExp('^' + escapeRegexp(normalizePath(path), '.')
|
||||
return new RegExp('^' + utils.escapeRegexp(normalizePath(path), '.')
|
||||
.replace(/\*/g, '(.+)')
|
||||
.replace(/(\/|\\\.):(\w+)\?/g, function(_, c, key){
|
||||
self.keys.push(key)
|
||||
@@ -213,9 +219,51 @@ Server = Class({
|
||||
require('http')
|
||||
.createServer(function(request, response){
|
||||
request.body = ''
|
||||
request.setBodyEncoding('utf8')
|
||||
request.addListener('body', function(chunk){ request.body += chunk })
|
||||
request.addListener('complete', function(){ self.route(request, response) })
|
||||
request.setBodyEncoding('binary')
|
||||
if (request.headers['content-type'] &&
|
||||
request.headers['content-type'].indexOf('multipart/form-data') !== -1) {
|
||||
var stream = new multipart.Stream(request),
|
||||
promise = new process.Promise,
|
||||
pendingFiles = 0
|
||||
request.params = { post: {}}
|
||||
promise.timeout(set('upload timeout') || 5000)
|
||||
stream.addListener('part', function(part){
|
||||
if (part.filename) {
|
||||
var file = new File(part.tempfile = '/tmp/express-' + Number(new Date) + utils.uid(), 'w')
|
||||
++pendingFiles
|
||||
part.pos = 0
|
||||
part.addListener('body', function(chunk){
|
||||
file.write(chunk, part.pos, 'binary').addErrback(function(){
|
||||
promise.emitError.apply(promise, arguments)
|
||||
})
|
||||
part.pos += chunk.length
|
||||
})
|
||||
.addListener('complete', function(){
|
||||
file.close().addCallback(function(){
|
||||
if (!--pendingFiles)
|
||||
promise.emitSuccess()
|
||||
}).addErrback(function(){
|
||||
promise.emitError.apply(promise, arguments)
|
||||
})
|
||||
utils.mergeParam(part.name, part, request.params.post)
|
||||
})
|
||||
}
|
||||
else
|
||||
part.buf = '',
|
||||
part
|
||||
.addListener('body', function(chunk){ part.buf += chunk })
|
||||
.addListener('complete', function(){
|
||||
if (part.buf.length)
|
||||
utils.mergeParam(part.name, part.buf, request.params.post)
|
||||
})
|
||||
}).addListener('complete', function(){
|
||||
promise.addCallback(function(){ self.route(request, response) })
|
||||
})
|
||||
}
|
||||
else
|
||||
request
|
||||
.addListener('body', function(chunk){ request.body += chunk })
|
||||
.addListener('complete', function(){ self.route(request, response) })
|
||||
})
|
||||
.listen(this.port, this.host, this.backlog)
|
||||
puts('Express started at http://' + this.host + ':' + this.port + '/ in ' + Express.environment + ' mode')
|
||||
@@ -252,7 +300,7 @@ Server = Class({
|
||||
// --- Express
|
||||
|
||||
Express = {
|
||||
version: '0.0.2',
|
||||
version: '0.1.0',
|
||||
config: [],
|
||||
routes: [],
|
||||
plugins: [],
|
||||
@@ -264,6 +312,7 @@ Express = {
|
||||
|
||||
configure(function(){
|
||||
use(require('express/plugins/view').View)
|
||||
use(require('express/plugins/cache').Cache)
|
||||
use(require('express/plugins/redirect').Redirect)
|
||||
use(require('express/plugins/body-decoder').BodyDecoder)
|
||||
})
|
||||
@@ -276,3 +325,8 @@ configure('development', function(){
|
||||
configure('test', function(){
|
||||
enable('throw exceptions')
|
||||
})
|
||||
|
||||
configure('production', function(){
|
||||
enable('cache view contents')
|
||||
enable('cache static files')
|
||||
})
|
||||
|
||||
@@ -103,7 +103,7 @@ exports.configure = function(environment, fn) {
|
||||
if (fn instanceof Function)
|
||||
return Express.config.push([environment, fn])
|
||||
if (typeof environment != 'string')
|
||||
throw 'environment require'
|
||||
throw new Error('environment required')
|
||||
for (var i = 0, len = Express.config.length; i < len; ++i)
|
||||
if (Express.config[i][0] == environment ||
|
||||
Express.config[i][0] == 'all')
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Express - ElementCollection - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
|
||||
|
||||
/**
|
||||
* Load libxml support.
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var libxml = require('libxmljs')
|
||||
@@ -126,7 +126,7 @@ ElementCollection = Collection.extend({
|
||||
*/
|
||||
|
||||
prev: function() {
|
||||
return $([this.at(0).prev_sibling()])
|
||||
return $([this.at(0).prevSibling()])
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -137,7 +137,7 @@ ElementCollection = Collection.extend({
|
||||
*/
|
||||
|
||||
next: function() {
|
||||
return $([this.at(0).next_sibling()])
|
||||
return $([this.at(0).nextSibling()])
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
+182
-9
@@ -1,136 +1,278 @@
|
||||
|
||||
// Express - Mime - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
|
||||
|
||||
var types = {
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var utils = require('express/utils')
|
||||
|
||||
/**
|
||||
* Mime type lookup table.
|
||||
*/
|
||||
|
||||
exports.types = {
|
||||
'323' : 'text/h323',
|
||||
'3gp' : 'video/3gpp',
|
||||
'a' : 'application/octet-stream',
|
||||
'acx' : 'application/internet-property-stream',
|
||||
'ai' : 'application/postscript',
|
||||
'aif' : 'audio/x-aiff',
|
||||
'aifc' : 'audio/x-aiff',
|
||||
'aiff' : 'audio/x-aiff',
|
||||
'asc' : 'application/pgp-signature',
|
||||
'asf' : 'video/x-ms-asf',
|
||||
'asr' : 'video/x-ms-asf',
|
||||
'asm' : 'text/x-asm',
|
||||
'asx' : 'video/x-ms-asf',
|
||||
'atom' : 'application/atom+xml',
|
||||
'au' : 'audio/basic',
|
||||
'avi' : 'video/x-msvideo',
|
||||
'axs' : 'application/olescript',
|
||||
'bas' : 'text/plain',
|
||||
'bat' : 'application/x-msdownload',
|
||||
'bcpio' : 'application/x-bcpio',
|
||||
'bin' : 'application/octet-stream',
|
||||
'bmp' : 'image/bmp',
|
||||
'bz2' : 'application/x-bzip2',
|
||||
'c' : 'text/x-c',
|
||||
'cab' : 'application/vnd.ms-cab-compressed',
|
||||
'cat' : 'application/vnd.ms-pkiseccat',
|
||||
'cc' : 'text/x-c',
|
||||
'cdf' : 'application/x-netcdf',
|
||||
'cer' : 'application/x-x509-ca-cert',
|
||||
'cgm' : 'image/cgm',
|
||||
'chm' : 'application/vnd.ms-htmlhelp',
|
||||
'class' : 'application/octet-stream',
|
||||
'clp' : 'application/x-msclip',
|
||||
'cmx' : 'image/x-cmx',
|
||||
'cod' : 'image/cis-cod',
|
||||
'com' : 'application/x-msdownload',
|
||||
'conf' : 'text/plain',
|
||||
'cpio' : 'application/x-cpio',
|
||||
'cpp' : 'text/x-c',
|
||||
'cpt' : 'application/mac-compactpro',
|
||||
'crd' : 'application/x-mscardfile',
|
||||
'crl' : 'application/pkix-crl',
|
||||
'crt' : 'application/x-x509-ca-cert',
|
||||
'csh' : 'application/x-csh',
|
||||
'css' : 'text/css',
|
||||
'csv' : 'text/csv',
|
||||
'cxx' : 'text/x-c',
|
||||
'dcr' : 'application/x-director',
|
||||
'deb' : 'application/x-debian-package',
|
||||
'der' : 'application/x-x509-ca-cert',
|
||||
'diff' : 'text/x-diff',
|
||||
'dir' : 'application/x-director',
|
||||
'djv' : 'image/vnd.djvu',
|
||||
'djvu' : 'image/vnd.djvu',
|
||||
'dll' : 'application/x-msdownload',
|
||||
'dmg' : 'application/octet-stream',
|
||||
'dms' : 'application/octet-stream',
|
||||
'doc' : 'application/msword',
|
||||
'dot' : 'application/msword',
|
||||
'dtd' : 'application/xml-dtd',
|
||||
'dv' : 'video/x-dv',
|
||||
'dvi' : 'application/x-dvi',
|
||||
'dxr' : 'application/x-director',
|
||||
'ear' : 'application/java-archive',
|
||||
'eml' : 'message/rfc822',
|
||||
'eps' : 'application/postscript',
|
||||
'etx' : 'text/x-setext',
|
||||
'evy' : 'application/envoy',
|
||||
'exe' : 'application/x-msdownload',
|
||||
'ez' : 'application/andrew-inset',
|
||||
'f' : 'text/x-fortran',
|
||||
'f77' : 'text/x-fortran',
|
||||
'f90' : 'text/x-fortran',
|
||||
'fif' : 'application/fractals',
|
||||
'flr' : 'x-world/x-vrml',
|
||||
'flv' : 'video/x-flv',
|
||||
'for' : 'text/x-fortran',
|
||||
'gem' : 'application/octet-stream',
|
||||
'gemspec' : 'text/x-script.ruby',
|
||||
'gif' : 'image/gif',
|
||||
'gram' : 'application/srgs',
|
||||
'grxml' : 'application/srgs+xml',
|
||||
'gtar' : 'application/x-gtar',
|
||||
'gz' : 'application/x-gzip',
|
||||
'h' : 'text/x-c',
|
||||
'hdf' : 'application/x-hdf',
|
||||
'hh' : 'text/x-c',
|
||||
'hlp' : 'application/winhlp',
|
||||
'hqx' : 'application/mac-binhex40',
|
||||
'hta' : 'application/hta',
|
||||
'htc' : 'text/x-component',
|
||||
'htm' : 'text/html',
|
||||
'html' : 'text/html',
|
||||
'htt' : 'text/webviewhtml',
|
||||
'ice' : 'x-conference/x-cooltalk',
|
||||
'ico' : 'image/vnd.microsoft.icon',
|
||||
'ics' : 'text/calendar',
|
||||
'ief' : 'image/ief',
|
||||
'ifb' : 'text/calendar',
|
||||
'iges' : 'model/iges',
|
||||
'igs' : 'model/iges',
|
||||
'iii' : 'application/x-iphone',
|
||||
'ins' : 'application/x-internet-signup',
|
||||
'isp' : 'application/x-internet-signup',
|
||||
'iso' : 'application/octet-stream',
|
||||
'jar' : 'application/java-archive',
|
||||
'java' : 'text/x-java-source',
|
||||
'jfif' : 'image/pipeg',
|
||||
'jnlp' : 'application/x-java-jnlp-file',
|
||||
'jp2' : 'image/jp2',
|
||||
'jpe' : 'image/jpeg',
|
||||
'jpeg' : 'image/jpeg',
|
||||
'jpg' : 'image/jpeg',
|
||||
'js' : 'application/javascript',
|
||||
'json' : 'application/json',
|
||||
'kar' : 'audio/midi',
|
||||
'latex' : 'application/x-latex',
|
||||
'lha' : 'application/octet-stream',
|
||||
'lsf' : 'video/x-la-asf',
|
||||
'lsx' : 'video/x-la-asf',
|
||||
'lzh' : 'application/octet-stream',
|
||||
'log' : 'text/plain',
|
||||
'm13' : 'application/x-msmediaview',
|
||||
'm14' : 'application/x-msmediaview',
|
||||
'm3u' : 'audio/x-mpegurl',
|
||||
'm4a' : 'audio/mp4a-latm',
|
||||
'm4b' : 'audio/mp4a-latm',
|
||||
'm4p' : 'audio/mp4a-latm',
|
||||
'm4u' : 'video/vnd.mpegurl',
|
||||
'm4v' : 'video/mp4',
|
||||
'mac' : 'image/x-macpaint',
|
||||
'man' : 'text/troff',
|
||||
'mathml' : 'application/mathml+xml',
|
||||
'mbox' : 'application/mbox',
|
||||
'mdb' : 'application/x-msaccess',
|
||||
'mdoc' : 'text/troff',
|
||||
'me' : 'text/troff',
|
||||
'mesh' : 'model/mesh',
|
||||
'mht' : 'message/rfc822',
|
||||
'mhtml' : 'message/rfc822',
|
||||
'mid' : 'audio/midi',
|
||||
'midi' : 'audio/midi',
|
||||
'mif' : 'application/vnd.mif',
|
||||
'mime' : 'message/rfc822',
|
||||
'mml' : 'application/mathml+xml',
|
||||
'mng' : 'video/x-mng',
|
||||
'mny' : 'application/x-msmoney',
|
||||
'mov' : 'video/quicktime',
|
||||
'movie' : 'video/x-sgi-movie',
|
||||
'mp2' : 'video/mpeg',
|
||||
'mp3' : 'audio/mpeg',
|
||||
'mp4' : 'video/mp4',
|
||||
'mp4v' : 'video/mp4',
|
||||
'mpa' : 'video/mpeg',
|
||||
'mpe' : 'video/mpeg',
|
||||
'mpeg' : 'video/mpeg',
|
||||
'mpg' : 'video/mpeg',
|
||||
'mpga' : 'audio/mpeg',
|
||||
'mpp' : 'application/vnd.ms-project',
|
||||
'mpv2' : 'video/mpeg',
|
||||
'ms' : 'text/troff',
|
||||
'msh' : 'model/mesh',
|
||||
'msi' : 'application/x-msdownload',
|
||||
'mvb' : 'application/x-msmediaview',
|
||||
'mxu' : 'video/vnd.mpegurl',
|
||||
'nc' : 'application/x-netcdf',
|
||||
'nws' : 'message/rfc822',
|
||||
'oda' : 'application/oda',
|
||||
'odp' : 'application/vnd.oasis.opendocument.presentation',
|
||||
'ods' : 'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'odt' : 'application/vnd.oasis.opendocument.text',
|
||||
'ogg' : 'application/ogg',
|
||||
'p' : 'text/x-pascal',
|
||||
'p10' : 'application/pkcs10',
|
||||
'p12' : 'application/x-pkcs12',
|
||||
'p7b' : 'application/x-pkcs7-certificates',
|
||||
'p7c' : 'application/x-pkcs7-mime',
|
||||
'p7m' : 'application/x-pkcs7-mime',
|
||||
'p7r' : 'application/x-pkcs7-certreqresp',
|
||||
'p7s' : 'application/x-pkcs7-signature',
|
||||
'pas' : 'text/x-pascal',
|
||||
'pbm' : 'image/x-portable-bitmap',
|
||||
'pct' : 'image/pict',
|
||||
'pdb' : 'chemical/x-pdb',
|
||||
'pdf' : 'application/pdf',
|
||||
'pem' : 'application/x-x509-ca-cert',
|
||||
'pfx' : 'application/x-pkcs12',
|
||||
'pgm' : 'image/x-portable-graymap',
|
||||
'pgn' : 'application/x-chess-pgn',
|
||||
'pgp' : 'application/pgp-encrypted',
|
||||
'pic' : 'image/pict',
|
||||
'pict' : 'image/pict',
|
||||
'pkg' : 'application/octet-stream',
|
||||
'pko' : 'application/ynd.ms-pkipko',
|
||||
'pl' : 'text/x-script.perl',
|
||||
'pm' : 'text/x-script.perl-module',
|
||||
'pma' : 'application/x-perfmon',
|
||||
'pmc' : 'application/x-perfmon',
|
||||
'pml' : 'application/x-perfmon',
|
||||
'pmr' : 'application/x-perfmon',
|
||||
'pmw' : 'application/x-perfmon',
|
||||
'png' : 'image/png',
|
||||
'pnm' : 'image/x-portable-anymap',
|
||||
'pnt' : 'image/x-macpaint',
|
||||
'pntg' : 'image/x-macpaint',
|
||||
'pot' : 'application/vnd.ms-powerpoint',
|
||||
'ppm' : 'image/x-portable-pixmap',
|
||||
'pps' : 'application/vnd.ms-powerpoint',
|
||||
'ppt' : 'application/vnd.ms-powerpoint',
|
||||
'prf' : 'application/pics-rules',
|
||||
'ps' : 'application/postscript',
|
||||
'psd' : 'image/vnd.adobe.photoshop',
|
||||
'pub' : 'application/x-mspublisher',
|
||||
'py' : 'text/x-script.python',
|
||||
'qt' : 'video/quicktime',
|
||||
'qti' : 'image/x-quicktime',
|
||||
'qtif' : 'image/x-quicktime',
|
||||
'ra' : 'audio/x-pn-realaudio',
|
||||
'rake' : 'text/x-script.ruby',
|
||||
'ram' : 'audio/x-pn-realaudio',
|
||||
'rar' : 'application/x-rar-compressed',
|
||||
'ras' : 'image/x-cmu-raster',
|
||||
'rb' : 'text/x-script.ruby',
|
||||
'rdf' : 'application/rdf+xml',
|
||||
'rgb' : 'image/x-rgb',
|
||||
'rm' : 'application/vnd.rn-realmedia',
|
||||
'rmi' : 'audio/mid',
|
||||
'roff' : 'text/troff',
|
||||
'rpm' : 'application/x-redhat-package-manager',
|
||||
'rss' : 'application/rss+xml',
|
||||
'rtf' : 'application/rtf',
|
||||
'rtx' : 'text/richtext',
|
||||
'ru' : 'text/x-script.ruby',
|
||||
's' : 'text/x-asm',
|
||||
'scd' : 'application/x-msschedule',
|
||||
'sct' : 'text/scriptlet',
|
||||
'setpay' : 'application/set-payment-initiation',
|
||||
'setreg' : 'application/set-registration-initiation',
|
||||
'sgm' : 'text/sgml',
|
||||
'sgml' : 'text/sgml',
|
||||
'sh' : 'application/x-sh',
|
||||
'shar' : 'application/x-shar',
|
||||
'sig' : 'application/pgp-signature',
|
||||
'silo' : 'model/mesh',
|
||||
'sit' : 'application/x-stuffit',
|
||||
'skd' : 'application/x-koan',
|
||||
'skm' : 'application/x-koan',
|
||||
'skp' : 'application/x-koan',
|
||||
'skt' : 'application/x-koan',
|
||||
'smi' : 'application/smil',
|
||||
'smil' : 'application/smil',
|
||||
'snd' : 'audio/basic',
|
||||
'so' : 'application/octet-stream',
|
||||
'spc' : 'application/x-pkcs7-certificates',
|
||||
'spl' : 'application/x-futuresplash',
|
||||
'src' : 'application/x-wais-source',
|
||||
'sst' : 'application/vnd.ms-pkicertstore',
|
||||
'stl' : 'application/vnd.ms-pkistl',
|
||||
'stm' : 'text/html',
|
||||
'sv4cpio' : 'application/x-sv4cpio',
|
||||
'sv4crc' : 'application/x-sv4crc',
|
||||
'svg' : 'image/svg+xml',
|
||||
'svgz' : 'image/svg+xml',
|
||||
'swf' : 'application/x-shockwave-flash',
|
||||
@@ -142,30 +284,60 @@ var types = {
|
||||
'texi' : 'application/x-texinfo',
|
||||
'texinfo' : 'application/x-texinfo',
|
||||
'text' : 'text/plain',
|
||||
'tgz' : 'application/x-compressed',
|
||||
'tif' : 'image/tiff',
|
||||
'tiff' : 'image/tiff',
|
||||
'torrent' : 'application/x-bittorrent',
|
||||
'tr' : 'text/troff',
|
||||
'trm' : 'application/x-msterminal',
|
||||
'tsv' : 'text/tab-seperated-values',
|
||||
'txt' : 'text/plain',
|
||||
'uls' : 'text/iuls',
|
||||
'ustar' : 'application/x-ustar',
|
||||
'vcd' : 'application/x-cdlink',
|
||||
'vcf' : 'text/x-vcard',
|
||||
'vcs' : 'text/x-vcalendar',
|
||||
'vrml' : 'model/vrml',
|
||||
'vxml' : 'application/voicexml+xml',
|
||||
'war' : 'application/java-archive',
|
||||
'wav' : 'audio/x-wav',
|
||||
'wbmp' : 'image/vnd.wap.wbmp',
|
||||
'wbxml' : 'application/vnd.wap.wbxml',
|
||||
'wcm' : 'application/vnd.ms-works',
|
||||
'wdb' : 'application/vnd.ms-works',
|
||||
'wks' : 'application/vnd.ms-works',
|
||||
'wma' : 'audio/x-ms-wma',
|
||||
'wmf' : 'application/x-msmetafile',
|
||||
'wml' : 'text/vnd.wap.wml',
|
||||
'wmls' : 'text/vnd.wap.wmlscript',
|
||||
'wmlsc' : 'application/vnd.wap.wmlscriptc',
|
||||
'wmv' : 'video/x-ms-wmv',
|
||||
'wmx' : 'video/x-ms-wmx',
|
||||
'wps' : 'application/vnd.ms-works',
|
||||
'wri' : 'application/x-mswrite',
|
||||
'wrl' : 'model/vrml',
|
||||
'wrz' : 'x-world/x-vrml',
|
||||
'wsdl' : 'application/wsdl+xml',
|
||||
'xaf' : 'x-world/x-vrml',
|
||||
'xbm' : 'image/x-xbitmap',
|
||||
'xht' : 'application/xhtml+xml',
|
||||
'xhtml' : 'application/xhtml+xml',
|
||||
'xla' : 'application/vnd.ms-excel',
|
||||
'xlc' : 'application/vnd.ms-excel',
|
||||
'xlm' : 'application/vnd.ms-excel',
|
||||
'xls' : 'application/vnd.ms-excel',
|
||||
'xlt' : 'application/vnd.ms-excel',
|
||||
'xml' : 'application/xml',
|
||||
'xof' : 'x-world/x-vrml',
|
||||
'xpm' : 'image/x-xpixmap',
|
||||
'xsl' : 'application/xml',
|
||||
'xslt' : 'application/xslt+xml',
|
||||
'xul' : 'application/vnd.mozilla.xul+xml',
|
||||
'xwd' : 'image/x-xwindowdump',
|
||||
'xyz' : 'chemical/x-xyz',
|
||||
'yaml' : 'text/yaml',
|
||||
'yml' : 'text/yaml',
|
||||
'z' : 'application/x-compress',
|
||||
'zip' : 'application/zip'
|
||||
}
|
||||
|
||||
@@ -178,10 +350,11 @@ var types = {
|
||||
* however this can be altered using the 'default mime type'
|
||||
* setting.
|
||||
*
|
||||
* mime('png') // => 'image/png'
|
||||
* mime('.png') // => 'image/png'
|
||||
* mime('image.png') // => 'image/png'
|
||||
* mime('path/to/image.png') // => 'image/png'
|
||||
* var mime = require('express/mime')
|
||||
* mime.type('png') // => 'image/png'
|
||||
* mime.type('.png') // => 'image/png'
|
||||
* mime.type('image.png') // => 'image/png'
|
||||
* mime.type('path/to/image.png') // => 'image/png'
|
||||
*
|
||||
* @param {string} path
|
||||
* @return {string}
|
||||
@@ -189,9 +362,9 @@ var types = {
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.mime = function(path) {
|
||||
return types[path] ||
|
||||
types[extname(path)] ||
|
||||
exports.type = function(path) {
|
||||
return exports.types[path] ||
|
||||
exports.types[utils.extname(path)] ||
|
||||
set('default mime type') ||
|
||||
'application/octet-stream'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
exports.use = function(plugin, options) {
|
||||
if ('init' in plugin) plugin.init()
|
||||
if ('init' in plugin) plugin.init(options)
|
||||
Express.plugins.push({
|
||||
klass: plugin,
|
||||
options: options
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
process.mixin(require('express/plugins/hooks'))
|
||||
process.mixin(require('express/plugins/cookie'))
|
||||
process.mixin(require('express/plugins/session'))
|
||||
process.mixin(require('express/plugins/profiler'))
|
||||
process.mixin(require('express/plugins/common-logger'))
|
||||
process.mixin(require('express/plugins/content-length'))
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
|
||||
// Express - Cache - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
|
||||
|
||||
// --- Store
|
||||
|
||||
exports.Store = Class({
|
||||
|
||||
/**
|
||||
* Ensure that the given _key_ is a string.
|
||||
* Override in subclass to provide data-store specific functionality.
|
||||
*
|
||||
* @param {string} key
|
||||
* @param {string} val
|
||||
* @api public
|
||||
*/
|
||||
|
||||
set: function(key, val) {
|
||||
if (typeof key !== 'string') throw new Error(this.name + ' store #set() key must be a string')
|
||||
},
|
||||
|
||||
/**
|
||||
* Ensure that the given _key_ is a string.
|
||||
* Override in subclass to provide data-store specific functionality.
|
||||
*
|
||||
* @param {string} key
|
||||
* @api public
|
||||
*/
|
||||
|
||||
get: function(key) {
|
||||
if (typeof key !== 'string') throw new Error(this.name + 'store #get() key must be a string')
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert to '[NAME Store]'.
|
||||
*
|
||||
* @return {string}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
toString: function() {
|
||||
return '[' + this.name + ' Store]'
|
||||
}
|
||||
})
|
||||
|
||||
// --- Store.Memory
|
||||
|
||||
exports.Store.Memory = exports.Store.extend({
|
||||
|
||||
/**
|
||||
* Datastore name.
|
||||
*/
|
||||
|
||||
name: 'Memory',
|
||||
|
||||
/**
|
||||
* Initialize data.
|
||||
*/
|
||||
|
||||
init: function() {
|
||||
this.data = {}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the given _key_ to _val_, returning _val_.
|
||||
*
|
||||
* @param {string} key
|
||||
* @param {string} val
|
||||
* @return {string}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
set: function(key, val) {
|
||||
this.__super__(key, val)
|
||||
return this.data[key] = val
|
||||
},
|
||||
|
||||
/**
|
||||
* Get data found matching the given _key_.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* cache.get('page:front')
|
||||
* // => '<html>...</html>'
|
||||
*
|
||||
* cache.get('page:*')
|
||||
* // => { 'page:front': '<html>...</html>',
|
||||
* 'page:users': '<html>...</html>',
|
||||
* ... }
|
||||
*
|
||||
* @param {string} key
|
||||
* @return {mixed}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
get: function(key) {
|
||||
this.__super__(key)
|
||||
if (key.indexOf('*') === -1)
|
||||
return this.data[key]
|
||||
var vals = {},
|
||||
regexp = this.normalize(key)
|
||||
for (var key in this.data)
|
||||
if (this.data.hasOwnProperty(key))
|
||||
if (regexp.test(key))
|
||||
vals[key] = this.data[key]
|
||||
return vals
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear data matching the given _key_.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* cache.clear('page:front')
|
||||
* cache.clear('page:*')
|
||||
*
|
||||
* @param {string} key
|
||||
* @api public
|
||||
*/
|
||||
|
||||
clear: function(key) {
|
||||
if (key.indexOf('*') === -1)
|
||||
return delete this.data[key]
|
||||
var regexp = this.normalize(key)
|
||||
for (var key in this.data)
|
||||
if (this.data.hasOwnProperty(key))
|
||||
if (regexp.test(key))
|
||||
delete this.data[key]
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert the given key matching _pattern_
|
||||
* into a RegExp.
|
||||
*
|
||||
* - * is converted to (.*?)
|
||||
*
|
||||
* @param {string} pattern
|
||||
* @return {regexp}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
normalize: function(pattern) {
|
||||
return new RegExp('^' + pattern.replace(/[*]/g, '(.*?)') + '$')
|
||||
}
|
||||
})
|
||||
|
||||
exports.Cache = Plugin.extend({
|
||||
extend: {
|
||||
|
||||
/**
|
||||
* Initialize extensions.
|
||||
*/
|
||||
|
||||
init: function() {
|
||||
Request.include({
|
||||
cache: new exports.Store.Memory
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -56,12 +56,12 @@ exports.Cookie = Plugin.extend({
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - path: Cookie path, defaults to '/'
|
||||
* - domain: Tail matched domain name such as 'vision-media.ca' or 'blog.vision-media.ca' etc
|
||||
* - expires: Date object converted to 'Wdy, DD-Mon-YYYY HH:MM:SS GMT'
|
||||
* - path Cookie path, defaults to '/'
|
||||
* - domain Tail matched domain name such as 'vision-media.ca' or 'blog.vision-media.ca' etc
|
||||
* - expires Date object converted to 'Wdy, DD-Mon-YYYY HH:MM:SS GMT'
|
||||
* when undefined the cookie will last the duration of a the
|
||||
* client's session.
|
||||
* - secure: When true the cookie will be sent by the client only when transfering data via HTTPS
|
||||
* - secure When true the cookie will be sent by the client only when transfering data via HTTPS
|
||||
* - httpOnly When true the cookie will be sent to the server only and will not be accessable via
|
||||
* client-side scripting.
|
||||
*
|
||||
@@ -73,6 +73,8 @@ exports.Cookie = Plugin.extend({
|
||||
*/
|
||||
|
||||
cookie: function(name, val, options) {
|
||||
options = options || {}
|
||||
options.path = options.path || '/'
|
||||
return val ?
|
||||
this.response.cookies.push(exports.compileCookie(name, val, options)) :
|
||||
this.cookies[name]
|
||||
@@ -86,13 +88,14 @@ exports.Cookie = Plugin.extend({
|
||||
on: {
|
||||
|
||||
/**
|
||||
* Parser request cookie data.
|
||||
* Parse request cookie data.
|
||||
*/
|
||||
|
||||
request: function(event) {
|
||||
event.request.response.cookies = []
|
||||
if (event.request.headers.cookie)
|
||||
event.request.cookies = exports.parseCookie(event.request.headers.cookie)
|
||||
event.request.cookies = event.request.headers.cookie ?
|
||||
exports.parseCookie(event.request.headers.cookie) :
|
||||
{}
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -50,7 +50,7 @@ exports.Hooks = Plugin.extend({
|
||||
|
||||
request: function(event) {
|
||||
$(before).each(function(fn){
|
||||
fn.call(event.request)
|
||||
fn.call(event.request, event.request)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -60,7 +60,7 @@ exports.Hooks = Plugin.extend({
|
||||
|
||||
response: function(event) {
|
||||
$(after).each(function(fn){
|
||||
fn.call(event.request)
|
||||
fn.call(event.request, event.request)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
|
||||
// Express - Session - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var utils = require('express/utils')
|
||||
|
||||
// --- Session
|
||||
|
||||
var Session = Class({
|
||||
|
||||
/**
|
||||
* Initialize session _sid_.
|
||||
*/
|
||||
|
||||
init: function(sid) {
|
||||
this.id = sid
|
||||
this.touch()
|
||||
},
|
||||
|
||||
/**
|
||||
* Update last access time.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
touch: function() {
|
||||
this.lastAccess = Number(new Date)
|
||||
}
|
||||
})
|
||||
|
||||
// --- MemoryStore
|
||||
|
||||
exports.MemoryStore = Class({
|
||||
|
||||
/**
|
||||
* Initialize in-memory session store.
|
||||
*/
|
||||
|
||||
init: function() {
|
||||
this.store = {}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch session with the given _sid_ or
|
||||
* a new Session is returned.
|
||||
*
|
||||
* @param {int} sid
|
||||
* @return {Session}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
fetch: function(sid) {
|
||||
return this.store[sid] || new Session(sid)
|
||||
},
|
||||
|
||||
/**
|
||||
* Commit _session_ data.
|
||||
*
|
||||
* @param {Session} session
|
||||
* @api private
|
||||
*/
|
||||
|
||||
commit: function(session) {
|
||||
return this.store[session.id] = session
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear all sessions.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
clear: function() {
|
||||
this.store = {}
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy session using the given _sid_.
|
||||
*
|
||||
* @param {int} sid
|
||||
* @api public
|
||||
*/
|
||||
|
||||
destroy: function(sid) {
|
||||
delete this.store[sid]
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the number of sessions currently stored.
|
||||
*
|
||||
* @return {int}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
length: function() {
|
||||
return $(this.store).length()
|
||||
},
|
||||
|
||||
/**
|
||||
* Reap sessions older than _ms_.
|
||||
*
|
||||
* @param {int} ms
|
||||
* @api private
|
||||
*/
|
||||
|
||||
reap: function(ms) {
|
||||
var self = this,
|
||||
threshold = Number(new Date(Number(new Date) - ms))
|
||||
$(this.store).each(function(session, sid){
|
||||
if (session.lastAccess < threshold)
|
||||
self.destroy(sid)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
exports.Session = Plugin.extend({
|
||||
extend: {
|
||||
|
||||
/**
|
||||
* Initialize memory store and start reaper.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - dataStore constructor name of session data store, defaults to MemoryStore
|
||||
* - lifetime lifetime of session in milliseconds, defaults to one day
|
||||
* - reapInterval interval in milliseconds in which to reap old sessions, defaults to one hour
|
||||
*
|
||||
* @param {hash} options
|
||||
* @api private
|
||||
*/
|
||||
|
||||
init: function(options) {
|
||||
process.mixin(this, options)
|
||||
this.store = new (this.dataStore || exports.MemoryStore)(options)
|
||||
this.startReaper()
|
||||
},
|
||||
|
||||
/**
|
||||
* Start reaper.
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
startReaper: function() {
|
||||
var self = this,
|
||||
oneDay = 86400000,
|
||||
oneHour = 3600000
|
||||
setInterval(function(){
|
||||
self.store.reap(self.lifetime || oneDay)
|
||||
}, self.reapInterval || oneHour)
|
||||
}
|
||||
},
|
||||
|
||||
// --- Events
|
||||
|
||||
on: {
|
||||
|
||||
/**
|
||||
* Create session id when not found; delegate to store.
|
||||
*/
|
||||
|
||||
request: function(event) {
|
||||
var sid
|
||||
if (!(sid = event.request.cookie('sid')))
|
||||
event.request.cookie('sid', sid = utils.uid(), set('session cookie'))
|
||||
event.request.session = exports.Session.store.fetch(sid)
|
||||
event.request.session.touch()
|
||||
},
|
||||
|
||||
/**
|
||||
* Delegate to store, allowing it to save sessions changes.
|
||||
*/
|
||||
|
||||
response: function(event) {
|
||||
exports.Session.store.commit(event.request.session)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1,21 +1,21 @@
|
||||
|
||||
// Express - View - Copyright TJ Holowaychuk <tj@vision-media.ca> (MIT Licensed)
|
||||
|
||||
var posix = require('posix')
|
||||
|
||||
/**
|
||||
* Template content cache.
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var cache = {}
|
||||
var posix = require('posix'),
|
||||
utils = require('express/utils')
|
||||
|
||||
/**
|
||||
* Supported template engines.
|
||||
*/
|
||||
|
||||
var engine = {
|
||||
ejs: require('support/ejs/ejs'),
|
||||
haml: require('support/haml/lib/haml')
|
||||
ejs: require('ejs'),
|
||||
haml: require('haml'),
|
||||
sass: require('sass')
|
||||
}
|
||||
|
||||
// --- View
|
||||
@@ -57,7 +57,7 @@ exports.View = Plugin.extend({
|
||||
*
|
||||
* @param {string} view
|
||||
* @param {hash} options
|
||||
* @settings 'views', 'cache views'
|
||||
* @settings 'views', 'cache view contents'
|
||||
* @api public
|
||||
*/
|
||||
|
||||
@@ -66,13 +66,13 @@ exports.View = Plugin.extend({
|
||||
options = options || {},
|
||||
path = set('views') + '/' + view,
|
||||
type = path.split('.').slice(-2)[0],
|
||||
ext = extname(path),
|
||||
ext = utils.extname(path),
|
||||
layout = options.layout === undefined ? true : options.layout
|
||||
self.contentType(ext)
|
||||
function render(content) {
|
||||
content = engine[type].render(content, options)
|
||||
if (layout)
|
||||
self.render('layout.' + type + '.' + ext, process.mixin(options, {
|
||||
self.render('layout.' + type + '.' + ext, process.mixin(true, options, {
|
||||
layout: false,
|
||||
locals: {
|
||||
body: content
|
||||
@@ -81,11 +81,13 @@ exports.View = Plugin.extend({
|
||||
else
|
||||
self.halt(200, content)
|
||||
}
|
||||
if (set('cache views') && cache[view])
|
||||
render(cache[view])
|
||||
if (set('cache view contents') && self.cache.get(path))
|
||||
render(self.cache.get(path))
|
||||
else
|
||||
posix.cat(path).addCallback(function(content){
|
||||
render(cache[view] = content)
|
||||
set('cache view contents') ?
|
||||
render(self.cache.set(path, content)) :
|
||||
render(content)
|
||||
}).addErrback(function(e){
|
||||
throw e
|
||||
})
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
var StaticFile = require('express/static').File,
|
||||
statusBodies = require('http').STATUS_CODES,
|
||||
queryString = require('querystring'),
|
||||
mime = require('express/mime'),
|
||||
url = require('url')
|
||||
|
||||
// --- InvalidStatusCode
|
||||
@@ -67,11 +68,10 @@ exports.Request = Class({
|
||||
this.response = response
|
||||
this.url = url.parse(this.url)
|
||||
this.url.pathname = exports.normalizePath(this.url.pathname)
|
||||
this.params = {
|
||||
get: this.url.query ? queryString.parseQuery(this.url.query) : {},
|
||||
post: {},
|
||||
path: {}
|
||||
}
|
||||
this.params = this.params || {}
|
||||
this.params.path = {}
|
||||
this.params.get = this.url.query ? queryString.parseQuery(this.url.query) : {}
|
||||
this.params.post = this.params.post || {}
|
||||
this.plugins = $(Express.plugins).map(function(plugin){
|
||||
return new plugin.klass(plugin.options)
|
||||
})
|
||||
@@ -113,20 +113,19 @@ exports.Request = Class({
|
||||
|
||||
/**
|
||||
* Check if Accept header includes the mime type
|
||||
* for the given _path_, which calls mime().
|
||||
* for the given _path_, which calls mime.type().
|
||||
*
|
||||
* When no Accept header is present true will be
|
||||
* returned as stated in the HTTP specification.
|
||||
*
|
||||
* @param {string} path
|
||||
* @return {bool}
|
||||
* @see mime()
|
||||
* @api public
|
||||
*/
|
||||
|
||||
accepts: function(path) {
|
||||
return this.header('accept') ?
|
||||
this.header('accept').indexOf(mime(path)) !== -1 :
|
||||
this.header('accept').indexOf(mime.type(path)) !== -1 :
|
||||
true
|
||||
},
|
||||
|
||||
@@ -187,16 +186,15 @@ exports.Request = Class({
|
||||
|
||||
/**
|
||||
* Set Content-Type header to the mime type
|
||||
* for the given _path_, which calls mime().
|
||||
* for the given _path_, which calls mime.type().
|
||||
*
|
||||
* @param {string} path
|
||||
* @return {Request}
|
||||
* @see mime()
|
||||
* @api public
|
||||
*/
|
||||
|
||||
contentType: function(path) {
|
||||
this.header('content-type', mime(path))
|
||||
this.header('content-type', mime.type(path))
|
||||
return this
|
||||
},
|
||||
|
||||
|
||||
+10
-3
@@ -35,19 +35,26 @@ exports.File = Class({
|
||||
* - Ensures the file exists
|
||||
* - Ensures the file is a regular file (not FIFO, Socket, etc)
|
||||
* - Automatically assigns content type
|
||||
* - Halts with 404 when failing
|
||||
*
|
||||
* @param {Request} request
|
||||
* @settings 'cache static files'
|
||||
* @api public
|
||||
*/
|
||||
|
||||
send: function(request) {
|
||||
var file = this.path
|
||||
var cache, file = this.path
|
||||
if (set('cache static files') && (cache = request.cache.get(file)))
|
||||
return request.contentType(cache.type),
|
||||
request.halt(200, cache.content, 'binary')
|
||||
path.exists(file, function(exists){
|
||||
if (!exists) request.halt()
|
||||
if (!exists) return request.halt()
|
||||
posix.stat(file).addCallback(function(stats){
|
||||
if (!stats.isFile()) request.halt()
|
||||
if (!stats.isFile()) return request.halt()
|
||||
posix.cat(file, 'binary').addCallback(function(content){
|
||||
request.contentType(file)
|
||||
if (set('cache static files'))
|
||||
request.cache.set(file, { type: file, content: content })
|
||||
request.halt(200, content, 'binary')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -9,15 +9,17 @@ JSON.encode = JSON.stringify
|
||||
JSON.decode = JSON.parse
|
||||
|
||||
/**
|
||||
* Return the directory name of the given _path_.
|
||||
* Return a unique identifier.
|
||||
*
|
||||
* @param {string} path
|
||||
* @return {string}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.dirname = function(path) {
|
||||
return path.split('/').slice(0, -1).join('/')
|
||||
exports.uid = function() {
|
||||
var uid = ''
|
||||
for (var n = 4; n; --n)
|
||||
uid += (Math.abs((Math.random() * 0xFFFFFFF) | 0)).toString(16)
|
||||
return uid
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,4 +94,30 @@ exports.toArray = function(arr, offset) {
|
||||
exports.escapeRegexp = function(string, chars) {
|
||||
var specials = (chars || '/ . * + ? | ( ) [ ] { } \\').split(' ').join('|\\')
|
||||
return string.replace(new RegExp('(\\' + specials + ')', 'g'), '\\$1')
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge param _key_ and _val_ into _params_. Key
|
||||
* should be a query string key such as 'user[name]',
|
||||
* and _val_ is it's associated value. The root _params_
|
||||
* object is returned.
|
||||
*
|
||||
* This is primarily used by Express for merging multi-part
|
||||
* body values together.
|
||||
*
|
||||
* @param {string} key
|
||||
* @param {string} val
|
||||
* @return {hash}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.mergeParam = function(key, val, params) {
|
||||
var keys = key.match(/(\w+)/g),
|
||||
orig = params
|
||||
for (var i = 0, len = keys.length; i < len; ++i)
|
||||
if (i == len - 1)
|
||||
params[keys[i]] = val
|
||||
else
|
||||
params = (params[keys[i]] = params[keys[i]] || {})
|
||||
return orig
|
||||
}
|
||||
+1
-1
Submodule lib/support/haml updated: 53fad8e082...b1fa42226b
Submódulo
+1
Submodule lib/support/sass added at dfc1cd027f
+5
-5
@@ -4,7 +4,7 @@
|
||||
;(function(){
|
||||
|
||||
JSpec = {
|
||||
version : '3.1.0',
|
||||
version : '3.2.1',
|
||||
assert : true,
|
||||
cache : {},
|
||||
suites : [],
|
||||
@@ -1046,7 +1046,7 @@
|
||||
*/
|
||||
|
||||
expect : function(actual) {
|
||||
assert = function(matcher, args, negate) {
|
||||
function assert(matcher, args, negate) {
|
||||
var expected = toArray(args, 1)
|
||||
matcher.negate = negate
|
||||
assertion = new JSpec.Assertion(matcher, actual, expected, negate)
|
||||
@@ -1056,11 +1056,11 @@
|
||||
return assertion.result
|
||||
}
|
||||
|
||||
to = function(matcher) {
|
||||
function to(matcher) {
|
||||
return assert(matcher, arguments, false)
|
||||
}
|
||||
|
||||
not_to = function(matcher) {
|
||||
function not_to(matcher) {
|
||||
return assert(matcher, arguments, true)
|
||||
}
|
||||
|
||||
@@ -1692,7 +1692,7 @@
|
||||
case Number:
|
||||
case RegExp:
|
||||
case Function:
|
||||
state = actual.toString().match(arg.toString())
|
||||
state = actual.toString().indexOf(arg) !== -1
|
||||
break
|
||||
|
||||
case Object:
|
||||
|
||||
+3
-1
@@ -27,12 +27,13 @@ specs = {
|
||||
independant: [
|
||||
'core',
|
||||
'routing',
|
||||
'helpers',
|
||||
'utils',
|
||||
'request',
|
||||
'mime',
|
||||
'static',
|
||||
'collection',
|
||||
'plugins',
|
||||
'plugins.cache',
|
||||
'plugins.view',
|
||||
'plugins.common-logger',
|
||||
'plugins.content-length',
|
||||
@@ -41,6 +42,7 @@ specs = {
|
||||
'plugins.redirect',
|
||||
'plugins.hooks',
|
||||
'plugins.cookie',
|
||||
'plugins.session',
|
||||
],
|
||||
dependant: [
|
||||
'element-collection'
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
|
||||
describe 'Express'
|
||||
describe 'toArray()'
|
||||
describe 'when given an array'
|
||||
it 'should return the array'
|
||||
toArray([1,2,3]).should.eql [1,2,3]
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when given an object with indexed values and length'
|
||||
it 'should return an array'
|
||||
var args = -{ return arguments }('foo', 'bar')
|
||||
toArray(args).should.eql ['foo', 'bar']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'escape()'
|
||||
it 'should escape html'
|
||||
escape('<p>this & that').should.eql '<p>this & that'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'extname()'
|
||||
it 'should return the a files extension'
|
||||
extname('image.png').should.eql 'png'
|
||||
extname('image.large.png').should.eql 'png'
|
||||
extname('/path/to/image.large.png').should.eql 'png'
|
||||
end
|
||||
|
||||
it 'should return null when not found'
|
||||
extname('path').should.be_null
|
||||
extname('/just/a/path').should.be_null
|
||||
end
|
||||
end
|
||||
|
||||
describe 'dirname()'
|
||||
it 'should return the directory path'
|
||||
dirname('/path/to/images/foo.bar.png').should.eql '/path/to/images'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'basename()'
|
||||
it 'should return a files basename'
|
||||
basename('foo/bar/baz.image.png').should.eql 'baz.image.png'
|
||||
end
|
||||
end
|
||||
end
|
||||
+30
-24
@@ -1,36 +1,42 @@
|
||||
|
||||
describe 'Express'
|
||||
before
|
||||
mime = require('express/mime')
|
||||
end
|
||||
|
||||
before_each
|
||||
reset()
|
||||
end
|
||||
|
||||
describe 'mime()'
|
||||
describe 'when given an extension with leading dot'
|
||||
it 'should return the associated mime type'
|
||||
mime('.png').should.eql 'image/png'
|
||||
describe 'mime'
|
||||
describe 'type()'
|
||||
describe 'when given an extension with leading dot'
|
||||
it 'should return the associated mime type'
|
||||
mime.type('.png').should.eql 'image/png'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when given an extension without leading dot'
|
||||
it 'should return the associated mime type'
|
||||
mime('png').should.eql 'image/png'
|
||||
|
||||
describe 'when given an extension without leading dot'
|
||||
it 'should return the associated mime type'
|
||||
mime.type('png').should.eql 'image/png'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when given a file path'
|
||||
it 'should return the associated mime type'
|
||||
mime('/path/to/an/image.png').should.eql 'image/png'
|
||||
|
||||
describe 'when given a file path'
|
||||
it 'should return the associated mime type'
|
||||
mime.type('/path/to/an/image.png').should.eql 'image/png'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when given an unknown extension'
|
||||
it 'should default to the "default mime type" setting'
|
||||
set('default mime type', 'text/plain')
|
||||
mime('meow').should.eql 'text/plain'
|
||||
end
|
||||
|
||||
it 'should default to "application/octet-stream" otherwise'
|
||||
mime('meow').should.eql 'application/octet-stream'
|
||||
|
||||
describe 'when given an unknown extension'
|
||||
it 'should default to the "default mime type" setting'
|
||||
set('default mime type', 'text/plain')
|
||||
mime.type('meow').should.eql 'text/plain'
|
||||
end
|
||||
|
||||
it 'should default to "application/octet-stream" otherwise'
|
||||
mime.type('meow').should.eql 'application/octet-stream'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
|
||||
describe 'Express'
|
||||
before_each
|
||||
reset()
|
||||
use(require('express/plugins/cache').Cache)
|
||||
cache = require('express/plugins/cache')
|
||||
end
|
||||
|
||||
describe 'Cache'
|
||||
describe 'Request'
|
||||
describe '#cache'
|
||||
it 'should use memory store by default'
|
||||
get('/item', function(){
|
||||
return this.cache.toString()
|
||||
})
|
||||
get('/item').body.should.eql '[Memory Store]'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Store'
|
||||
describe 'Memory'
|
||||
before_each
|
||||
store = new cache.Store.Memory
|
||||
end
|
||||
|
||||
describe '#toString()'
|
||||
it 'should return [Memory Store]'
|
||||
store.toString().should.eql '[Memory Store]'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#set()'
|
||||
describe 'given a key and value'
|
||||
it 'should set the cache data'
|
||||
store.set('foo', 'bar')
|
||||
store.get('foo').should.eql 'bar'
|
||||
end
|
||||
|
||||
it 'should override existing data'
|
||||
store.set('foo', 'bar')
|
||||
store.set('foo', 'baz')
|
||||
store.get('foo').should.eql 'baz'
|
||||
end
|
||||
|
||||
it 'should return data'
|
||||
store.set('foo', 'bar').should.eql 'bar'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'given an abitrary key'
|
||||
it 'should throw an error'
|
||||
-{ store.set({}, 'foo') }.should.throw_error
|
||||
end
|
||||
end
|
||||
|
||||
describe 'given an abitrary value'
|
||||
it 'should serialize as JSON'
|
||||
store.set('user', { name: 'tj' }).should.eql { name: 'tj' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get()'
|
||||
describe 'given a key'
|
||||
it 'should return cached value'
|
||||
store.set('foo', 'bar')
|
||||
store.get('foo').should.eql 'bar'
|
||||
end
|
||||
|
||||
it 'should unserialize JSON data'
|
||||
store.set('user', { name: 'tj' })
|
||||
store.get('user').should.eql { name: 'tj' }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'given wildcards'
|
||||
it 'should return a set of caches'
|
||||
store.set('user:1', 'a')
|
||||
store.set('user:2', 'b')
|
||||
store.set('foo', 'bar')
|
||||
store.get('user:*').should.eql { 'user:1': 'a', 'user:2': 'b' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#clear()'
|
||||
describe 'given a key'
|
||||
it 'should delete previous data'
|
||||
store.set('foo', 'bar')
|
||||
store.clear('foo')
|
||||
store.get('foo').should.be_null
|
||||
end
|
||||
end
|
||||
|
||||
describe 'given wildcards'
|
||||
it 'should clear a set of caches'
|
||||
store.set('user:one', '1')
|
||||
store.set('user:two', '2')
|
||||
store.clear('user:*')
|
||||
store.get('user:one').should.be_null
|
||||
store.get('user:two').should.be_null
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -82,7 +82,7 @@ describe 'Express'
|
||||
this.cookie('foo', 'bar')
|
||||
return ''
|
||||
})
|
||||
get('/user').headers['set-cookie'].should.eql 'SID=732423sdfs73243; path=/; secure, foo=bar'
|
||||
get('/user').headers['set-cookie'].should.eql 'SID=732423sdfs73243; path=/; secure, foo=bar; path=/'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
var mime = require('express/mime')
|
||||
|
||||
CSSColors = Plugin.extend({
|
||||
extend: {
|
||||
init: function() {
|
||||
@@ -7,7 +9,7 @@ CSSColors = Plugin.extend({
|
||||
},
|
||||
on: {
|
||||
response: function(event) {
|
||||
if (event.response.headers['content-type'] == mime('css'))
|
||||
if (event.response.headers['content-type'] == mime.type('css'))
|
||||
event.response.body = event.response.body.replace('black', '#000')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
|
||||
describe 'Express'
|
||||
before_each
|
||||
reset()
|
||||
use(require('express/plugins/cookie').Cookie)
|
||||
use(Session = require('express/plugins/session').Session)
|
||||
Session.store.clear()
|
||||
end
|
||||
|
||||
describe 'Session'
|
||||
describe 'when sid cookie is not present'
|
||||
it 'should set sid cookie'
|
||||
get('/login', function(){ return '' })
|
||||
get('/login').headers['set-cookie'].should.match(/^sid=(\w+);/)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when sid cookie is present'
|
||||
it 'should not set sid'
|
||||
get('/login', function(){ return '' })
|
||||
get('/login', { headers: { cookie: 'sid=123' }}).headers.should.not.have_property 'set-cookie'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'MemoryStore'
|
||||
before_each
|
||||
memory = new (require('express/plugins/session').MemoryStore)
|
||||
end
|
||||
|
||||
it 'should persist'
|
||||
post('/login', function(){
|
||||
return this.session.name = 'tj'
|
||||
})
|
||||
get('/login', function(){
|
||||
return this.session.name
|
||||
})
|
||||
var headers = { headers: { cookie: 'sid=123' }}
|
||||
post('/login', headers)
|
||||
get('/login', headers).status.should.eql 200
|
||||
get('/login', headers).body.should.eql 'tj'
|
||||
end
|
||||
|
||||
describe '#fetch()'
|
||||
describe 'when the session does not exist'
|
||||
it 'should return a new Session'
|
||||
memory.fetch('1').should.have_property 'lastAccess'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when the session does exist'
|
||||
it 'should return the previous session'
|
||||
memory.commit({ id: '1', same: true })
|
||||
memory.fetch('1').should.have_property 'same', true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#clear()'
|
||||
it 'should remove all sessions'
|
||||
memory.commit({ id: '1' })
|
||||
memory.commit({ id: '2' })
|
||||
memory.clear()
|
||||
memory.should.not.have_property '1'
|
||||
memory.should.not.have_property '2'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#length()'
|
||||
it 'should return the number of session'
|
||||
memory.commit({ id: '1' })
|
||||
memory.commit({ id: '2' })
|
||||
memory.length().should.eql 2
|
||||
end
|
||||
end
|
||||
|
||||
describe '#destroy()'
|
||||
it 'should destroy a single session'
|
||||
memory.commit({ id: '1' })
|
||||
memory.commit({ id: '2' })
|
||||
memory.destroy('1')
|
||||
memory.store.should.not.have_property '1'
|
||||
memory.store.should.have_property '2'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#reap()'
|
||||
it 'should destroy sessions older than the given age in milliseconds'
|
||||
memory.commit({ id: '1', lastAccess: Number(new Date) - 300 })
|
||||
memory.commit({ id: '2', lastAccess: Number(new Date) - 250 })
|
||||
memory.commit({ id: '3', lastAccess: Number(new Date) - 100 })
|
||||
memory.commit({ id: '4', lastAccess: Number(new Date) })
|
||||
memory.reap(200)
|
||||
memory.store.should.not.have_property '1'
|
||||
memory.store.should.not.have_property '2'
|
||||
memory.store.should.have_property '3'
|
||||
memory.store.should.have_property '4'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -174,7 +174,7 @@ describe 'Express'
|
||||
|
||||
it 'should work with a query string'
|
||||
get('/user', function(){
|
||||
return this.param('page') || 'First page'
|
||||
return String(this.param('page') || 'First page')
|
||||
})
|
||||
get('/user').body.should.eql 'First page'
|
||||
get('/user?page=2').body.should.eql '2'
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
|
||||
describe 'Express'
|
||||
before
|
||||
utils = require('express/utils')
|
||||
end
|
||||
|
||||
describe 'toArray()'
|
||||
describe 'when given an array'
|
||||
it 'should return the array'
|
||||
utils.toArray([1,2,3]).should.eql [1,2,3]
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when given an object with indexed values and length'
|
||||
it 'should return an array'
|
||||
var args = -{ return arguments }('foo', 'bar')
|
||||
utils.toArray(args).should.eql ['foo', 'bar']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'escape()'
|
||||
it 'should escape html'
|
||||
utils.escape('<p>this & that').should.eql '<p>this & that'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'uid()'
|
||||
it 'should return a string of random characters'
|
||||
utils.uid().should.not.eql utils.uid()
|
||||
utils.uid().length.should.be_greater_than 20
|
||||
end
|
||||
end
|
||||
|
||||
describe 'extname()'
|
||||
it 'should return the a files extension'
|
||||
utils.extname('image.png').should.eql 'png'
|
||||
utils.extname('image.large.png').should.eql 'png'
|
||||
utils.extname('/path/to/image.large.png').should.eql 'png'
|
||||
end
|
||||
|
||||
it 'should return null when not found'
|
||||
utils.extname('path').should.be_null
|
||||
utils.extname('/just/a/path').should.be_null
|
||||
end
|
||||
end
|
||||
|
||||
describe 'basename()'
|
||||
it 'should return a files basename'
|
||||
utils.basename('foo/bar/baz.image.png').should.eql 'baz.image.png'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'mergeParam()'
|
||||
describe 'with empty params'
|
||||
it 'should merge the given key and value'
|
||||
params = {}
|
||||
utils.mergeParam('user[names][first]', 'tj', params)
|
||||
params.user.names.first.should.eql 'tj'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with populated params'
|
||||
it 'should merge not overwrite'
|
||||
params = { user: { name: 'tj' }}
|
||||
utils.mergeParam('user[email]', 'tj@vision-media.ca', params)
|
||||
params.user.name.should.eql 'tj'
|
||||
params.user.email.should.eql 'tj@vision-media.ca'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
+1
-1
Submodule spec/support/libxmljs updated: 584f3aa303...0be1b6f48f
Referência em uma Nova Issue
Bloquear um usuário