Initial commit
[yaffs-website] / node_modules / tiny-lr / readme.md
1 # tiny-lr [![Build Status](https://travis-ci.org/mklabs/tiny-lr.svg?branch=master)](https://travis-ci.org/mklabs/tiny-lr)
2
3 This script manages a tiny [LiveReload](http://livereload.com/) server
4 implementation.
5
6 [![NPM](https://nodei.co/npm/tiny-lr.png?downloads=true&stars=true)](https://nodei.co/npm/tiny-lr/)
7
8 It exposes an HTTP server and express middleware, with a very basic REST
9 Api to notify the server of a particular change.
10
11 It doesn't have any watch ability, it must be done at the build process or
12 application level.
13
14 Instead, it exposes a very simple API to notify the server that some
15 changes have been made, then broadcasted to every livereload client
16 connected.
17
18     # notify a single change
19     curl http://localhost:35729/changed?files=style.css
20
21     # notify using a longer path
22     curl http://localhost:35729/changed?files=js/app.js
23
24     # notify multiple changes, comma or space delimited
25     curl http://localhost:35729/changed?files=index.html,style.css,docs/docco.css
26
27 Or you can bulk the information into a POST request, with body as a JSON array of files.
28
29     curl -X POST http://localhost:35729/changed -d '{ "files": ["style.css", "app.js"] }'
30
31     # from a JSON file
32     node -pe 'JSON.stringify({ files: ["some.css", "files.css"] })' > files.json
33     curl -X POST -d @files.json http://localhost:35729
34
35 As for the livereload client, you need to install the browser extension:
36 http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-
37 (**note**: you need to listen on port 35729 to be able to use with your
38 brower extension)
39
40 or add the livereload script tag manually:
41 http://feedback.livereload.com/knowledgebase/articles/86180-how-do-i-add-the-script-tag-manually-
42 (and here you can choose whatever port you want)
43
44 ## Integration
45
46 The best way to integrate the runner in your workflow is to add it as a `reload`
47 step within your build tool.
48
49 ```js
50 var tinylr = require('tiny-lr');
51
52 // standard LiveReload port
53 var port = 35729;
54
55 // tinylr(opts) => new tinylr.Server(opts);
56 tinylr().listen(port, function() {
57   console.log('... Listening on %s ...', port);
58 })
59 ```
60
61 You can define your own route and listen for specific request:
62
63 ```js
64 var server = tinylr();
65
66 server.on('GET /myplace', function(req, res) {
67   res.write('Mine');
68   res.end();
69 })
70 ```
71
72 And stop the server manually:
73
74 ```js
75 server.close();
76 ```
77
78 This will close any websocket connection established and emit a close event.
79
80 ### Middleware
81
82 To use as a connect / express middleware, tiny-lr needs query /
83 bodyParser middlewares prior in the stack (to handle POST requests)
84
85 Any handled requests ends at the tinylr level, not found and errors are
86 nexted to the rest of the stack.
87
88 ```js
89 var port = process.env.LR_PORT || process.env.PORT || 35729;
90
91 var path    = require('path');
92 var express = require('express');
93 var tinylr  = require('tiny-lr');
94 var body    = require('body-parser');
95
96 var app = express();
97
98 // This binds both express app and tinylr on the same port
99
100
101 app
102   .use(body())
103   .use(tinylr.middleware({ app: app }))
104   .use(express.static(path.resolve('./')))
105   .listen(port, function() {
106     console.log('listening on %d', port);
107   });
108 ```
109
110 The port you listen on is important, and tinylr should **always** listen on
111 the LiveReload standard one: `35729`. Otherwise, you won't be able to rely
112 on the browser extensions, though you can still use the manual snippet
113 approach.
114
115 You can also start two different servers, one on your app port, the
116 other listening on the LiveReload port.
117
118 ### Using grunt
119
120 Head over to [https://github.com/gruntjs/grunt-contrib-watch](https://github.com/gruntjs/grunt-contrib-watch#live-reloading)
121
122 ### Using make
123
124 See [make-livereload](https://github.com/mklabs/make-livereload) repo.
125 This repository defines a bin wrapper you can use and install with:
126
127     npm install make-livereload -g
128
129 It bundles the same bin wrapper previously used in tiny-lr repo.
130
131     Usage: tiny-lr [options]
132
133     Options:
134
135       -h, --help     output usage information
136       -V, --version  output the version number
137       port           -p
138       pid            Path to the generated PID file (default: ./tiny-lr.pid)
139
140 ### Using gulp
141
142 See [gulp-livereload](https://github.com/vohof/gulp-livereload) repo.
143
144 ## Options
145
146 - `livereload`    - Path to the client side lib (defaults to `path.join(__dirname, '../node_modules/livereload-js/dist/livereload.js')`)
147 - `port`          - Livereload port (defaults to `35729`)
148 - `errorListener` - A callback to invoke when an error occurs (otherwise, fallbacks to standard error output)
149 - `app`           - An express or other middleware based HTTP server
150 - `key`           - Option to pass in to create an https server
151 - `cert`          - Option to pass in to create an https server
152 - `pfx`           - Can also be used to create an https server instead of `key` & `cert`
153 - `liveCSS`       - LiveReload option to enable live CSS reloading (defaults to true)
154 - `liveJs`        - LiveReload option to enable live JS reloading (defaults to true)
155 - `liveImg`       - LiveReload option to enable live images reloading (defaults to true)
156
157 ## Tests
158
159     npm test
160
161 ---
162
163
164 # TOC
165    - [tiny-lr](#tiny-lr)
166      - [GET /](#tiny-lr-get-)
167      - [GET /changed](#tiny-lr-get-changed)
168      - [POST /changed](#tiny-lr-post-changed)
169      - [GET /livereload.js](#tiny-lr-get-livereloadjs)
170      - [GET /kill](#tiny-lr-get-kill)
171 <a name="" />
172
173 <a name="tiny-lr" />
174 # tiny-lr
175 accepts ws clients.
176
177 ```js
178 var url = parse(this.request.url);
179 var server = this.app;
180
181 var ws = this.ws = new WebSocket('ws://' + url.host + '/livereload');
182
183 ws.onopen = function(event) {
184   var hello = {
185     command: 'hello',
186     protocols: ['http://livereload.com/protocols/official-7']
187   };
188
189   ws.send(JSON.stringify(hello));
190 };
191
192 ws.onmessage = function(event) {
193   assert.deepEqual(event.data, JSON.stringify({
194     command: 'hello',
195     protocols: ['http://livereload.com/protocols/official-7'],
196     serverName: 'tiny-lr'
197   }));
198
199   assert.ok(Object.keys(server.clients).length);
200   done();
201 };
202 ```
203
204 properly cleans up established connection on exit.
205
206 ```js
207 var ws = this.ws;
208
209 ws.onclose = done.bind(null, null);
210
211 request(this.server)
212   .get('/kill')
213   .expect(200, function() {
214     console.log('server shutdown');
215   });
216 ```
217
218 <a name="tiny-lr" />
219 # tiny-lr
220 <a name="tiny-lr-get-" />
221 ## GET /
222 respond with nothing, but respond.
223
224 ```js
225 request(this.server)
226   .get('/')
227   .expect('Content-Type', /json/)
228   .expect('{"tinylr":"Welcome","version":"0.0.1"}')
229   .expect(200, done);
230 ```
231
232 unknown route respond with proper 404 and error message.
233
234 ```js
235 request(this.server)
236   .get('/whatev')
237   .expect('Content-Type', /json/)
238   .expect('{"error":"not_found","reason":"no such route"}')
239   .expect(404, done);
240 ```
241
242 <a name="tiny-lr-get-changed" />
243 ## GET /changed
244 with no clients, no files.
245
246 ```js
247 request(this.server)
248   .get('/changed')
249   .expect('Content-Type', /json/)
250   .expect(/"clients":\[\]/)
251   .expect(/"files":\[\]/)
252   .expect(200, done);
253 ```
254
255 with no clients, some files.
256
257 ```js
258 request(this.server)
259   .get('/changed?files=gonna.css,test.css,it.css')
260   .expect('Content-Type', /json/)
261   .expect('{"clients":[],"files":["gonna.css","test.css","it.css"]}')
262   .expect(200, done);
263 ```
264
265 <a name="tiny-lr-post-changed" />
266 ## POST /changed
267 with no clients, no files.
268
269 ```js
270 request(this.server)
271   .post('/changed')
272   .expect('Content-Type', /json/)
273   .expect(/"clients":\[\]/)
274   .expect(/"files":\[\]/)
275   .expect(200, done);
276 ```
277
278 with no clients, some files.
279
280 ```js
281 var data = { clients: [], files: ['cat.css', 'sed.css', 'ack.js'] };
282
283 request(this.server)
284   .post('/changed')
285   .send({ files: data.files })
286   .expect('Content-Type', /json/)
287   .expect(JSON.stringify(data))
288   .expect(200, done);
289 ```
290
291 <a name="tiny-lr-get-livereloadjs" />
292 ## GET /livereload.js
293 respond with livereload script.
294
295 ```js
296 request(this.server)
297   .get('/livereload.js')
298   .expect(/LiveReload/)
299   .expect(200, done);
300 ```
301
302 <a name="tiny-lr-get-kill" />
303 ## GET /kill
304 shutdown the server.
305
306 ```js
307 var server = this.server;
308 request(server)
309   .get('/kill')
310   .expect(200, function(err) {
311     if(err) return done(err);
312     assert.ok(!server._handle);
313     done();
314   });
315 ```
316
317 ## Thanks!
318
319 - Tiny-lr is a [LiveReload](http://livereload.com/) implementation. They
320   really made frontend editing better for a lot of us. They have a
321   [LiveReload App on the Mac App Store](https://itunes.apple.com/us/app/livereload/id482898991)
322   you might want to check out.
323
324 - To all [contributors](https://github.com/mklabs/tiny-lr/graphs/contributors)
325
326 - [@FGRibreau](https://github.com/FGRibreau) / [pid.js
327   gist](https://gist.github.com/1846952)) for the background friendly
328 bin wrapper, used in [make-livereload](https://github.com/mklabs/make-livereload)