commit 9e957d4e2c46a9042e1b4bcf9fcee686e3db5a71 Author: TJ Holowaychuk Date: Tue Jul 31 20:33:12 2012 -0700 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b7fa2e8c --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules +.DS_Store +api.html +index.html diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..52b6eecb --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +expressjs.com diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..834b57c9 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ + +JADE = ./node_modules/.bin/jade + +HTML = index.html \ + api.html \ + guide.html \ + applications.html \ + community.html \ + faq.html + +docs: $(HTML) + +%.html: %.jade + $(JADE) --path $< < $< > $@ + +clean: + rm -f *.html + +.PHONY: docs clean diff --git a/Readme.md b/Readme.md new file mode 100644 index 00000000..625c3a77 --- /dev/null +++ b/Readme.md @@ -0,0 +1,26 @@ + +# ExpressJS.com + + The site for Express. + +## Building + +Setup: + +``` +$ npm install -g serve +$ npm install +$ make +$ serve . & +$ open http://localhost:3000 +``` + +then rebuild changes with: + +``` +$ make +``` + +## Contributing + + - __dont__ edit the HTML directly, edit the _jade_. diff --git a/api.jade b/api.jade new file mode 100644 index 00000000..da407447 --- /dev/null +++ b/api.jade @@ -0,0 +1,33 @@ +!!! 5 +html + head + title Express - api reference + include includes/head + body.inner + .bar + section#content + header + include includes/logo + active = '/api.html' + include includes/menu + + include includes/mixins + + include en/api/menu + + #right + include en/api/express + + h2 Application + a(name='application') + include en/api/app + + h2 Request + a(name='request') + include en/api/req + + h2 Response + a(name='response') + include en/api/res + + include includes/footer diff --git a/app.js b/app.js new file mode 100644 index 00000000..07b06084 --- /dev/null +++ b/app.js @@ -0,0 +1,93 @@ + +o = $; + +// misc junk + +o(function(){ + var width = window.innerWidth; + var height = window.innerHeight; + var doc = o(document); + + // .onload + o('html').addClass('onload'); + + // top link + o('#top').click(function(e){ + o('body').animate({ scrollTop: 0 }, 'fast'); + e.preventDefault(); + }); + + // scrolling links + var added; + doc.scroll(function(e){ + if (doc.scrollTop() > 5) { + if (added) return; + added = true; + o('body').addClass('scroll'); + } else { + o('body').removeClass('scroll'); + added = false; + } + }) + + // highlight code + o('pre.js code').each(function(){ + o(this).html(highlight(o(this).text())); + }) +}) + +// active menu junk + +o(function(){ + var prev; + var n = 0; + + var headings = o('h3').map(function(i, el){ + return { + top: o(el).offset().top, + id: el.id + } + }); + + function closest() { + var h; + var top = o(window).scrollTop(); + var i = headings.length; + while (i--) { + h = headings[i]; + if (top >= h.top) return h; + } + } + + o(document).scroll(function(){ + var h = closest(); + if (!h) return; + + if (prev) { + prev.removeClass('active'); + prev.parent().parent().removeClass('active'); + } + + var a = o('a[href="#' + h.id + '"]'); + a.addClass('active'); + a.parent().parent().addClass('active'); + + prev = a; + }) +}) + +/** + * Highlight the given `js`. + */ + +function highlight(js) { + return js + .replace(//g, '>') + .replace(/\/\/(.*)/gm, '//$1') + .replace(/('.*?')/gm, '$1') + .replace(/(\d+\.\d+)/gm, '$1') + .replace(/(\d+)/gm, '$1') + .replace(/\bnew *(\w+)/gm, 'new $1') + .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1') +} \ No newline at end of file diff --git a/applications.html b/applications.html new file mode 100644 index 00000000..14f46d6a --- /dev/null +++ b/applications.html @@ -0,0 +1,25 @@ +Express - applications

LearnBoost

LearnBoost provides a free, easy to use online +online education suite including gradebook, +lesson plans, attendance, reporting, and calendars +among other tools. +

Storify

Create stories using social media. Turn what people post +on social media into compelling stories. Collect the best photos, video, +tweets and more to publish +

Geekli.st

A place for geeks to share what they've done, who they did it with and +connect with great companies and communities. +

Klout

Klout is the Standard for Influence. Join Klout to discover your +influence and compare with others you may know. +

Prismatic

Prismatic learns from how you interact on social networks so that we +can show you the most interesting content and conversation from your friends. +

Clipboard

Clipboard is a powerful tool allowing to save live clips +of your interests on the web, not just static images, +but fully-functional fragments of anything online. +

Persona

Persona, or "BrowserID" is Mozilla's answer +to a better identification system for your browser, +this promising tool is definitely worth checking out. +

and more!

Shodan search reports that there are well over 26,000 Express applications +in the wild, we can't possibly list them all here, but if you feel +your application helps showcase the framework open an issue on +the github repo. +

\ No newline at end of file diff --git a/applications.jade b/applications.jade new file mode 100644 index 00000000..39e0b853 --- /dev/null +++ b/applications.jade @@ -0,0 +1,14 @@ +!!! 5 +html + head + title Express - applications + include includes/head + body.applications.inner + .bar + section#content + header + include includes/logo + active = '/applications.html' + include includes/menu + include en/applications + include includes/footer diff --git a/community.html b/community.html new file mode 100644 index 00000000..13c1264c --- /dev/null +++ b/community.html @@ -0,0 +1,15 @@ +Express - community

Mailing List

Join over 1500 Express users or browse over 5000 +discussions in the Google Group. +

IRC Channel

Hundreds of developers idle in #express on freenode every day, +if you have questions about the framework jump in for quick +feedback. +

Examples

View dozens of Express application examples +in the github repository covering everything from API design and authentication +to template engine integration. +

Issues

If you've come across what you think is a bug, or just want to make +a feature request open a ticket in the issue queue. +

Third Party

Our vibrant community has created a large variety of extensions, +middleware +and higher level frameworks. Check them out in the +wiki.

\ No newline at end of file diff --git a/community.jade b/community.jade new file mode 100644 index 00000000..701b6212 --- /dev/null +++ b/community.jade @@ -0,0 +1,14 @@ +!!! 5 +html + head + title Express - community + include includes/head + body.community.inner + .bar + section#content + header + include includes/logo + active = '/community.html' + include includes/menu + include en/community + include includes/footer diff --git a/en/api/app-VERB.jade b/en/api/app-VERB.jade new file mode 100644 index 00000000..14edb07b --- /dev/null +++ b/en/api/app-VERB.jade @@ -0,0 +1,59 @@ +section + h3(id='app.VERB') app.VERB(path, [callback...], callback) + + p. + The app.VERB() methods provide the routing functionality + in Express, where VERB is one of the HTTP verbs, such + as app.post(). Multiple callbacks may be give, all are treated + equally, and behave just like middleware, with the one exception that + these callbacks may invoke next('route') to bypass the + remaining route callback(s). This mechanism can be used to perform pre-conditions + on a route then pass control to subsequent routes when there is no reason to proceed + with the route matched. + + p. + The following snippet illustrates the most simple route definition possible. Express + translates the path strings to regular expressions, used internally to match incoming requests. + Query strings are not considered when peforming these matches, for example "GET /" + would match the following route, as would "GET /?name=tobi". + + +js. + app.get('/', function(req, res){ + res.send('hello world'); + }); + + p. + Regular expressions may also be used, and can be useful + if you have very specific restraints, for example the following + would match "GET /commits/71dbb9c" as well as "GET /commits/71dbb9c..4c084f9". + + +js. + app.get(/^\/commits\/(\d+)(?:\.\.(\d+))?$/, function(req, res){ + var from = req.params[0]; + var to = req.params[1] || 'HEAD'; + res.send('commit range ' + from + '..' + to); + }); + + p. + Several callbacks may also be passed, useful for re-using middleware + that load resources, perform validations, etc. + + +js. + app.get('/user/:id', user.load, function(){ + // ... + }) + + p. + These callbacks may be passed within arrays as well, these arrays are + simply flattened when passed: + + +js. + var middleware = [loadForum, loadThread]; + + app.get('/forum/:fid/thread/:tid', middleware, function(){ + // ... + }) + + app.post('/forum/:fid/thread/:tid', middleware, function(){ + // ... + }) diff --git a/en/api/app-all.jade b/en/api/app-all.jade new file mode 100644 index 00000000..600f2f59 --- /dev/null +++ b/en/api/app-all.jade @@ -0,0 +1,34 @@ +section + h3(id='app.all') app.all(path, [callback...], callback) + + p. + This method functions just like the app.VERB() methods, + however it matches all HTTP verbs. + + p. + This method is extremely useful for + mapping "global" logic for specific path prefixes or arbitrary matches. + For example if you placed the following route at the top of all other + route definitions, it would require that all routes from that point on + would require authentication, and automatically load a user. Keep in mind + that these callbacks do not have to act as end points, loadUser + can perform a task, then next() to continue matching subsequent + routes. + + +js. + app.all('*', requireAuthentication, loadUser); + + p. + Or the equivalent: + + +js. + app.all('*', requireAuthentication) + app.all('*', loadUser); + + p. + Another great example of this is white-listed "global" functionality. Here + the example is much like before, however only restricting paths prefixed with + "/api": + + +js. + app.all('/api/*', requireAuthentication); \ No newline at end of file diff --git a/en/api/app-configure.jade b/en/api/app-configure.jade new file mode 100644 index 00000000..22fcdf09 --- /dev/null +++ b/en/api/app-configure.jade @@ -0,0 +1,40 @@ +section + h3(id='app.configure') app.configure([env], callback) + + p. + Conditionally invoke callback when env matches app.get('env'), + aka process.env.NODE_ENV. This method remains for legacy reason, and is effectively + an if statement as illustrated in the following snippets. These functions are not + required in order to use app.set() and other configuration methods. + + +js. + // all environments + app.configure(function(){ + app.set('title', 'My Application'); + }) + + // development only + app.configure('development', function(){ + app.set('db uri', 'localhost/dev'); + }) + + // production only + app.configure('production', function(){ + app.set('db uri', 'n.n.n.n/prod'); + }) + + Is effectively sugar for: + + +js. + // all environments + app.set('title', 'My Application'); + + // development only + if ('development' == app.get('env')) { + app.set('db uri', 'localhost/dev'); + } + + // production only + if ('production' == app.get('env')) { + app.set('db uri', 'n.n.n.n/prod'); + } diff --git a/en/api/app-disable.jade b/en/api/app-disable.jade new file mode 100644 index 00000000..d2bcbc91 --- /dev/null +++ b/en/api/app-disable.jade @@ -0,0 +1,10 @@ +section + h3(id='app.disable') app.disable(name) + + p. + Set setting name to false. + + +js. + app.disable('trust proxy'); + app.get('trust proxy'); + // => false \ No newline at end of file diff --git a/en/api/app-disabled.jade b/en/api/app-disabled.jade new file mode 100644 index 00000000..99653521 --- /dev/null +++ b/en/api/app-disabled.jade @@ -0,0 +1,13 @@ +section + h3(id='app.disabled') app.disabled(name) + + p. + Check if setting name is disabled. + + +js. + app.disabled('trust proxy'); + // => true + + app.enable('trust proxy'); + app.disabled('trust proxy'); + // => false \ No newline at end of file diff --git a/en/api/app-enable.jade b/en/api/app-enable.jade new file mode 100644 index 00000000..ea4cc63e --- /dev/null +++ b/en/api/app-enable.jade @@ -0,0 +1,10 @@ +section + h3(id='app.enable') app.enable(name) + + p. + Set setting name to true. + + +js. + app.enable('trust proxy'); + app.get('trust proxy'); + // => true \ No newline at end of file diff --git a/en/api/app-enabled.jade b/en/api/app-enabled.jade new file mode 100644 index 00000000..25a6c976 --- /dev/null +++ b/en/api/app-enabled.jade @@ -0,0 +1,13 @@ +section + h3(id='app.enabled') app.enabled(name) + + p. + Check if setting name is enabled. + + +js. + app.enabled('trust proxy'); + // => false + + app.enable('trust proxy'); + app.enabled('trust proxy'); + // => true \ No newline at end of file diff --git a/en/api/app-engine.jade b/en/api/app-engine.jade new file mode 100644 index 00000000..a7b825e0 --- /dev/null +++ b/en/api/app-engine.jade @@ -0,0 +1,41 @@ +section + h3(id='app.engine') app.engine(ext, callback) + + p. + Register the given template engine callback as ext + + By default will require() the engine based on the + file extension. For example if you try to render + a "foo.jade" file Express will invoke the following internally, + and cache the require() on subsequent calls to increase + performance. + + +js. + app.engine('jade', require('jade').__express); + + p. + For engines that do not provide .__express out of the box - + or if you wish to "map" a different extension to the template engine + you may use this method. For example mapping the EJS template engine to + ".html" files: + + +js. + app.engine('html', require('ejs').renderFile); + + p. + In this case EJS provides a .renderFile() method with + the same signature that Express expects: (path, options, callback), + though note that it aliases this method as ejs.__express internally + so if you're using ".ejs" extensions you dont need to do anything. + + p. + Some template engines do not follow this convention, the + consolidate.js + library was created to map all of node's popular template + engines to follow this convention, thus allowing them to + work seemlessly within Express. + + +js. + var engines = require('consolidate'); + app.engine('haml', engines.haml); + app.engine('html', engines.hogan); diff --git a/en/api/app-get.jade b/en/api/app-get.jade new file mode 100644 index 00000000..4e4e5b33 --- /dev/null +++ b/en/api/app-get.jade @@ -0,0 +1,13 @@ +section + h3(id='app.get') app.get(name) + + p. + Get setting name value. + + +js. + app.get('title'); + // => undefined + + app.set('title', 'My Site'); + app.get('title'); + // => "My Site" \ No newline at end of file diff --git a/en/api/app-listen.jade b/en/api/app-listen.jade new file mode 100644 index 00000000..10948a77 --- /dev/null +++ b/en/api/app-listen.jade @@ -0,0 +1,37 @@ +section + h3(id='app.listen') app.listen() + + p. + Bind and listen for connections on the given host and port, + this method is identical to node's http.Server#listen(). + + +js. + var express = require('express'); + var app = express(); + app.listen(3000); + + p. + The app returned by express() is in fact a JavaScript + Function, designed to be passed to node's http servers as a callback + to handle requests. This allows you to provide both HTTP and HTTPS versions of + your app with the same codebase easily, as the app does not inherit from these, + it is simply a callback: + + +js. + var express = require('express'); + var https = require('https'); + var http = require('http'); + var app = express(); + + http.createServer(app).listen(80); + https.createServer(options, app).listen(443); + + p. + The app.listen() method is simply a convenience method defined as, + if you wish to use HTTPS or provide both, use the technique above. + + +js. + app.listen = function(){ + var server = http.createServer(this); + return server.listen.apply(server, arguments); + }; diff --git a/en/api/app-locals.jade b/en/api/app-locals.jade new file mode 100644 index 00000000..a9375767 --- /dev/null +++ b/en/api/app-locals.jade @@ -0,0 +1,37 @@ +section + h3(id='app.locals') app.locals + + p. + Application local variables are provided to all templates + rendered within the application. This is useful for providing + helper functions to templates, as well as app-level data. + + +js. + app.locals.title = 'My App'; + app.locals.strftime = require('strftime'); + + p. + The app.locals object is a JavaScript Function, + which when invoked with an object will merge properties into itself, providing + a simple way to expose existing objects as local variables. + + +js. + app.locals({ + title: 'My App', + phone: '1-250-858-9990', + email: 'me@myapp.com' + }); + + app.locals.title + // => 'My App' + + app.locals.email + // => 'me@myapp.com' + + p. + By default Express exposes only a single app-level local variable, code>settings. + + +js. + app.set('title', 'My App'); + // use settings.title in a view + \ No newline at end of file diff --git a/en/api/app-param.jade b/en/api/app-param.jade new file mode 100644 index 00000000..51faf9dc --- /dev/null +++ b/en/api/app-param.jade @@ -0,0 +1,73 @@ +section + h3(id='app.param') app.param([name], callback) + + p. + Map logic to route parameters. For example when :user + is present in a route path you may map user loading logic to automatically + provide req.user to the route, or perform validations + on the parameter input. + + p. + The following snippet illustrates how the callback + is much like middleware, thus supporting async operations, however + providing the additional value of the parameter, here named as id. + An attempt to load the user is then performed, assigning req.user, + otherwise passing an error to next(err). + + +js. + app.param('user', function(req, res, next, id){ + User.find(id, function(err, user){ + if (err) { + next(err); + } else if (user) { + req.user = user; + next(); + } else { + next(new Error('failed to load user')); + } + }); + }); + + p. + Alternatively you may pass only a callback, in which + case you have the opportunity to alter the app.param() API. + For example the express-params + defines the following callback which allows you to restrict parameters to a given + regular expression. + + p. + This example is a bit more advanced, checking if the second argument is a regular + expression, returning the callback which acts much like the "user" param example. + + +js. + app.param(function(name, fn){ + if (fn instanceof RegExp) { + return function(req, res, next, val){ + var captures; + if (captures = fn.exec(String(val))) { + req.params[name] = captures; + next(); + } else { + next('route'); + } + } + } + }); + + p. + The method could now be used to effectively validate parameters, or also + parse them to provide capture groups: + + +js. + app.param('id', /^\d+$/); + + app.get('/user/:id', function(req, res){ + res.send('user ' + req.params.id); + }); + + app.param('range', /^(\w+)\.\.(\w+)?$/); + + app.get('/range/:range', function(req, res){ + var range = req.params.range; + res.send('from ' + range[1] + ' to ' + range[2]); + }); \ No newline at end of file diff --git a/en/api/app-render.jade b/en/api/app-render.jade new file mode 100644 index 00000000..93f54a25 --- /dev/null +++ b/en/api/app-render.jade @@ -0,0 +1,16 @@ +section + h3(id='app.render') app.render(view, [options], callback) + + p. + Render a view with a callback responding with + the rendered string. This is the app-level variant of res.render(), + and otherwise behaves the same way. + + +js. + app.render('email', function(err, html){ + // ... + }); + + app.render('email', { name: 'Tobi' }, function(err, html){ + // ... + }); \ No newline at end of file diff --git a/en/api/app-routes.jade b/en/api/app-routes.jade new file mode 100644 index 00000000..438f179d --- /dev/null +++ b/en/api/app-routes.jade @@ -0,0 +1,31 @@ + +section + h3(id='app.routes') app.routes + + p. + The app.routes object houses all of the routes defined mapped + by the associated HTTP verb. This object may be used for introspection capabilities, + for example Express uses this internally not only for routing but to provide default + OPTIONS behaviour unless app.options() is used. Your application + or framework may also remove routes by simply by removing them from this object. + + +js. + console.log(app.routes) + + { get: + [ { path: '/', + method: 'get', + callbacks: [Object], + keys: [], + regexp: /^\/\/?$/i }, + { path: '/user/:id', + method: 'get', + callbacks: [Object], + keys: [{ name: 'id', optional: false }], + regexp: /^\/user\/(?:([^\/]+?))\/?$/i } ], + delete: + [ { path: '/user/:id', + method: 'delete', + callbacks: [Object], + keys: [Object], + regexp: /^\/user\/(?:([^\/]+?))\/?$/i } ] } \ No newline at end of file diff --git a/en/api/app-set.jade b/en/api/app-set.jade new file mode 100644 index 00000000..71a0892d --- /dev/null +++ b/en/api/app-set.jade @@ -0,0 +1,10 @@ +section + h3(id='app.set') app.set(name, value) + + p. + Assigns setting name to value. + + +js. + app.set('title', 'My Site'); + app.get('title'); + // => "My Site" \ No newline at end of file diff --git a/en/api/app-settings.jade b/en/api/app-settings.jade new file mode 100644 index 00000000..eaec3d7b --- /dev/null +++ b/en/api/app-settings.jade @@ -0,0 +1,41 @@ +section + h3(id='app-settings') settings + + p. + The following settings are provided to alter how Express will behave: + + ul + li + code env + | Environment mode, defaults to process.env.NODE_ENV or "development" + li + code trust proxy + | Enables reverse proxy support, disabled by default + li + code jsonp callback + | Enables jsonp callback support, enabled by default + li + code jsonp callback name + | Changes the default callback name of ?callback= + li + code json replacer + | JSON replacer callback, null by default + li + code json spaces + | JSON response spaces for formatting, defaults to 2 in development, 0 in production + li + code case sensitive routing + | Enable case sensitivity, disabled by default, treating "/Foo" and "/foo" as the same + li + code strict routing + | Enable strict routing, by default "/foo" and "/foo/" are treated the same by the router + li + code view cache + | Enables view template compilation caching, enabled in production by default + li + code view engine + | The default engine extension to use when omitted + li + code views + | The view directory path + \ No newline at end of file diff --git a/en/api/app.jade b/en/api/app.jade new file mode 100644 index 00000000..645faea8 --- /dev/null +++ b/en/api/app.jade @@ -0,0 +1,16 @@ +include ./app-set +include ./app-get +include ./app-enable +include ./app-disable +include ./app-enabled +include ./app-disabled +include ./app-configure +include ./app-settings +include ./app-engine +include ./app-param +include ./app-VERB +include ./app-all +include ./app-locals +include ./app-render +include ./app-routes +include ./app-listen \ No newline at end of file diff --git a/en/api/express.jade b/en/api/express.jade new file mode 100644 index 00000000..3390e99f --- /dev/null +++ b/en/api/express.jade @@ -0,0 +1,15 @@ +section + h3(id='express') express() + + p. + Create an express application. + + +js. + var express = require('express'); + var app = express(); + + app.get('/', function(req, res){ + res.send('hello world'); + }); + + app.listen(3000); diff --git a/en/api/menu.jade b/en/api/menu.jade new file mode 100644 index 00000000..f8a51a48 --- /dev/null +++ b/en/api/menu.jade @@ -0,0 +1,68 @@ +ul#menu + li#app-api + a(href='#express') Application + ul#app-menu + li: a(href='#express') express() + li: a(href='#app.set') app.set() + li: a(href='#app.get') app.get() + li: a(href='#app.enable') app.enable() + li: a(href='#app.disable') app.disable() + li: a(href='#app.enabled') app.endabled() + li: a(href='#app.disabled') app.disabled() + li: a(href='#app.configure') app.configure() + li: a(href='#app.engine') app.engine() + li: a(href='#app.param') app.param() + li: a(href='#app-settings') application settings + li: a(href='#app.VERB') application routing + li: a(href='#app.all') app.all() + li: a(href='#app.locals') app.locals + li: a(href='#app.render') app.render() + li: a(href='#app.routes') app.routes + li: a(href='#app.listen') app.listen() + li#req-api + a(href='#req.params') Request + ul#req-menu + li: a(href='#req.params') req.params + li: a(href='#req.query') req.query + li: a(href='#req.body') req.body + li: a(href='#req.param') req.param() + li: a(href='#req.cookies') req.cookies + li: a(href='#req.signedCookies') req.signedCookies + li: a(href='#req.get') req.get() + li: a(href='#req.accepts') req.accepts() + li: a(href='#req.accepted') req.accepted + li: a(href='#req.is') req.is() + li: a(href='#req.ip') req.ip + li: a(href='#req.ips') req.ips + li: a(href='#req.path') req.path + li: a(href='#req.host') req.host + li: a(href='#req.fresh') req.fresh + li: a(href='#req.stale') req.stale + li: a(href='#req.xhr') req.xhr + li: a(href='#req.protocol') req.protocol + li: a(href='#req.secure') req.secure + li: a(href='#req.subdomains') req.subdomains + li: a(href='#req.acceptedLanguages') req.acceptedLanguages + li: a(href='#req.acceptedCharsets') req.acceptedCharsets + li: a(href='#req.acceptsCharset') req.acceptsCharset() + li: a(href='#req.acceptsLanguage') req.acceptsLanguage() + li#res-api + a(href='#res.status') Response + ul#res-menu + li: a(href='#res.status') res.status() + li: a(href='#res.set') res.set() + li: a(href='#res.get') res.get() + li: a(href='#res.cookie') res.cookie() + li: a(href='#res.clearCookie') res.clearCookie() + li: a(href='#res.redirect') res.redirect() + li: a(href='#res.charset') res.charset + li: a(href='#res.send') res.send() + li: a(href='#res.json') res.json() + li: a(href='#res.type') res.type() + li: a(href='#res.format') res.format() + li: a(href='#res.attachment') res.attachment() + li: a(href='#res.sendfile') res.sendfile() + li: a(href='#res.download') res.download() + li: a(href='#res.links') res.links() + li: a(href='#res.locals') res.locals + li: a(href='#res.render') res.render() diff --git a/en/api/req-accepted.jade b/en/api/req-accepted.jade new file mode 100644 index 00000000..cb9aab87 --- /dev/null +++ b/en/api/req-accepted.jade @@ -0,0 +1,15 @@ +section + h3(id='req.accepted') req.accepted + + p. + Return an array of Accepted media types ordered from highest quality to lowest. + + +js. + [ { value: 'application/json', + quality: 1, + type: 'application', + subtype: 'json' }, + { value: 'text/html', + quality: 0.5, + type: 'text', + subtype: 'html' } ] \ No newline at end of file diff --git a/en/api/req-acceptedCharsets.jade b/en/api/req-acceptedCharsets.jade new file mode 100644 index 00000000..34266c22 --- /dev/null +++ b/en/api/req-acceptedCharsets.jade @@ -0,0 +1,9 @@ +section + h3(id='req.acceptedCharsets') req.acceptedCharsets + + p. + Return an array of Accepted charsets ordered from highest quality to lowest. + + +js. + Accept-Charset: iso-8859-5;q=.2, unicode-1-1;q=0.8 + // => ['unicode-1-1', 'iso-8859-5'] diff --git a/en/api/req-acceptedLanguages.jade b/en/api/req-acceptedLanguages.jade new file mode 100644 index 00000000..cca60de1 --- /dev/null +++ b/en/api/req-acceptedLanguages.jade @@ -0,0 +1,9 @@ +section + h3(id='req.acceptedLanguages') req.acceptedLanguages + + p. + Return an array of Accepted languages ordered from highest quality to lowest. + + +js. + Accept-Language: en;q=.5, en-us + // => ['en-us', 'en'] diff --git a/en/api/req-accepts.jade b/en/api/req-accepts.jade new file mode 100644 index 00000000..d04bf229 --- /dev/null +++ b/en/api/req-accepts.jade @@ -0,0 +1,38 @@ +section + h3(id='req.accepts') req.accepts(types) + + p. + Check if the given types are acceptable, returning + the best match when true, otherwise undefined - in which + case you should respond with 406 "Not Acceptable". + + p. + The type value may be a single mime type string + such as "application/json", the extension name + such as "json", a comma-delimted list or an array. When a list + or array is given the best match, if any is returned. + + +js. + // Accept: text/html + req.accepts('html'); + // => "html" + + // Accept: text/*, application/json + req.accepts('html'); + // => "html" + req.accepts('text/html'); + // => "text/html" + req.accepts('json, text'); + // => "json" + req.accepts('application/json'); + // => "application/json" + + // Accept: text/*, application/json + req.accepts('image/png'); + req.accepts('png'); + // => undefined + + // Accept: text/*;q=.5, application/json + req.accepts(['html', 'json']); + req.accepts('html, json'); + // => "json" diff --git a/en/api/req-acceptsCharset.jade b/en/api/req-acceptsCharset.jade new file mode 100644 index 00000000..baa8b75c --- /dev/null +++ b/en/api/req-acceptsCharset.jade @@ -0,0 +1,5 @@ +section + h3(id='req.acceptsCharset') req.acceptsCharset(charset) + + p. + Check if the given charset are acceptable. diff --git a/en/api/req-acceptsLanguage.jade b/en/api/req-acceptsLanguage.jade new file mode 100644 index 00000000..23e21ee6 --- /dev/null +++ b/en/api/req-acceptsLanguage.jade @@ -0,0 +1,5 @@ +section + h3(id='req.acceptsLanguage') req.acceptsLanguage(lang) + + p. + Check if the given lang are acceptable. diff --git a/en/api/req-body.jade b/en/api/req-body.jade new file mode 100644 index 00000000..d584f535 --- /dev/null +++ b/en/api/req-body.jade @@ -0,0 +1,20 @@ +section + h3(id='req.body') req.body + + p. + This property is an object containing the parsed request body. This feature + is provided by the bodyParser() middleware, though other body + parsing middleware may follow this convention as well. This property + defaults to {} when bodyParser() is used. + + +js. + // POST user[name]=tobi&user[email]=tobi@learnboost.com + req.body.user.name + // => "tobi" + + req.body.user.email + // => "tobi@learnboost.com" + + // POST { "name": "tobi" } + req.body.name + // => "tobi" \ No newline at end of file diff --git a/en/api/req-cookies.jade b/en/api/req-cookies.jade new file mode 100644 index 00000000..caf38be3 --- /dev/null +++ b/en/api/req-cookies.jade @@ -0,0 +1,12 @@ +section + h3(id='req.cookies') req.cookies + + p. + When the cookieParser() middleware is used this object + defaults to {}, otherwise contains the cookies sent by + the user-agent. + + +js. + // Cookie: name=tj + req.cookies.name + // => "tj" diff --git a/en/api/req-fresh.jade b/en/api/req-fresh.jade new file mode 100644 index 00000000..662d805c --- /dev/null +++ b/en/api/req-fresh.jade @@ -0,0 +1,10 @@ +section + h3(id='req.fresh') req.fresh + + p. + Check if the request is fresh - aka Last-Modified and/or the ETag still match, + indicating that the resource is "fresh". + + +js. + req.fresh + // => true diff --git a/en/api/req-header.jade b/en/api/req-header.jade new file mode 100644 index 00000000..12c0cd59 --- /dev/null +++ b/en/api/req-header.jade @@ -0,0 +1,17 @@ +section + h3(id='req.get') req.get(field) + p + | Get the case-insensitive request header field. + | The Referrer and Referer fields are interchangeable. + + +js. + req.get('Content-Type'); + // => "text/plain" + + req.get('content-type'); + // => "text/plain" + + req.get('Something'); + // => undefined + + p Aliased as req.header(field). \ No newline at end of file diff --git a/en/api/req-host.jade b/en/api/req-host.jade new file mode 100644 index 00000000..d31b7838 --- /dev/null +++ b/en/api/req-host.jade @@ -0,0 +1,10 @@ +section + h3(id='req.host') req.host + + p. + Returns the hostname from the "Host" header field (void of portno). + + +js. + // Host: "example.com:3000" + req.host + // => "example.com" \ No newline at end of file diff --git a/en/api/req-ip.jade b/en/api/req-ip.jade new file mode 100644 index 00000000..b25d6f82 --- /dev/null +++ b/en/api/req-ip.jade @@ -0,0 +1,10 @@ +section + h3(id='req.ip') req.ip + + p. + Return the remote address, or when "trust proxy" + is enabled - the upstream address. + + +js. + req.ip + // => "127.0.0.1" diff --git a/en/api/req-ips.jade b/en/api/req-ips.jade new file mode 100644 index 00000000..fa4b25d9 --- /dev/null +++ b/en/api/req-ips.jade @@ -0,0 +1,12 @@ +section + h3(id='req.ips') req.ips + + p. + When "trust proxy" is `true`, parse + the "X-Forwarded-For" ip address list + and return an array, otherwise an empty + array is returned. + + For example if the value were "client, proxy1, proxy2" + you would receive the array ["client", "proxy1", "proxy2"] + where "proxy2" is the furthest down-stream. diff --git a/en/api/req-is.jade b/en/api/req-is.jade new file mode 100644 index 00000000..386443bf --- /dev/null +++ b/en/api/req-is.jade @@ -0,0 +1,22 @@ +section + h3(id='req.is') req.is(type) + + p. + Check if the incoming request contains the "Content-Type" + header field, and it matches the give mime type. + + +js. + // With Content-Type: text/html; charset=utf-8 + req.is('html'); + req.is('text/html'); + req.is('text/*'); + // => true + + // When Content-Type is application/json + req.is('json'); + req.is('application/json'); + req.is('application/*'); + // => true + + req.is('html'); + // => false diff --git a/en/api/req-param.jade b/en/api/req-param.jade new file mode 100644 index 00000000..c9a1c98b --- /dev/null +++ b/en/api/req-param.jade @@ -0,0 +1,30 @@ +section + h3(id='req.param') req.param(name) + + p. + Return the value of param name when present. + + +js. + // ?name=tobi + req.param('name') + // => "tobi" + + // POST name=tobi + req.param('name') + // => "tobi" + + // /user/tobi for /user/:name + req.param('name') + // => "tobi" + + p Lookup is performed in the following order: + + ul + li req.params + li req.body + li req.query + + p. + Direct access to req.body, req.params, + and req.query should be favoured for clarity - unless + you truly accept input from each object. \ No newline at end of file diff --git a/en/api/req-params.jade b/en/api/req-params.jade new file mode 100644 index 00000000..cfa68354 --- /dev/null +++ b/en/api/req-params.jade @@ -0,0 +1,23 @@ +section + h3(id='req.params') req.params + + p. + This property is an array containing properties mapped to the named route "parameters". + For example if you have the route /user/:name, then the "name" property + is available to you as req.params.name. This object defaults to {}. + + +js. + // GET /user/tj + req.params.name + // => "tj" + + p. + When a regular expression is used for the route definition, capture groups + are provided in the array using req.params[N], where N + is the nth capture group. This rule is applied to unnamed wild-card matches + with string routes such as `/file/*`: + + +js. + // GET /file/javascripts/jquery.js + req.params[0] + // => "javascripts/jquery.js" diff --git a/en/api/req-path.jade b/en/api/req-path.jade new file mode 100644 index 00000000..cabf93b0 --- /dev/null +++ b/en/api/req-path.jade @@ -0,0 +1,10 @@ +section + h3(id='req.path') req.path + + p. + Returns the request URL pathname. + + +js. + // example.com/users?sort=desc + req.path + // => "/users" \ No newline at end of file diff --git a/en/api/req-protocol.jade b/en/api/req-protocol.jade new file mode 100644 index 00000000..541303bb --- /dev/null +++ b/en/api/req-protocol.jade @@ -0,0 +1,14 @@ +section + h3(id='req.protocol') req.protocol + + p. + Return the protocol string "http" or "https" + when requested with TLS. When the "trust proxy" + setting is enabled the "X-Forwarded-Proto" header + field will be trusted. If you're running behind + a reverse proxy that supplies https for you this + may be enabled. + + +js. + req.protocol + // => "http" \ No newline at end of file diff --git a/en/api/req-query.jade b/en/api/req-query.jade new file mode 100644 index 00000000..11963b06 --- /dev/null +++ b/en/api/req-query.jade @@ -0,0 +1,21 @@ +section + h3(id='req.query') req.query + + p. + This property is an object containing the parsed query-string, + defaulting to {}. + + +js. + // GET /search?q=tobi+ferret + req.query.q + // => "tobi ferret" + + // GET /shoes?order=desc&shoe[color]=blue&shoe[type]=converse + req.query.order + // => "desc" + + req.query.show.color + // => "blue" + + req.query.show.converse + // => "converse" diff --git a/en/api/req-secure.jade b/en/api/req-secure.jade new file mode 100644 index 00000000..424310b6 --- /dev/null +++ b/en/api/req-secure.jade @@ -0,0 +1,8 @@ +section + h3(id='req.secure') req.secure + + p. + Check if a TLS connection is established. This is a short-hand for: + + +js. + return 'https' == this.protocol; diff --git a/en/api/req-signedCookies.jade b/en/api/req-signedCookies.jade new file mode 100644 index 00000000..a5b3c236 --- /dev/null +++ b/en/api/req-signedCookies.jade @@ -0,0 +1,16 @@ +section + h3(id='req.signedCookies') req.signedCookies + + p. + When the cookieParser(secret) middleware is used this object + defaults to {}, otherwise contains the signed cookies sent by + the user-agent, unsigned and ready for use. Signed cookies reside in a different + object to show developer intent, otherwise a malicious attack could be + placed on `req.cookie` values which are easy to spoof. Note that signing + a cookie does not mean it is "hidden" nor encrypted, this simply prevents + tampering as the secret used to sign is private. + + +js. + // Cookie: user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3 + req.signedCookies.user + // => "tobi" diff --git a/en/api/req-stale.jade b/en/api/req-stale.jade new file mode 100644 index 00000000..11fd5292 --- /dev/null +++ b/en/api/req-stale.jade @@ -0,0 +1,10 @@ +section + h3(id='req.stale') req.stale + + p. + Check if the request is stale - aka Last-Modified and/or the ETag do not match, + indicating that the resource is "stale". + + +js. + req.stale + // => true diff --git a/en/api/req-subdomains.jade b/en/api/req-subdomains.jade new file mode 100644 index 00000000..a7fee1a8 --- /dev/null +++ b/en/api/req-subdomains.jade @@ -0,0 +1,10 @@ +section + h3(id='req.subdomains') req.subdomains + + p. + Return subdomains as an array. + + +js. + // Host: "tobi.ferrets.example.com" + req.subdomains + // => ["ferrets", "tobi"] \ No newline at end of file diff --git a/en/api/req-xhr.jade b/en/api/req-xhr.jade new file mode 100644 index 00000000..56fa9ee3 --- /dev/null +++ b/en/api/req-xhr.jade @@ -0,0 +1,10 @@ +section + h3(id='req.xhr') req.xhr + + p. + Check if the request was issued with the "X-Request-With" + header field set to "XMLHttpRequest" (jQuery etc). + + +js. + req.xhr + // => true diff --git a/en/api/req.jade b/en/api/req.jade new file mode 100644 index 00000000..159ace26 --- /dev/null +++ b/en/api/req.jade @@ -0,0 +1,24 @@ +include ./req-params +include ./req-query +include ./req-body +include ./req-param +include ./req-cookies +include ./req-signedCookies +include ./req-header +include ./req-accepts +include ./req-accepted +include ./req-is +include ./req-ip +include ./req-ips +include ./req-path +include ./req-host +include ./req-fresh +include ./req-stale +include ./req-xhr +include ./req-protocol +include ./req-secure +include ./req-subdomains +include ./req-acceptedLanguages +include ./req-acceptedCharsets +include ./req-acceptsCharset +include ./req-acceptsLanguage diff --git a/en/api/res-attachment.jade b/en/api/res-attachment.jade new file mode 100644 index 00000000..74b853cf --- /dev/null +++ b/en/api/res-attachment.jade @@ -0,0 +1,16 @@ +section + h3(id='res.attachment') res.attachment([filename]) + + p. + Sets the Content-Disposition header field to "attachment". If + a filename is given then the Content-Type will be + automatically set based on the extname via res.type(), + and the Content-Disposition's "filename=" parameter will be set. + + +js. + res.attachment(); + // Content-Disposition: attachment + + res.attachment('path/to/logo.png'); + // Content-Disposition: attachment; filename="logo.png" + // Content-Type: image/png diff --git a/en/api/res-charset.jade b/en/api/res-charset.jade new file mode 100644 index 00000000..328416c3 --- /dev/null +++ b/en/api/res-charset.jade @@ -0,0 +1,10 @@ +section + h3(id='res.charset') res.charset + + p. + Assign the charset. Defaults to "utf-8". + + +js. + res.charset = 'value'; + res.send('

some html

'); + // => Content-Type: text/html; charset=value diff --git a/en/api/res-clearCookie.jade b/en/api/res-clearCookie.jade new file mode 100644 index 00000000..6e78f4d9 --- /dev/null +++ b/en/api/res-clearCookie.jade @@ -0,0 +1,9 @@ +section + h3(id='res.clearCookie') res.clearCookie(name, [options]) + p. + Clear cookie name. The path + option defaults to "/". + + +js. + res.cookie('name', 'tobi', { path: '/admin' }); + res.clearCookie('name', { path: '/admin' }); diff --git a/en/api/res-cookie.jade b/en/api/res-cookie.jade new file mode 100644 index 00000000..b91d971f --- /dev/null +++ b/en/api/res-cookie.jade @@ -0,0 +1,26 @@ +section + h3(id='res.cookie') res.cookie(name, value, [options]) + p. + Set cookie name to value, where + which may be a string or object converted to JSON. The path + option defaults to "/". + + +js. + res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true }); + res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true }); + + p. + The maxAge option is a convenience option for setting "expires" + relative to the current time in milliseconds. The following is equivalent to + the previous example. + + +js. + res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true }) + + p. + An object may be passed which is then serialized as JSON, which is + automatically parsed by the bodyParser() middleware. + + +js. + res.cookie('cart', { items: [1,2,3] }); + res.cookie('cart', { items: [1,2,3] }, { maxAge: 900000 }); \ No newline at end of file diff --git a/en/api/res-download.jade b/en/api/res-download.jade new file mode 100644 index 00000000..f54d33a5 --- /dev/null +++ b/en/api/res-download.jade @@ -0,0 +1,28 @@ +section + h3(id='res.download') res.download(path, [filename], [fn]) + + p. + Transfer the file at path as an "attachment", + typically browsers will prompt the user for download. The + Content-Disposition "filename=" parameter, aka the one + that will appear in the brower dialog is set to path + by default, however you may provide an override filename. + + p. + When an error has ocurred or transfer is complete the optional + callback fn is invoked. This method uses res.sendfile() + to transfer the file. + + +js. + res.download('/report-12345.pdf'); + + res.download('/report-12345.pdf', 'report.pdf'); + + res.download('/report-12345.pdf', 'report.pdf', function(err){ + if (err) { + // handle error, keep in mind the response may be partially-sent + // so check res.headerSent + } else { + // decrement a download credit etc + } + }); diff --git a/en/api/res-format.jade b/en/api/res-format.jade new file mode 100644 index 00000000..9e25536d --- /dev/null +++ b/en/api/res-format.jade @@ -0,0 +1,56 @@ +section + h3(id='res.format') res.format(object) + + p. + Performs content-negotiation on the request Accept header + field when present. This method uses req.accepted, an array of + acceptable types ordered by their quality values, otherwise the + first callback is invoked. When no match is performed the server + responds with 406 "Not Acceptable", or invokes the default + callback. + + p. + The Content-Type is set for you when a callback is selected, + however you may alter this within the callback using res.set() + or res.type() etcetera. + + p. + The following example would respond with { "message": "hey" } + when the Accept header field is set to "application/json" or "*/json", + however if "*/*" is given then "hey" will be the response. + + +js. + res.format({ + 'text/plain': function(){ + res.send('hey'); + }, + + 'text/html': function(){ + res.send('

hey

'); + }, + + 'appliation/json': function(){ + res.send({ message: 'hey' }); + } + }); + + p. + In addition to canonicalized MIME types you may also + use extnames mapped to these types, providing a slightly + less verbose implementation: + + +js. + res.format({ + text: function(){ + res.send('hey'); + }, + + html: function(){ + res.send('

hey

'); + }, + + json: function(){ + res.send({ message: 'hey' }); + } + }); + \ No newline at end of file diff --git a/en/api/res-get.jade b/en/api/res-get.jade new file mode 100644 index 00000000..a2a1aeef --- /dev/null +++ b/en/api/res-get.jade @@ -0,0 +1,8 @@ +section + h3(id='res.get') res.get(field) + p + | Get the case-insensitive response header field. + + +js. + res.get('Content-Type'); + // => "text/plain" diff --git a/en/api/res-json.jade b/en/api/res-json.jade new file mode 100644 index 00000000..6671bfed --- /dev/null +++ b/en/api/res-json.jade @@ -0,0 +1,14 @@ +section + h3(id='res.json') res.json([status|body], [body]) + + p. + Send a JSON response. This method is identical + to res.send() when an object or + array is passed, however it may be used for + explicit JSON conversion of non-objects (null, undefined, etc), + though these are technically not valid JSON. + + +js. + res.json(null) + res.json({ user: 'tobi' }) + res.json(500, { error: 'message' }) diff --git a/en/api/res-links.jade b/en/api/res-links.jade new file mode 100644 index 00000000..6bee0fb5 --- /dev/null +++ b/en/api/res-links.jade @@ -0,0 +1,19 @@ +section + h3(id='res.links') res.links(links) + + p. + Join the given links to populate the "Link" + response header field. + + +js. + res.links({ + next: 'http://api.example.com/users?page=2', + last: 'http://api.example.com/users?page=5' + }); + + p yields: + + pre + code. + Link: <http://api.example.com/users?page=2>; rel="next", + <http://api.example.com/users?page=5>; rel="last" diff --git a/en/api/res-locals.jade b/en/api/res-locals.jade new file mode 100644 index 00000000..73d3f081 --- /dev/null +++ b/en/api/res-locals.jade @@ -0,0 +1,18 @@ +section + h3(id='res.locals') res.locals + + p. + Response local variables are scoped to the request, thus only + available to the view(s) rendered during that request / response + cycle, if any. Otherwise this API is identical to app.locals. + + p. + This object is useful for exposes request-level information such as the + request pathname, authenticated user, user settings etcetera. + + +js. + app.use(function(req, res, next){ + res.locals.user = req.user; + res.locals.authenticated = ! req.user.anonymous; + next(); + }); \ No newline at end of file diff --git a/en/api/res-redirect.jade b/en/api/res-redirect.jade new file mode 100644 index 00000000..71697eda --- /dev/null +++ b/en/api/res-redirect.jade @@ -0,0 +1,53 @@ +section + h3(id='res.redirect') res.redirect([status], url) + p. + Redirect to the given url with optional statua code + defaulting to 302 "Found". + + +js. + res.redirect('/foo/bar'); + res.redirect('http://example.com'); + res.redirect(301, 'http://example.com'); + res.redirect('../login'); + + p. + Express supports a few forms of redirection, first being + a fully qualified URI for redirecting to a different site: + + +js. + res.redirect('http://google.com'); + + p. + The second form is the pathname-relative redirect, for example + if you were on http://example.com/admin/post/new, the + following redirect to /admin would land you at http://example.com/admin: + + +js. + res.redirect('/admin'); + + p. + This next redirect is relative to the mount point of the application. For example + if you have a blog application mounted at /blog, ideally it has no knowledge of + where it was mounted, so where a redirect of /admin/post/new would simply give you + http://example.com/admin/post/new, the following mount-relative redirect would give + you http://example.com/blog/admin/post/new: + + +js. + res.redirect('admin/post/new'); + + p. + Pathname relative redirects are also possible. If you were + on http://example.com/admin/post/new, the following redirect + would land you at http//example.com/admin/post: + + +js. + res.redirect('..'); + + p. + The final special-case is a back redirect, redirecting back to + the Referer (or Referrer), defaulting to / when missing. + + +js. + res.redirect('back'); + + diff --git a/en/api/res-render.jade b/en/api/res-render.jade new file mode 100644 index 00000000..0303fdab --- /dev/null +++ b/en/api/res-render.jade @@ -0,0 +1,17 @@ +section + h3(id='res.render') res.render(view, [locals], callback) + + p. + Render a view with a callback responding with + the rendered string. When an error occurs next(err) + is invoked internally. When a callback is provided both the possible error + and rendered string are passed, and no automated response is performed. + + +js. + app.render('index', function(err, html){ + // ... + }); + + app.render('user', { name: 'Tobi' }, function(err, html){ + // ... + }); \ No newline at end of file diff --git a/en/api/res-send.jade b/en/api/res-send.jade new file mode 100644 index 00000000..94af486b --- /dev/null +++ b/en/api/res-send.jade @@ -0,0 +1,55 @@ +section + h3(id='res.send') res.send([body|status], [body]) + + p. + Send a response. + + +js. + res.send(new Buffer('whoop')); + res.send({ some: 'json' }); + res.send('

some html

'); + res.send(404, 'Sorry, we cannot find that!'); + res.send(500, { error: 'something blew up' }); + res.send(200); + + p. + This method performs a myriad of + useful tasks for simple non-streaming responses such + as automatically assigning the Content-Length unless + previously defined and providing automatic HEAD and + HTTP cache freshness support. + + p. + When a Buffer is given + the Content-Type is set to "application/octet-stream" + unless previously defined as shown below: + + +js. + res.set('Content-Type', 'text/html'); + res.send(new Buffer('

some html

')); + + p. + When a String is given the + Content-Type is set defaulted to "text/html": + + +js. + res.send('

some html

'); + + p. + When an Array or Object is + given Express will respond with the JSON representation: + + +js. + res.send({ user: 'tobi' }) + res.send([1,2,3]) + + p. + Finally when a Number is given without + any of the previously mentioned bodies, then a response + body string is assigned for you. For example 200 will + respond will the text "OK", and 204 "Not Found" and so on. + + +js. + res.send(200) + res.send(204) + res.send(500) diff --git a/en/api/res-sendfile.jade b/en/api/res-sendfile.jade new file mode 100644 index 00000000..01a37c8d --- /dev/null +++ b/en/api/res-sendfile.jade @@ -0,0 +1,33 @@ +section + h3(id='res.sendfile') res.sendfile(path, [options], [fn]]) + + p Transfer the file at the given path. + + p. + Automatically defaults the Content-Type response header field based + on the filename's extension. The callback fn(err) is + invoked when the transfer is complete or when an error occurs. + + p Options: + + ul + li maxAge in milliseconds defaulting to 0 + li root root directory for relative filenames + + p. + This method provides fine-grained support for file serving + as illustrated in the following example: + + +js. + app.get('/user/:uid/photos/:file', function(req, res){ + var uid = req.params.uid + , file = req.params.file; + + req.user.mayViewFilesFrom(uid, function(yes){ + if (yes) { + res.sendfile('/uploads/' + uid + '/' + file); + } else { + res.send(403, 'Sorry! you cant see that.'); + } + }); + }); \ No newline at end of file diff --git a/en/api/res-set.jade b/en/api/res-set.jade new file mode 100644 index 00000000..97640236 --- /dev/null +++ b/en/api/res-set.jade @@ -0,0 +1,16 @@ +section + h3(id='res.set') res.set(field, [value]) + p + | Set header field to value, + | or pass an object to set multiple fields at once. + + +js. + res.set('Content-Type', 'text/plain'); + + res.set({ + 'Content-Type': 'text/plain', + 'Content-Length': '123', + 'ETag': '12345' + }) + + p Aliased as res.header(field, [value]). \ No newline at end of file diff --git a/en/api/res-status.jade b/en/api/res-status.jade new file mode 100644 index 00000000..0e000395 --- /dev/null +++ b/en/api/res-status.jade @@ -0,0 +1,8 @@ +section + h3(id='res.status') res.status(code) + + p. + Chainable alias of node's '`res.statusCode=`. + + +js. + req.status(204).sendfile('path/to/404.png'); diff --git a/en/api/res-type.jade b/en/api/res-type.jade new file mode 100644 index 00000000..fe8d210f --- /dev/null +++ b/en/api/res-type.jade @@ -0,0 +1,14 @@ +section + h3(id='res.type') res.type(type) + + p. + Sets the Content-Type to the mime lookup of type, + or when "/" is present the Content-Type is simply set to this + literal value. + + +js. + res.type('.html'); + res.type('html'); + res.type('json'); + res.type('application/json'); + res.type('png'); diff --git a/en/api/res.jade b/en/api/res.jade new file mode 100644 index 00000000..57deaf7c --- /dev/null +++ b/en/api/res.jade @@ -0,0 +1,17 @@ +include ./res-status +include ./res-set +include ./res-get +include ./res-cookie +include ./res-clearCookie +include ./res-redirect +include ./res-charset +include ./res-send +include ./res-json +include ./res-type +include ./res-format +include ./res-attachment +include ./res-sendfile +include ./res-download +include ./res-links +include ./res-locals +include ./res-render diff --git a/en/applications.jade b/en/applications.jade new file mode 100644 index 00000000..184afdf1 --- /dev/null +++ b/en/applications.jade @@ -0,0 +1,86 @@ + +mixin image(name) + img(src='/images/apps/screenshots/#{name}.small.png') + +mixin link(title, url) + .link + | Visit + a(href=url)= title + +section.application + h2 LearnBoost + p. + LearnBoost provides a free, easy to use online + online education suite including gradebook, + lesson plans, attendance, reporting, and calendars + among other tools. + + +link('LearnBoost', 'https://www.learnboost.com/') + +image('learnboost') + +section.application + h2 Storify + p. + Create stories using social media. Turn what people post + on social media into compelling stories. Collect the best photos, video, + tweets and more to publish + + +link('Storify', 'http://storify.com/') + +image('storify') + +section.application + h2 Geekli.st + p. + A place for geeks to share what they've done, who they did it with and + connect with great companies and communities. + + +link('Geekli.st', 'http://geekli.st') + +image('geeklist') + +section.application + h2 Klout + p. + Klout is the Standard for Influence. Join Klout to discover your + influence and compare with others you may know. + + +link('Klout', 'http://klout.com') + +image('klout') + +section.application + h2 Prismatic + p. + Prismatic learns from how you interact on social networks so that we + can show you the most interesting content and conversation from your friends. + + +link('Prismatic', 'http://getprismatic.com/') + +image('prismatic') + +section.application + h2 Clipboard + p. + Clipboard is a powerful tool allowing to save live clips + of your interests on the web, not just static images, + but fully-functional fragments of anything online. + + +link('Clipboard', 'http://clipboard.com/') + +image('clipboard') + +section.application + h2 Persona + p. + Persona, or "BrowserID" is Mozilla's answer + to a better identification system for your browser, + this promising tool is definitely worth checking out. + + +link('Persona', 'https://login.persona.org/') + +image('browserid') + +section.application + h2 and more! + p. + Shodan search reports that there are well over 26,000 Express applications + in the wild, we can't possibly list them all here, but if you feel + your application helps showcase the framework open an issue on + the github repo. + + +image('more') \ No newline at end of file diff --git a/en/community.jade b/en/community.jade new file mode 100644 index 00000000..d6fd7d6f --- /dev/null +++ b/en/community.jade @@ -0,0 +1,34 @@ +#boxes.clearfix + section#mailing-list + h3 Mailing List + p. + Join over 1500 Express users or browse over 5000 + discussions in the Google Group. + + section#irc + h3 IRC Channel + p. + Hundreds of developers idle in #express on freenode every day, + if you have questions about the framework jump in for quick + feedback. + + section#examples + h3 Examples + p. + View dozens of Express application examples + in the github repository covering everything from API design and authentication + to template engine integration. + + section#issues + h3 Issues + p. + If you've come across what you think is a bug, or just want to make + a feature request open a ticket in the issue queue. + + section#extending + h3 Third Party + p. + Our vibrant community has created a large variety of extensions, + middleware + and higher level frameworks. Check them out in the + wiki. \ No newline at end of file diff --git a/en/faq.jade b/en/faq.jade new file mode 100644 index 00000000..b8c4b739 --- /dev/null +++ b/en/faq.jade @@ -0,0 +1,117 @@ + +section + h3(id='models') How do I define models? + + p. + Express has no notion of a database at all, this is + left up to third-party node modules - allowing you to + interface with nearly any database. + +section + h3(id='auth') How can I authenticate users? + + p. + This is another opinionated area that Express does not + venture into, you may use any authentication scheme you wish. + For a simple username / password scheme view this example. + +section + h3(id='templates') Which template engines does Express support? + + p. + Anything that can conform with the (path, locals, callback) signature. + To normalize template engine interfaces and caching it's recommended to + check the consolidate.js + project for support. Unlisted template engines may still support the Express + signature. + +section + h3(id='structure') How should I structure my application? + + p. + There is no true answer to this question, it is highly dependant + on the scale of your application and the team involved. To be as + flexible as possible Express makes no assumptions in terms of structure. + + p. + Routes and other application-specific logic may live in as many files + as you wish, in any directory structure you prefer. View the following + examples for inspiration: + + ul + li: a(href='https://github.com/visionmedia/express/blob/master/examples/route-separation/app.js#L20') Route listings + li: a(href='https://github.com/visionmedia/express/blob/master/examples/route-map/index.js#L47') Route map + li: a(href='https://github.com/visionmedia/express/tree/master/examples/route-loading') Route bootstrapping + li: a(href='https://github.com/visionmedia/express/tree/master/examples/mvc') MVC style controllers + + p. + Available as well are third-party extensions to Express to simplify some of these patterns: + + ul + li: a(href='https://github.com/visionmedia/express-resource') Resourceful routing + li: a(href='https://github.com/visionmedia/express-namespace') Namespaced routing + +section + h3(id='multiple-statics') How can I serve statics from several directories? + + p. + You may typically use any middleware several times + within your application. With the following middleware setup and a request + to "GET /javascripts/jquery.js" would first check "./public/javascripts/jquery.js", + if it does not exist then the subsequent middleware will check "./files/javascripts/jquery.js". + + +js. + app.use(express.static('public')); + app.use(express.static('files')); + +setup + h3(id='static-prefix') How can I prefix a pathname for serving statics? + + p. + Connect's generic "mounting" feature allows you to define + the pathname "prefix" to which the middleware will be invoked, + effectively behaving as if that prefix string was never + part of the path. Suppose if you wanted "GET /files/javascripts/jquery.js", + you could mount the middleware at "/files", exposing "/javascripts/jquery.js" + as the req.url allowing the middleware to serve the file: + + +js. + app.use('/public', express.static('public')); + +setup + h3(id='migration') How do I migrate my Express 2.x application? + + p. + Express 2x will likely be supported through to node 1.0 so there's + no immediate reason to update beyond the refactoring and API changes + that Express 3x introduces, so if you're happy with 2x feel free + to remain on that branch. For migration information visit the + migration + wiki page, or view a list of changes made in 3.x. + +setup + h3(id='error-handling') How do you setup an error handler in Express? + + p. + Error-handling middleware are defined just like regular middleware, + however must be define with an arity of 4, that is the signature + (err, req, res, next): + + +js. + app.use(function(err, req, res, next){ + console.error(err.stack); + res.send(500, 'Something broke!'); + }); + + p. + View error-handling information. + +setup + h3(id='size') How big is the Express codebase? + + p. + Express is a very small framework, the 3.0.0 release is only + 932 SLOC, and the mandatory portion of Connect which Express + is built on is only 267 SLOC. The optional middleware bundled + with Connect add an additional 1143 SLOC, and are lazy loaded + upon use. diff --git a/en/guide/executable.jade b/en/guide/executable.jade new file mode 100644 index 00000000..f31b856b --- /dev/null +++ b/en/guide/executable.jade @@ -0,0 +1,76 @@ +section + h3(id='executable') Using express(1) to generate an app + + p. + Express is bundled with an executable, aptly named express(1). + If you install express globally with npm you'll have it available from anywhere + on your machine: + + +js. + $ npm install -g express + + p. + This tool provides a simple way to get an application skeleton going, + but has limited scope, for example it supports only a few template engines, + whereas Express itself supports virtually any template engine built for node. + Be sure to check out the --help: + + +js. + + Usage: express [options] + + Options: + + -h, --help output usage information + -V, --version output the version number + -s, --sessions add session support + -e, --ejs add ejs engine support (defaults to jade) + -J, --jshtml add jshtml engine support (defaults to jade) + -h, --hogan add hogan.js engine support + -c, --css add stylesheet support (less|stylus) (defaults to plain css) + -f, --force force on non-empty directory + p. + If you want to generate an application with EJS, Stylus, and session + support you would simply execute: + + +js. + $ express --sessions --css stylus --ejs myapp + + create : myapp + create : myapp/package.json + create : myapp/app.js + create : myapp/public + create : myapp/public/javascripts + create : myapp/public/images + create : myapp/public/stylesheets + create : myapp/public/stylesheets/style.styl + create : myapp/routes + create : myapp/routes/index.js + create : myapp/views + create : myapp/views/index.ejs + + install dependencies: + $ cd myapp && npm install + + run the app: + $ node app + + p. + Like any other node application, you must then install the dependencies: + + +js. + $ cd myapp + $ npm install + + p. + Then fire it up! + + +js. + $ node app + + p. + That's all you need to get a simple application up and running. Keep in mind + that Express is not bound to any specific directory structure, these are simply + a baseline for you to work from. For application structure alternatives be + sure to view the examples + found in the github repo. \ No newline at end of file diff --git a/en/guide/index.jade b/en/guide/index.jade new file mode 100644 index 00000000..8212882e --- /dev/null +++ b/en/guide/index.jade @@ -0,0 +1,2 @@ +include intro +include executable \ No newline at end of file diff --git a/en/guide/intro.jade b/en/guide/intro.jade new file mode 100644 index 00000000..f2b51b7d --- /dev/null +++ b/en/guide/intro.jade @@ -0,0 +1,90 @@ +section + h3(id='intro') Getting started + + p. + With node installed (download), + get your first application started by creating a directory somewhere + on your machine: + + +js. + $ mkdir hello-world + + p. + In this same directory you'll be defining the application "package", which + are no different than any other node package. You'll need a package.json + file in the directory, with express defined as a dependency: + + +js. + { + "name": "hello-world", + "description": "hello world test app", + "version": "0.0.1", + "private": true, + "dependencies": { + "express": "3.0.0" + } + } + + p. + Now that you have a package.json file in this directory you can use + npm(1) to install the dependencies, in this case just + Express: + + +js. + $ npm install + + p. + Once npm finishes you'll have a localized Express 3.x dependency in + the ./node_modules directory. You may verify this with npm ls + as shown in the following snippet displaying a tree of Express and its + own dependencies. + + +js. + $ npm ls + hello-world@0.0.1 /private/tmp + └─┬ express@3.0.0beta7 + ├── commander@0.6.1 + ├─┬ connect@2.3.9 + │ ├── bytes@0.1.0 + │ ├── cookie@0.0.4 + │ ├── crc@0.2.0 + │ ├── formidable@1.0.11 + │ └── qs@0.4.2 + ├── cookie@0.0.3 + ├── debug@0.7.0 + ├── fresh@0.1.0 + ├── methods@0.0.1 + ├── mkdirp@0.3.3 + ├── range-parser@0.0.4 + ├─┬ response-send@0.0.1 + │ └── crc@0.2.0 + └─┬ send@0.0.3 + └── mime@1.2.6 + + p. + Now to create the application itself! Create a file named app.js or server.js, + whichever you prefer, require express and then create a new application with express(): + + +js. + var express = require('express'); + var app = express(); + + p. + With the new application instance you can start defining routes via app.VERB(), + in this case "GET /" responding with the "Hello World" string. The req and + res are the exact same objects that node provides to you, thus you may invoke + res.pipe(), req.on('data', callback) and anything else you + would do without Express involved. + + +js. + app.get('/', function(req, res){ + res.send('Hello World'); + }); + + p. + Now to bind and listen for connections invoke the app.listen() method, + accepting the same arguments as node's net.Server#listen(): + + +js. + app.listen(3000); + console.log('Listening on port 3000'); diff --git a/en/guide/menu.jade b/en/guide/menu.jade new file mode 100644 index 00000000..f98d3167 --- /dev/null +++ b/en/guide/menu.jade @@ -0,0 +1,4 @@ +ul#menu + li: ul + li: a(href='#intro') Getting started + li: a(href='#executable') express(1) executable diff --git a/faq.html b/faq.html new file mode 100644 index 00000000..63520d49 --- /dev/null +++ b/faq.html @@ -0,0 +1,51 @@ +Express - faq

How do I define models?

Express has no notion of a database at all, this is +left up to third-party node modules - allowing you to +interface with nearly any database. +

How can I authenticate users?

This is another opinionated area that Express does not +venture into, you may use any authentication scheme you wish. +For a simple username / password scheme view this example. +

Which template engines does Express support?

Anything that can conform with the (path, locals, callback) signature. +To normalize template engine interfaces and caching it's recommended to +check the consolidate.js +project for support. Unlisted template engines may still support the Express +signature. +

How should I structure my application?

There is no true answer to this question, it is highly dependant +on the scale of your application and the team involved. To be as +flexible as possible Express makes no assumptions in terms of structure. +

Routes and other application-specific logic may live in as many files +as you wish, in any directory structure you prefer. View the following +examples for inspiration: +

Available as well are third-party extensions to Express to simplify some of these patterns: +

How can I serve statics from several directories?

You may typically use any middleware several times +within your application. With the following middleware setup and a request +to "GET /javascripts/jquery.js" would first check "./public/javascripts/jquery.js", +if it does not exist then the subsequent middleware will check "./files/javascripts/jquery.js". +

app.use(express.static('public'));
+app.use(express.static('files'));
+

How can I prefix a pathname for serving statics?

Connect's generic "mounting" feature allows you to define +the pathname "prefix" to which the middleware will be invoked, +effectively behaving as if that prefix string was never +part of the path. Suppose if you wanted "GET /files/javascripts/jquery.js", +you could mount the middleware at "/files", exposing "/javascripts/jquery.js" +as the req.url allowing the middleware to serve the file: +

app.use('/public', express.static('public'));
+

How do I migrate my Express 2.x application?

Express 2x will likely be supported through to node 1.0 so there's +no immediate reason to update beyond the refactoring and API changes +that Express 3x introduces, so if you're happy with 2x feel free +to remain on that branch. For migration information visit the +migration +wiki page, or view a list of changes made in 3.x. +

How do you setup an error handler in Express?

Error-handling middleware are defined just like regular middleware, +however must be define with an arity of 4, that is the signature +(err, req, res, next): +

app.use(function(err, req, res, next){
+  console.error(err.stack);
+  res.send(500, 'Something broke!');
+});
+

View error-handling information. +

How big is the Express codebase?

Express is a very small framework, the 3.0.0 release is only +932 SLOC, and the mandatory portion of Connect which Express +is built on is only 267 SLOC. The optional middleware bundled +with Connect add an additional 1143 SLOC, and are lazy loaded +upon use.

\ No newline at end of file diff --git a/faq.jade b/faq.jade new file mode 100644 index 00000000..5144702a --- /dev/null +++ b/faq.jade @@ -0,0 +1,15 @@ +!!! 5 +html + head + title Express - faq + include includes/head + body.inner + .bar + section#content + header + include includes/logo + active = '/faq.html' + include includes/menu + #faq + include en/faq + include includes/footer diff --git a/guide.html b/guide.html new file mode 100644 index 00000000..74208b34 --- /dev/null +++ b/guide.html @@ -0,0 +1,111 @@ +Express - api reference

Getting started

With node installed (download), +get your first application started by creating a directory somewhere +on your machine: +

$ mkdir hello-world
+

In this same directory you'll be defining the application "package", which +are no different than any other node package. You'll need a package.json +file in the directory, with express defined as a dependency: +

{
+  "name": "hello-world",
+  "description": "hello world test app",
+  "version": "0.0.1",
+  "private": true,
+  "dependencies": {
+    "express": "3.0.0"
+  }
+}
+

Now that you have a package.json file in this directory you can use +npm(1) to install the dependencies, in this case just +Express: +

$ npm install
+

Once npm finishes you'll have a localized Express 3.x dependency in +the ./node_modules directory. You may verify this with npm ls +as shown in the following snippet displaying a tree of Express and its +own dependencies. +

$ npm ls
+hello-world@0.0.1 /private/tmp
+└─┬ express@3.0.0beta7 
+  ├── commander@0.6.1 
+  ├─┬ connect@2.3.9 
+  │ ├── bytes@0.1.0 
+  │ ├── cookie@0.0.4 
+  │ ├── crc@0.2.0 
+  │ ├── formidable@1.0.11 
+  │ └── qs@0.4.2 
+  ├── cookie@0.0.3 
+  ├── debug@0.7.0 
+  ├── fresh@0.1.0 
+  ├── methods@0.0.1 
+  ├── mkdirp@0.3.3 
+  ├── range-parser@0.0.4 
+  ├─┬ response-send@0.0.1 
+  │ └── crc@0.2.0 
+  └─┬ send@0.0.3 
+    └── mime@1.2.6
+    

Now to create the application itself! Create a file named app.js or server.js, +whichever you prefer, require express and then create a new application with express(): +

var express = require('express');
+var app = express();
+

With the new application instance you can start defining routes via app.VERB(), +in this case "GET /" responding with the "Hello World" string. The req and +res are the exact same objects that node provides to you, thus you may invoke +res.pipe(), req.on('data', callback) and anything else you +would do without Express involved. +

app.get('/', function(req, res){
+  res.send('Hello World');
+});
+

Now to bind and listen for connections invoke the app.listen() method, +accepting the same arguments as node's net.Server#listen(): +

app.listen(3000);
+console.log('Listening on port 3000');

Using express(1) to generate an app

Express is bundled with an executable, aptly named express(1). +If you install express globally with npm you'll have it available from anywhere +on your machine: +

$ npm install -g express
+

This tool provides a simple way to get an application skeleton going, +but has limited scope, for example it supports only a few template engines, +whereas Express itself supports virtually any template engine built for node. +Be sure to check out the --help: +

Usage: express [options]
+
+Options:
+
+  -h, --help          output usage information
+  -V, --version       output the version number
+  -s, --sessions      add session support
+  -e, --ejs           add ejs engine support (defaults to jade)
+  -J, --jshtml        add jshtml engine support (defaults to jade)
+  -h, --hogan         add hogan.js engine support
+  -c, --css   add stylesheet  support (less|stylus) (defaults to plain css)
+  -f, --force         force on non-empty directory

If you want to generate an application with EJS, Stylus, and session +support you would simply execute: +

$ express --sessions --css stylus --ejs myapp
+
+create : myapp
+create : myapp/package.json
+create : myapp/app.js
+create : myapp/public
+create : myapp/public/javascripts
+create : myapp/public/images
+create : myapp/public/stylesheets
+create : myapp/public/stylesheets/style.styl
+create : myapp/routes
+create : myapp/routes/index.js
+create : myapp/views
+create : myapp/views/index.ejs
+
+install dependencies:
+  $ cd myapp && npm install
+  
+run the app:
+  $ node app  
+  

Like any other node application, you must then install the dependencies: +

$ cd myapp
+$ npm install
+

Then fire it up! +

$ node app
+

That's all you need to get a simple application up and running. Keep in mind +that Express is not bound to any specific directory structure, these are simply +a baseline for you to work from. For application structure alternatives be +sure to view the examples +found in the github repo.

\ No newline at end of file diff --git a/guide.jade b/guide.jade new file mode 100644 index 00000000..568f06db --- /dev/null +++ b/guide.jade @@ -0,0 +1,19 @@ +!!! 5 +html + head + title Express - api reference + include includes/head + body.inner + .bar + section#content + header + include includes/logo + active = '/guide.html' + include includes/menu + + include includes/mixins + include en/guide/menu + + include en/guide/index + + include includes/footer diff --git a/images/apps/logos/canadian-tire.png b/images/apps/logos/canadian-tire.png new file mode 100644 index 00000000..25509563 Binary files /dev/null and b/images/apps/logos/canadian-tire.png differ diff --git a/images/apps/logos/clipboard.png b/images/apps/logos/clipboard.png new file mode 100644 index 00000000..52a9234f Binary files /dev/null and b/images/apps/logos/clipboard.png differ diff --git a/images/apps/logos/doodle-or-die.png b/images/apps/logos/doodle-or-die.png new file mode 100644 index 00000000..e2b76643 Binary files /dev/null and b/images/apps/logos/doodle-or-die.png differ diff --git a/images/apps/logos/ebay.png b/images/apps/logos/ebay.png new file mode 100644 index 00000000..18e247d9 Binary files /dev/null and b/images/apps/logos/ebay.png differ diff --git a/images/apps/logos/geeklist.png b/images/apps/logos/geeklist.png new file mode 100644 index 00000000..84eb2fdf Binary files /dev/null and b/images/apps/logos/geeklist.png differ diff --git a/images/apps/logos/klout.png b/images/apps/logos/klout.png new file mode 100644 index 00000000..470a86dd Binary files /dev/null and b/images/apps/logos/klout.png differ diff --git a/images/apps/logos/koding.png b/images/apps/logos/koding.png new file mode 100644 index 00000000..689f7913 Binary files /dev/null and b/images/apps/logos/koding.png differ diff --git a/images/apps/logos/learnboost.png b/images/apps/logos/learnboost.png new file mode 100644 index 00000000..8aa61f75 Binary files /dev/null and b/images/apps/logos/learnboost.png differ diff --git a/images/apps/logos/mcdonalds.png b/images/apps/logos/mcdonalds.png new file mode 100644 index 00000000..165e3535 Binary files /dev/null and b/images/apps/logos/mcdonalds.png differ diff --git a/images/apps/logos/mozilla.png b/images/apps/logos/mozilla.png new file mode 100644 index 00000000..b0b1d400 Binary files /dev/null and b/images/apps/logos/mozilla.png differ diff --git a/images/apps/logos/nerve.png b/images/apps/logos/nerve.png new file mode 100644 index 00000000..12e2d937 Binary files /dev/null and b/images/apps/logos/nerve.png differ diff --git a/images/apps/logos/starbucks.png b/images/apps/logos/starbucks.png new file mode 100644 index 00000000..b0a78ec9 Binary files /dev/null and b/images/apps/logos/starbucks.png differ diff --git a/images/apps/logos/storify.png b/images/apps/logos/storify.png new file mode 100644 index 00000000..033e0f64 Binary files /dev/null and b/images/apps/logos/storify.png differ diff --git a/images/apps/logos/uber.png b/images/apps/logos/uber.png new file mode 100644 index 00000000..06206612 Binary files /dev/null and b/images/apps/logos/uber.png differ diff --git a/images/apps/logos/yahoo.png b/images/apps/logos/yahoo.png new file mode 100644 index 00000000..d708fc8a Binary files /dev/null and b/images/apps/logos/yahoo.png differ diff --git a/images/apps/screenshots/browserid.small.png b/images/apps/screenshots/browserid.small.png new file mode 100644 index 00000000..9d2020dc Binary files /dev/null and b/images/apps/screenshots/browserid.small.png differ diff --git a/images/apps/screenshots/clipboard.small.png b/images/apps/screenshots/clipboard.small.png new file mode 100644 index 00000000..281780fc Binary files /dev/null and b/images/apps/screenshots/clipboard.small.png differ diff --git a/images/apps/screenshots/geeklist.small.png b/images/apps/screenshots/geeklist.small.png new file mode 100644 index 00000000..abe3869f Binary files /dev/null and b/images/apps/screenshots/geeklist.small.png differ diff --git a/images/apps/screenshots/klout.small.png b/images/apps/screenshots/klout.small.png new file mode 100644 index 00000000..bd212205 Binary files /dev/null and b/images/apps/screenshots/klout.small.png differ diff --git a/images/apps/screenshots/learnboost.small.png b/images/apps/screenshots/learnboost.small.png new file mode 100644 index 00000000..d4a78529 Binary files /dev/null and b/images/apps/screenshots/learnboost.small.png differ diff --git a/images/apps/screenshots/more.small.png b/images/apps/screenshots/more.small.png new file mode 100644 index 00000000..db6b7058 Binary files /dev/null and b/images/apps/screenshots/more.small.png differ diff --git a/images/apps/screenshots/prismatic.small.png b/images/apps/screenshots/prismatic.small.png new file mode 100644 index 00000000..2d203f61 Binary files /dev/null and b/images/apps/screenshots/prismatic.small.png differ diff --git a/images/apps/screenshots/storify.small.png b/images/apps/screenshots/storify.small.png new file mode 100644 index 00000000..3a9377ee Binary files /dev/null and b/images/apps/screenshots/storify.small.png differ diff --git a/images/arrow.png b/images/arrow.png new file mode 100644 index 00000000..3e2a53c8 Binary files /dev/null and b/images/arrow.png differ diff --git a/images/bg.png b/images/bg.png new file mode 100644 index 00000000..ca3d2679 Binary files /dev/null and b/images/bg.png differ diff --git a/images/github-small.png b/images/github-small.png new file mode 100644 index 00000000..c2167079 Binary files /dev/null and b/images/github-small.png differ diff --git a/images/github.png b/images/github.png new file mode 100644 index 00000000..b5157dbb Binary files /dev/null and b/images/github.png differ diff --git a/images/hr.png b/images/hr.png new file mode 100644 index 00000000..17ed8b4e Binary files /dev/null and b/images/hr.png differ diff --git a/images/ios-bg.png b/images/ios-bg.png new file mode 100644 index 00000000..a5e603e5 Binary files /dev/null and b/images/ios-bg.png differ diff --git a/images/light-bg.png b/images/light-bg.png new file mode 100644 index 00000000..a5e603e5 Binary files /dev/null and b/images/light-bg.png differ diff --git a/includes/app-logos.jade b/includes/app-logos.jade new file mode 100644 index 00000000..cac499a5 --- /dev/null +++ b/includes/app-logos.jade @@ -0,0 +1,17 @@ + +ul + +logo('learnboost') + +logo('storify') + +logo('geeklist') + +logo('klout') + +logo('koding') + +logo('clipboard') + +logo('mcdonalds') + +logo('mozilla') + +logo('ebay') + //+logo('nerve') + +logo('uber') + +logo('starbucks') + +logo('yahoo') + //+logo('canadian-tire') + //+logo('doodle-or-die') diff --git a/includes/footer.jade b/includes/footer.jade new file mode 100644 index 00000000..351788ac --- /dev/null +++ b/includes/footer.jade @@ -0,0 +1,7 @@ +a#top(href='#') + img(src='images/arrow.png') + +footer + #footer-content + © 2012 TJ Holowaychuk. All rights reserved. + diff --git a/includes/head.jade b/includes/head.jade new file mode 100644 index 00000000..ce0f8398 --- /dev/null +++ b/includes/head.jade @@ -0,0 +1,5 @@ +link(rel='stylesheet', href='style.css') +link(rel='stylesheet', href='//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&subset=latin,latin-ext') +meta(http-equiv='Content-Type', content='text/html; charset=UTF-8') +script(src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js') +script(src='app.js') \ No newline at end of file diff --git a/includes/intro.jade b/includes/intro.jade new file mode 100644 index 00000000..5ec1245d --- /dev/null +++ b/includes/intro.jade @@ -0,0 +1,26 @@ +#boxes.clearfix + section#web-applications + h3 Web Applications + p. + Express is a minimal and flexible node.js web application framework, providing + a robust set of features for building single and multi-page, and hybrid web applications. + + section#apis + h3 APIs + p. + With a myriad of HTTP utility methods and Connect middleware at your + disposal, creating a robust user-friendly API is quick and easy. + + section#performance + h3 Performance + p. + Express provides a thin layer of features fundamental + to any web application, without obscuring features + that you know and love in node.js + + section#community + h3 Community + p. + Express has a vibrant community of over 100 users in the #express channel on freenode, + 1500+ subscribed to the mailing list, and over + 7000 watchers on GitHub. diff --git a/includes/logo.jade b/includes/logo.jade new file mode 100644 index 00000000..ff429367 --- /dev/null +++ b/includes/logo.jade @@ -0,0 +1,5 @@ +section#logo + span.express express3.0.0 + span.description + | web application framework for + a(href='http://nodejs.org') node \ No newline at end of file diff --git a/includes/menu.jade b/includes/menu.jade new file mode 100644 index 00000000..6065b2ce --- /dev/null +++ b/includes/menu.jade @@ -0,0 +1,13 @@ + +include mixins + +nav.clearfix + +item('/') Home + +item('/api.html') API Reference + +item('/guide.html') Guide + +item('/applications.html') Applications + +item('/community.html') Community + +item('/faq.html') FAQ + +#x +#y \ No newline at end of file diff --git a/includes/mixins.jade b/includes/mixins.jade new file mode 100644 index 00000000..74d79c78 --- /dev/null +++ b/includes/mixins.jade @@ -0,0 +1,13 @@ + +mixin item(url) + a(href=url, class=active == url ? 'active' : '') + block + +mixin js + pre.js + code + block + +mixin logo(name) + li + img(src='/images/apps/logos/#{name}.png') \ No newline at end of file diff --git a/index.jade b/index.jade new file mode 100644 index 00000000..4b84361f --- /dev/null +++ b/index.jade @@ -0,0 +1,19 @@ +!!! 5 +html + head + title Express - node.js web application framework + include includes/head + body + .bar + section#content + header + include includes/logo + active = '/' + include includes/menu + section#logos + .content + include includes/app-logos + section#intro + .content + include includes/intro + include includes/footer diff --git a/package.json b/package.json new file mode 100644 index 00000000..1fb646f7 --- /dev/null +++ b/package.json @@ -0,0 +1,8 @@ +{ + "name": "expressjs.com", + "private": true, + "version": "0.0.0", + "dependencies": { + "jade": "0.26.1" + } +} diff --git a/style.css b/style.css new file mode 100644 index 00000000..b0937a28 --- /dev/null +++ b/style.css @@ -0,0 +1,455 @@ + +/* general */ + +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +body { + font: 300 12px/1.5 "Open Sans", sans-serif; + margin: 0; + padding: 0; + color: #7B838A; +} + +h1, h2, h3 { + margin: 5px 0; + font-weight: normal; + color: #353535; + -webkit-font-smoothing: antialiased; +} + +p em { + font-weight: bold; + font-style: normal; + color: #353535; +} + +p { + margin: 5px 0; +} + +.inner { + margin-top: 100px; +} + +#content { + margin-left: 80px; + width: 900px; + margin-bottom: 80px; +} + +li code { + color: #353535; +} + +section section p { + width: 60%; +} + +h2 { + margin-top: 80px; + font-weight: bold; +} + +h3 { + background: url(images/hr.png) top center no-repeat; + margin-top: 50px; + padding-top: 50px; + padding-bottom: 5px; + font-weight: bold; +} + +/* links */ + +a { + color: #259dff; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +:target { + padding-top: 100px; +} + +nav a { + color: #7B838A; +} + +/* logo */ + +#logo { + margin-top: 180px; + margin-bottom: 180px; + margin-left: 80px; + padding-left: 40px; + width: 440px; + border-left: 1px dotted #eee; + -webkit-font-smoothing: antialiased; +} + +#logo .express { + display: block; + font: 400 60px "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #353535; + width: 100%; +} + +#logo .description { + position: relative; + top: -5px; + font: 100 60px "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #cecece; + line-height: .75; +} + +#logo em { + font-style: normal; + font-weight: 100; + font-size: 9px; + color: #cecece; + margin-left: 5px; +} + +#logo a { + color: #cecece; +} + +#logo a:hover { + text-decoration: none; + color: #858585; +} + +/* secondary page logo */ + +.inner header { + position: fixed; + top: 0; + left: 0; + background: rgba(255,255,255,.9); + width: 100%; + height: 55px; + z-index: 100; +} + +.inner.scroll header { + border-bottom: 1px solid #ddd; + box-shadow: 0 0 4px #eee; +} + +.inner #logo { + position: fixed; + top: 0; + margin: 0; + padding: 10px 25px; + width: auto; + border-left: none; +} + +.inner #logo .express { + font-size: 25px; +} + +.inner #logo em { + display: none; +} + +.inner .description { + display: none; +} + +/* code */ + +p code { + background: #efefef; + border: 1px solid #eaeaea; + font-family: monaco, monospace; + font-size: .75em; + padding: 2px 8px; + -webkit-border-radius: 3px; +} + +pre { + color: #353535; + font-size: 14px; + line-height: 1.4; + margin: 20px 0; + padding: 20px; + background: white; + border: 1px solid #e7e7e7; + border-bottom: 1px solid #ddd; + -webkit-box-shadow: 0 1px 3px 0 #eee; + -webkit-border-radius: 3px; +} + +pre code { + font-family: monaco, monospace; + font-size: .8em; +} + +code .comment { color: #888 } +code .init { color: #2F6FAD } +code .string { color: #5890AD } +code .keyword { color: #8A6343 } +code .number { color: #2F6FAD } + +/* top button */ + +.scroll #top { + opacity: .2; +} + +#top { + line-height: 0; + background: black; + -webkit-border-radius: 2px; + position: fixed; + bottom: 15px; + right: 15px; + padding: 8px; + text-decoration: none; + color: white; + opacity: 0; + -webkit-transition: opacity 300ms; +} + +#top:hover { + opacity: 1; +} + +#top img { + width: 8px; + height: 5px; +} + +/* navigation */ + +nav { + position: fixed; + top: 20px; + right: 15px; + z-index: 100; +} + +nav a { + margin: 0 5px; + padding-right: 15px; + border-right: 1px dotted #eee; +} + +nav a:last-child { + border-right: none; +} + +nav a.active { + font-weight: bold; + color: #353535; +} + +/* clearfix */ + +.clearfix:after { + content: "."; + display: block; + clear: both; + visibility: hidden; + line-height: 0; + height: 0; +} + +.clearfix { + display: inline-block; +} + +html[xmlns] .clearfix { + display: block; +} + +* html .clearfix { + height: 1%; +} + +/* boxes */ + +#boxes { + background: url(images/hr.png) top center no-repeat; + margin-left: 50px; + padding-top: 50px; + padding-bottom: 50px; +} + +#boxes section { + width: 180px; + margin: 0 25px; + float: left; +} + +#boxes h3 { + background: none; + margin-top: 0; + padding-top: 0; +} + +#boxes section p { + width: 100%; +} + +/* secondary menu */ + +#menu { + position: fixed; + margin: 0; + padding: 0; + top: 105px; + right: 30px; + height: 500px; + text-align: right; +} + +#menu li { + list-style: none; +} + +#menu ul { + height: 0; + overflow-y: hidden; +} + +#menu ul.active { + height: auto; +} + +#menu > li > a { + color: #353535; + font-weight: bold; +} + +#menu ul a { + color: #7B838A; +} + +#menu ul a.active { + color: #259dff; +} + +/* applications page */ + +.application h2 { + margin: 0; +} + +.application { + background: url(images/hr.png) top center no-repeat; + padding: 80px 0; + height: 600px; + position: relative; +} + +.application p { + float: left; + width: 30%; +} + +.application img { + float: right; +} + +.application .link { + position: absolute; + bottom: 15px; + left: 15px; +} + +/* ipad landscape */ + +@media all and (max-width: 1200px) { + #content { + width: 760px; + } + + .applications #content, + .community #content { + width: 900px; + } +} + +/* ipad portrait */ + +@media all and (max-width: 768px) { + #content { + width: 500px; + } + + .applications #content, + .community #content { + width: 600px; + } + + .application img { + width: 60%; + } + + .application { + height: 450px; + } + + #boxes { + margin-left: 0; + } + + #boxes section { + width: 100%; + margin-top: 20px; + margin-left: 0; + } +} + +/* iphone portrait */ + +@media all and (max-width: 650px) { + #logo { + margin-left: 0; + } + + #content { + width: 380px; + } + + .applications #content, + .community #content { + width: 500px; + } + + section section p { + width: 100%; + } + + .application { + height: 380px; + } + + .application img { + width: 60%; + } + + #boxes { + margin-left: 0; + } + + #boxes section { + width: 100%; + margin-top: 20px; + margin-left: 0; + } +} + +/* tmp */ + +#logos, footer { + display: none; +} \ No newline at end of file