1 | # Coffee Toaster (current version - 0.3.8)
|
2 |
|
3 | Minimalist dependency management system for CoffeeScript.
|
4 |
|
5 | # Features
|
6 |
|
7 | * Inheritance support across multiples files for the lazy
|
8 | * Vendors management
|
9 | * Multi modules support in the same environment
|
10 | * Micro build routines across all modules
|
11 | * Namespaces
|
12 | * Automagic packaging system that uses folders as namespaces
|
13 | * Scaffolding routines
|
14 | * Interactive creation of a very simple skeleton for new projects and config file for existent projects
|
15 | * Broken and circular-loop dependency validation
|
16 | * Helps you prevent some mistakes with circular dependencies loops and alert you against dependencies not found
|
17 | * Live syntax-check
|
18 | * Precise live syntax-check with file path and line number information
|
19 | * Debug Mode
|
20 | * In order to provide easy debugging when inside the browser, Debug Mode will compile all your files individually into its respectives .js versions and write a smart boot-loader (toaster.js) to load every file in the proper order. Just include this boot-loader in your html file and voilà
|
21 |
|
22 |
|
23 | # Installation
|
24 |
|
25 | npm install -g coffee-toaster
|
26 |
|
27 | # Usage
|
28 |
|
29 | ## Creating a new App
|
30 |
|
31 | CoffeeToaster suggests a very simple structure for initial projects, you can customize it as you like.
|
32 |
|
33 | toaster -n mynewapp
|
34 |
|
35 | You will be asked for some things:
|
36 |
|
37 | 1. **name** - The name of your main module.
|
38 | * i.e.: mynewapp
|
39 | 1. **src** - The source folder for your main module, it can be relative or absolute.
|
40 | * i.e.: src
|
41 | 1. **release** - The release file for your main module, can be relative or absolute.
|
42 | * i.e.: release/app.js
|
43 |
|
44 | Considering all the default values, you'll end up with a structure like this:
|
45 |
|
46 | ├── /mynewapp
|
47 | ├── /release
|
48 | ├── /src
|
49 | └── toaster.coffee
|
50 |
|
51 | The toaster.coffee file will have this content:
|
52 |
|
53 | ````ruby
|
54 | module 'mynewapp'
|
55 | src: 'src'
|
56 | release: 'release/app.js'
|
57 | ````
|
58 |
|
59 |
|
60 | ## Toasting an existing project
|
61 |
|
62 | Your can toast an existent project like this:
|
63 |
|
64 | cd existing-project
|
65 | toaster -i
|
66 |
|
67 | Or:
|
68 |
|
69 | toaster -i existing-project
|
70 |
|
71 | The same questions (name, src, release) will be made, answer everything according your project structure.
|
72 |
|
73 | A 'toaster.coffee' file will be created inside it.
|
74 |
|
75 | ## When the magic happens
|
76 |
|
77 | To see all CoffeeToaster can do for you, after creating or toasting a new project, enter in the project folder and type 'toaster -w':
|
78 |
|
79 | cd existing-project
|
80 | toaster -w
|
81 |
|
82 | Or:
|
83 |
|
84 | toaster -w existing-project
|
85 |
|
86 | # Debug Mode
|
87 |
|
88 | In debug mode (option -d) files will be all compiled individually inside a folder called "toaster" in the same directory you have your release file, aiming to ease the debugging process.
|
89 |
|
90 | For example, if you have "release/app.js", a folder will be created in "release/toaster" and all your CoffeeScript files will be compiled to Javascript inside it.
|
91 |
|
92 | Bellow is a directory structure representing this:
|
93 |
|
94 | ├── release
|
95 | │ ├── app.js
|
96 | │ ├── index.html
|
97 | │ └── toaster
|
98 | │ ├── src
|
99 | │ │ ├── app.js
|
100 | │ │ ├── letters
|
101 | │ │ │ ├── a.js
|
102 | │ │ │ └── b.js
|
103 | │ │ ├── repeating
|
104 | │ │ │ └── a.js
|
105 | │ │ └── single
|
106 | │ │ └── script.js
|
107 | │ └── toaster.js
|
108 | ├── src
|
109 | │ ├── app.coffee
|
110 | │ ├── letters
|
111 | │ │ ├── a.coffee
|
112 | │ │ └── b.coffee
|
113 | │ ├── repeating
|
114 | │ │ └── a.coffee
|
115 | │ └── single
|
116 | │ └── script.coffee
|
117 | └── toaster.coffee
|
118 |
|
119 | There's also a 'toaster.js' file inside the 'release/toaster' folder, this Javascript file is responsible to load all your files into the right order.
|
120 |
|
121 | So in your .html your have two options:
|
122 |
|
123 | **1)** Include your release file (release/app.js)
|
124 |
|
125 | ````html
|
126 | <script src="app.js"></script>
|
127 | ````
|
128 |
|
129 | **2)** Include the toaster boot-loader (release/toaster/toaster.js)
|
130 |
|
131 | ````html
|
132 | <script src="toaster/toaster.js"></script>
|
133 | ````
|
134 |
|
135 |
|
136 | # How everything works?
|
137 |
|
138 | CoffeeToaster will write a file called 'toaster.coffee' in your app main folder.
|
139 |
|
140 | ## Config File (toaster.coffee)
|
141 |
|
142 | This file contains informations about the modules you have in your app, i.e:
|
143 |
|
144 | ````ruby
|
145 | module "My Awesome App"
|
146 | src: "src"
|
147 | release: "release/app.js"
|
148 | ````
|
149 |
|
150 | So when you call 'toaster -w' inside this directory, this config is loaded and every file and folder inside src folder start being watched.
|
151 |
|
152 | If debug is enabled (option -d), files will also compiled individually for a sane debugging routine, inside the browser.
|
153 |
|
154 | Every time something changes, CoffeeToaster re-compiles all your application by doing:
|
155 |
|
156 | * collects all .coffee files and process everything, adding package declarations to the class definitions, based on the folder they are
|
157 | * re-order everything so files and classes are defined always before they are needed
|
158 |
|
159 | Wait! How the hell it knows when my files or classes are needed?
|
160 |
|
161 | ## Import directive
|
162 |
|
163 | The import directive is known by:
|
164 |
|
165 | * #<< core/views/View
|
166 | * #<< utils/*
|
167 |
|
168 | By putting '#<< package/name/View' in your CoffeeScript file, you're telling CoffeeToaster about a dependency.
|
169 |
|
170 | Wild cards '#<< utils/*' are also accepted as a handy option.
|
171 |
|
172 | ## Example - Structure
|
173 |
|
174 | Let's assume you have this structure:
|
175 |
|
176 | ├── release
|
177 | │ ├── app.js
|
178 | │ ├── index.html
|
179 | ├── src
|
180 | │ ├── app.coffee
|
181 | │ ├── letters
|
182 | │ │ ├── a.coffee
|
183 | │ │ └── b.coffee
|
184 | │ ├── repeating
|
185 | │ │ ├── a.coffee
|
186 | │ ├── single
|
187 | │ │ └── script.coffee
|
188 | └── toaster.coffee
|
189 |
|
190 | ## Example - Contents
|
191 |
|
192 | And every file with the following contents:
|
193 |
|
194 | * **path:** letters/a.coffee
|
195 |
|
196 | ````ruby
|
197 | class A
|
198 | constructor:-> console.log "letters/A created!"
|
199 | ````
|
200 |
|
201 | * **path:** letters/b.coffee
|
202 |
|
203 | ````ruby
|
204 | class B
|
205 | constructor:-> console.log "letters/B created!"
|
206 | ````
|
207 |
|
208 | * **path:** repeating/a.coffee
|
209 |
|
210 | ````ruby
|
211 | class A
|
212 | constructor:-> console.log "repeating/A created!"
|
213 | ````
|
214 |
|
215 | * **path:** single/script.coffee
|
216 |
|
217 | ````ruby
|
218 | console.log "I am a script!"
|
219 | ````
|
220 |
|
221 | * **path:** app.coffee
|
222 |
|
223 | ````ruby
|
224 | #<< letters/*
|
225 | #<< repeating/a
|
226 | #<< single/script
|
227 |
|
228 | class App
|
229 | constructor:->
|
230 | console.log "App created!"
|
231 |
|
232 | new letters.A
|
233 | new letters.B
|
234 | new repeating.A
|
235 |
|
236 | new App
|
237 | ````
|
238 |
|
239 | ## Example - Merge Result (still CoffeeScript)
|
240 |
|
241 | This way, everything will be merged like this:
|
242 |
|
243 | ````ruby
|
244 | letters = {}
|
245 | repeating = {}
|
246 | single = {}
|
247 |
|
248 | pkg = ( ns )->
|
249 | curr = null
|
250 | parts = [].concat = ns.split( "." )
|
251 | for part, index in parts
|
252 | if curr == null
|
253 | curr = eval part
|
254 | continue
|
255 | else
|
256 | unless curr[ part ]?
|
257 | curr = curr[ part ] = {}
|
258 | else
|
259 | curr = curr[ part ]
|
260 | curr
|
261 |
|
262 | pkg( 'letters' ).A = class A
|
263 | constructor:-> console.log "letters/A created!"
|
264 |
|
265 | pkg( 'letters' ).B = class B
|
266 | constructor:-> console.log "letters/B created!"
|
267 |
|
268 | pkg( 'repeating' ).A = class A
|
269 | constructor:-> console.log "repeating/A created!"
|
270 |
|
271 | console.log "I am a simple script!"
|
272 |
|
273 | class App
|
274 | constructor:->
|
275 | console.log "App created!"
|
276 |
|
277 | new letters.A
|
278 | new letters.B
|
279 | new repeating.A
|
280 |
|
281 | new App
|
282 | ````
|
283 |
|
284 | Toaster will initialize your root namespaces and add a 'pkg' method, to make everything works as intended.
|
285 |
|
286 | ## Example - Output (JavaScript)
|
287 |
|
288 | The output JavaScript compiled after reordering files and classes will be something like this:
|
289 |
|
290 | ````javascript
|
291 | (function() {
|
292 | var A, App, B, letters, pkg, repeating, single;
|
293 | letters = {};
|
294 | repeating = {};
|
295 | single = {};
|
296 | pkg = function(ns) {
|
297 | var curr, index, part, parts, _len;
|
298 | curr = null;
|
299 | parts = [].concat = ns.split(".");
|
300 | for (index = 0, _len = parts.length; index < _len; index++) {
|
301 | part = parts[index];
|
302 | if (curr === null) {
|
303 | curr = eval(part);
|
304 | continue;
|
305 | } else {
|
306 | if (curr[part] == null) {
|
307 | curr = curr[part] = {};
|
308 | } else {
|
309 | curr = curr[part];
|
310 | }
|
311 | }
|
312 | }
|
313 | return curr;
|
314 | };
|
315 | pkg('letters').A = A = (function() {
|
316 | function A() {
|
317 | console.log("letters/A created!");
|
318 | }
|
319 | return A;
|
320 | })();
|
321 | pkg('letters').B = B = (function() {
|
322 | function B() {
|
323 | console.log("letters/B created!");
|
324 | }
|
325 | return B;
|
326 | })();
|
327 | pkg('repeating').A = A = (function() {
|
328 | function A() {
|
329 | console.log("repeating/A created!");
|
330 | }
|
331 | return A;
|
332 | })();
|
333 | console.log("I am a simple script!");
|
334 | App = (function() {
|
335 | function App() {
|
336 | console.log("App created!");
|
337 | new letters.A;
|
338 | new letters.B;
|
339 | new repeating.A;
|
340 | }
|
341 | return App;
|
342 | })();
|
343 | new App;
|
344 | }).call(this);
|
345 | ````
|
346 | As you can see things are ordered properly.
|
347 |
|
348 | ## Example - Log
|
349 |
|
350 | Executing the above script in the browser I got this log msgs:
|
351 |
|
352 | I am a simple script!
|
353 | App created!
|
354 | letters/A created!
|
355 | letters/B created!
|
356 | repeating/A created!
|
357 |
|
358 | # Example - more
|
359 |
|
360 | You can find another example right into the [examples](http://github.com/serpentem/coffee-toaster/blob/master/examples) folder.
|
361 |
|
362 | # Multiple Modules
|
363 |
|
364 | You can also specify multiple modules lilke:
|
365 |
|
366 | ````ruby
|
367 | module "my-awesome-module"
|
368 | src: "src"
|
369 | release: "release/module.js"
|
370 |
|
371 | module "my-super-awesome-module"
|
372 | src: "super_src"
|
373 | release: "release/super_module.js"
|
374 | ````
|
375 |
|
376 | # Changelog
|
377 |
|
378 | Please check the [CHANGELOG.md](http://github.com/serpentem/coffee-toaster/blob/master/build/CHANGELOG.md)
|
379 |
|
380 | # Mailing List
|
381 |
|
382 | A place to talk about it.
|
383 |
|
384 | https://groups.google.com/group/coffee-toaster |
\ | No newline at end of file |