1 | # Dgeni - Documentation Generator [![Build Status](https://travis-ci.org/angular/dgeni.svg?branch=master)](https://travis-ci.org/angular/dgeni)
|
2 |
|
3 | ![](assets/dgeni-logo-600x400.png)
|
4 |
|
5 | The node.js documentation generation utility by angular.js and other projects.
|
6 |
|
7 | Dgeni is pronounced like the girl name Jenny ([/ˈdʒɛni/](https://en.wikipedia.org/wiki/Help:IPA_for_English)),
|
8 | i.e the `d` is silent and the `g` is soft.
|
9 |
|
10 | ## Getting started
|
11 |
|
12 | Try out the Dgeni [example project](https://github.com/petebacondarwin/dgeni-example). Or maybe you're looking for an example [using AngularJS](https://github.com/petebacondarwin/dgeni-angular).
|
13 |
|
14 | Watch Pete's ng-europe talk on Dgeni :
|
15 |
|
16 | [![ScreenShot](http://img.youtube.com/vi/PQNROxXajyQ/0.jpg)](http://youtu.be/PQNROxXajyQ)
|
17 |
|
18 |
|
19 | ## Documenting AngularJS Apps
|
20 |
|
21 | There are two projects out there that build upon dgeni to help create documentation for AngularJS apps:
|
22 |
|
23 | * dgeni-alive: https://github.com/wingedfox/dgeni-alive
|
24 | * sia: https://github.com/boundstate/sia
|
25 |
|
26 | Do check them out and thanks to [Ilya](https://github.com/wingedfox) and [Bound State Software](https://github.com/boundstate)
|
27 | for putting these projects together.
|
28 |
|
29 | ## Installation
|
30 |
|
31 | You'll need node.js and a bunch of npm modules installed to use Dgeni. Get node.js from here:
|
32 | http://nodejs.org/.
|
33 |
|
34 | In the project you want to document you install Dgeni by running:
|
35 |
|
36 | ```
|
37 | npm install dgeni --save-dev
|
38 | ```
|
39 |
|
40 | This will install Dgeni and any modules that Dgeni depends upon.
|
41 |
|
42 |
|
43 | ## Running Dgeni
|
44 |
|
45 | Dgeni on its own doesn't do much. You must configure it with **Packages** that contain **Services**
|
46 | and **Processors**. It is the **Processors** that actually convert your source files to
|
47 | documentation files.
|
48 |
|
49 | To run the processors we create a new instance of `Dgeni`, providing to it an array of **Packages**
|
50 | to load. Then simply call the `generate()` method on this instance. The `generate()` method runs the
|
51 | processors asynchronously and returns a **Promise** that gets fulfilled with the generated documents.
|
52 |
|
53 | ```js
|
54 | var Dgeni = require('dgeni');
|
55 |
|
56 | var packages = [require('./myPackage')];
|
57 |
|
58 | var dgeni = new Dgeni(packages);
|
59 |
|
60 | dgeni.generate().then(function(docs) {
|
61 | console.log(docs.length, 'docs generated');
|
62 | });
|
63 | ```
|
64 |
|
65 | ### Running from the Command Line
|
66 |
|
67 | Dgeni is normally used from a build tool such as Gulp or Grunt but it does also come with a
|
68 | command line tool.
|
69 |
|
70 | If you install Dgeni globally then you can run it from anywhere:
|
71 |
|
72 | ```bash
|
73 | npm install -g dgeni
|
74 | dgeni some/package.js
|
75 | ```
|
76 |
|
77 | If Dgeni is only installed locally then you either have to specify the path explicitly:
|
78 |
|
79 | ```bash
|
80 | npm install dgeni
|
81 | node_modules/.bin/dgeni some/package.js
|
82 | ```
|
83 |
|
84 | or you can run the tool in an npm script:
|
85 |
|
86 | ```js
|
87 | {
|
88 | ...
|
89 | scripts: {
|
90 | docs: 'dgeni some/package.js'
|
91 | }
|
92 | ...
|
93 | }
|
94 | ```
|
95 |
|
96 |
|
97 | The usage is:
|
98 |
|
99 |
|
100 | ```bash
|
101 | dgeni path/to/mainPackage [path/to/other/packages ...] [--log level]
|
102 | ```
|
103 |
|
104 | You must provide the path to one or more Dgeni Packages to load. You can, optionally, set
|
105 | the logging level.
|
106 |
|
107 |
|
108 | ## Packages
|
109 |
|
110 | **Services**, **Processors**, configuration values and templates are be bundled into a `Package`. Packages
|
111 | can depend upon other Packages. In this way you can build up your custom configuration on
|
112 | top of an existing configuration.
|
113 |
|
114 | ### Defining a Package
|
115 |
|
116 | Dgeni provides a `Package` constructor to create new Packages. A Package instance has methods to register **Services** and
|
117 | **Processors**, and to configure the properties of **Processors**:
|
118 |
|
119 | ```js
|
120 | var Package = require('dgeni').Package;
|
121 | var myPackage = new Package('myPackage', ['packageDepencency1', 'packageDependency2']);
|
122 |
|
123 | myPackage.processor(require('./processors/processor1'));
|
124 | myPackage.processor(require('./processors/processor2'));
|
125 |
|
126 | myPackage.factory(require('./services/service1'));
|
127 | myPackage.factory(require('./services/service2'));
|
128 |
|
129 | myPackage.config(function(processor1, service2) {
|
130 | service2.someProperty = 'some value';
|
131 | processor1.specialService = service2;
|
132 | });
|
133 | ```
|
134 |
|
135 |
|
136 | ## Services
|
137 |
|
138 | Dgeni makes significant use of **Dependency Injection (DI)** to instantiate objects. Objects that
|
139 | will be instantiated by the DI system must be provided by a **factory function**, which is registered
|
140 | in a **Package**, either as a **Processor**, by `myPackage.processor(factoryFn)`, or as a **Service**,
|
141 | by `myPackage.factory(factoryFn)`.
|
142 |
|
143 | ### Defining a Service
|
144 |
|
145 | The parameters to a factory function are dependencies on other services that the DI system must find
|
146 | or instantiate and provide to the factory function.
|
147 |
|
148 | **car.js**:
|
149 | ```js
|
150 | module.exports = function car(engine, wheels) {
|
151 | return {
|
152 | drive: function() {
|
153 | engine.start();
|
154 | wheels.turn();
|
155 | }
|
156 | };
|
157 | };
|
158 | ```
|
159 |
|
160 | Here we have defined a `car` service, which depends upon two other services, `engine` and `wheels`
|
161 | defined elsewhere. Note that this `car` service doesn't care how and where these dependencies are
|
162 | defined. It relies on the DI system to provide them when needed.
|
163 |
|
164 | The `car` service returned by the factory function is an object containing one method, `drive()`,
|
165 | which in turn calls methods on `engine` and `wheels`.
|
166 |
|
167 |
|
168 | ### Registering a Service
|
169 |
|
170 | You then register the Service with a Package:
|
171 |
|
172 | **myPackage.js**:
|
173 | ```jsv
|
174 | var Package = require('dgeni').Package;
|
175 |
|
176 | module.exports = new Package('myPackage')
|
177 | .factory(require('./car'));
|
178 | ```
|
179 |
|
180 | This car Service is then available to any other Service, Processor or configuration block:
|
181 |
|
182 | ```js
|
183 | var Package = require('dgeni').Package;
|
184 |
|
185 | module.exports = new Package('greenTaxiPackage', ['myPackage'])
|
186 |
|
187 | .factory(function taxi(car) {
|
188 | return {
|
189 | orderTaxi: function(place) { car.driveTo(place); }
|
190 | };
|
191 | })
|
192 |
|
193 | .config(function(car) {
|
194 | car.fuel = 'hybrid';
|
195 | });
|
196 | ```
|
197 |
|
198 |
|
199 | ## Processors
|
200 |
|
201 | **Processors** are **Services** that contain a `$process(docs)` method. The processors are run
|
202 | one after another in a pipeline. Each Processor takes the collection documents from the previous
|
203 | Processor and manipulates it, maybe inserting new documents or adding meta data to documents that are
|
204 | there already.
|
205 |
|
206 | Processors can expose properties that tell Dgeni where in the pipeline they should be run and
|
207 | how to validate the configuration of the Processor.
|
208 |
|
209 | * `$enabled` - if set to `false` then this Processor will not be included in the pipeline
|
210 | * `$runAfter` - an array of strings, where each string is the name of a Processor that must appear
|
211 | **earlier** in the pipeline than this Processor
|
212 | * `$runBefore` - an array of strings, where each string is the name of a Processor that must appear
|
213 | **later** in the pipeline than this one
|
214 | * `$validate` - a [http://validatejs.org/](http://validatejs.org/) constraint object that Dgeni uses
|
215 | to validate the properties of this Processor.
|
216 |
|
217 |
|
218 | **Note that the validation feature has been moved to its own Dgeni Package `processorValidation`.
|
219 | Currently dgeni automatically adds this new package to a new instance of dgeni so that is still available
|
220 | for backward compatibility. In a future release this package will be moved to `dgeni-packages`.**
|
221 |
|
222 | ### Defining a Processor
|
223 |
|
224 | You define Processors just like you would a Service:
|
225 |
|
226 | **myDocProcessor.js**:
|
227 | ```js
|
228 | module.exports = function myDocProcessor(dependency1, dependency2) {
|
229 | return {
|
230 | $process: function (docs) {
|
231 | //... do stuff with the docs ...
|
232 | },
|
233 | $runAfter: ['otherProcessor1'],
|
234 | $runBefore: ['otherProcessor2', 'otherProcessor3'],
|
235 | $validate: {
|
236 | myProperty: { presence: true }
|
237 | },
|
238 | myProperty: 'some config value'
|
239 | };
|
240 | };
|
241 | ```
|
242 |
|
243 |
|
244 | ### Registering a Processor
|
245 |
|
246 | You then register the Processor with a Package:
|
247 | **myPackage.js**:
|
248 | ```jsv
|
249 | var Package = require('dgeni').Package;
|
250 |
|
251 | module.exports = new Package('myPackage')
|
252 | .processor(require('./myDocProcessor'));
|
253 | ```
|
254 |
|
255 | ### Asynchronous Processing
|
256 |
|
257 | The `$process(docs)` method can be synchronous or asynchronous:
|
258 |
|
259 | * If synchronous then it should return `undefined` or a new array of documents.
|
260 | If it returns a new array of docs then this array will replace the previous `docs` array.
|
261 | * If asynchronous then it must return a **Promise**, which should resolve to `undefined`
|
262 | or a new collection of documents. By returning a **Promise**, the processor tells Dgeni
|
263 | that it is asynchronous and Dgeni will wait for the promise to resolve before calling the
|
264 | next processor.
|
265 |
|
266 |
|
267 | Here is an example of an asynchronous **Processor**
|
268 | ```js
|
269 | var qfs = require('q-io/fs');
|
270 | module.exports = function readFileProcessor() {
|
271 | return {
|
272 | filePath: 'some/file.js',
|
273 | $process(docs) {
|
274 | return qfs.readFile(this.filePath).then(function(response) {
|
275 | docs.push(response.data);
|
276 | });
|
277 | }
|
278 | };
|
279 | ```
|
280 |
|
281 | ### Standard Dgeni Packages
|
282 |
|
283 | The [dgeni-packages repository](https://github.com/angular/dgeni-packages) contains many Processors -
|
284 | from basic essentials to complex, angular.js specific. These processors are grouped into Packages:
|
285 |
|
286 | * `base` - contains the basic file reading and writing Processors as well as an abstract
|
287 | rendering Processor.
|
288 |
|
289 | * `jsdoc` - depends upon `base` and adds Processors and Services to support parsing and
|
290 | extracting jsdoc style tags from comments in code.
|
291 |
|
292 | * `typescript` - depends upon `base` and adds Processors and Services to support parsing and
|
293 | extracting jsdoc style tags from comments in TypeScript (*.ts) code.
|
294 |
|
295 | * `nunjucks` - provides a [nunjucks](http://mozilla.github.io/nunjucks/) based rendering
|
296 | engine.
|
297 |
|
298 | * `ngdoc` - depends upon `jsdoc` and `nunjucks` and adds additional processing for the
|
299 | AngularJS extensions to jsdoc.
|
300 |
|
301 | * `examples` - depends upon `jsdoc` and provides Processors for extracting examples from jsdoc
|
302 | comments and converting them to files that can be run.
|
303 |
|
304 | * `dgeni` - support for documenting dgeni Packages.
|
305 |
|
306 |
|
307 | ### Pseudo Marker Processors
|
308 |
|
309 | You can define processors that don't do anything but act as markers for stages of the
|
310 | processing. You can use these markers in `$runBefore` and `$runAfter` properties to ensure
|
311 | that your Processor is run at the right time.
|
312 |
|
313 | The **Packages** in dgeni-packages define some of these marker processors. Here is a list
|
314 | of these in the order that Dgeni will add them to the processing pipeline:
|
315 |
|
316 |
|
317 | * reading-files *(defined in base)*
|
318 | * files-read *(defined in base)*
|
319 | * parsing-tags *(defined in jsdoc)*
|
320 | * tags-parsed *(defined in jsdoc)*
|
321 | * extracting-tags *(defined in jsdoc)*
|
322 | * tags-extracted *(defined in jsdoc)*
|
323 | * processing-docs *(defined in base)*
|
324 | * docs-processed *(defined in base)*
|
325 | * adding-extra-docs *(defined in base)*
|
326 | * extra-docs-added *(defined in base)*
|
327 | * computing-ids *(defined in base)*
|
328 | * ids-computed *(defined in base)*
|
329 | * computing-paths *(defined in base)*
|
330 | * paths-computed *(defined in base)*
|
331 | * rendering-docs *(defined in base)*
|
332 | * docs-rendered *(defined in base)*
|
333 | * writing-files *(defined in base)*
|
334 | * files-written *(defined in base)*
|
335 |
|
336 |
|
337 | ## Configuration Blocks
|
338 |
|
339 | You can configure the **Services** and **Processors** defined in a **Package** or its dependencies
|
340 | by registering **Configuration Blocks** with the **Package**. These are functions that can be
|
341 | injected with **Services** and **Processors** by the DI system, giving you the opportunity to
|
342 | set properties on them.
|
343 |
|
344 |
|
345 | ### Registering a Configuration Block
|
346 |
|
347 | You register a **Configuration Block** by calling `config(configFn)` on a Package.
|
348 |
|
349 | ```js
|
350 | myPackage.config(function(readFilesProcessor) {
|
351 | readFilesProcessor.sourceFiles = ['src/**/*.js'];
|
352 | });
|
353 | ```
|
354 |
|
355 | ## Dgeni Events
|
356 |
|
357 | In Dgeni you can trigger and handle **events** to allow packages to take part in the processing
|
358 | lifecycle of the documentation generation.
|
359 |
|
360 |
|
361 | ### Triggering Events
|
362 |
|
363 | You trigger an event simply by calling `triggerEvent(eventName, ...)` on a `Dgeni` instance.
|
364 |
|
365 | The `eventName` is a string that identifies the event to be triggered, which is used to wire up
|
366 | event handlers. Additional arguments are passed through to the handlers.
|
367 |
|
368 | Each handler that is registered for the event is called in series. The return value
|
369 | from the call is a promise to the event being handled. This allows event handlers to be async.
|
370 | If any handler returns a rejected promise the event triggering is cancelled and the rejected
|
371 | promise is returned.
|
372 |
|
373 | For example:
|
374 |
|
375 | ```js
|
376 | var eventPromise = dgeni.triggerEvent('someEventName', someArg, otherArg);
|
377 | ```
|
378 |
|
379 | ### Handling Events
|
380 |
|
381 | You register an event handler in a `Package`, by calling `handleEvent(eventName, handlerFactory)` on
|
382 | the package instance. The handlerFactory will be used by the DI system to get the handler, which allows
|
383 | you to inject services to be available to the handler.
|
384 |
|
385 | The handler factory should return the handler function. This function will receive all the arguments passed
|
386 | to the `triggerHandler` method. As a minimum this will include the `eventName`.
|
387 |
|
388 | For example:
|
389 |
|
390 | ```js
|
391 | myPackage.eventHandler('generationStart', function validateProcessors(log, dgeni) {
|
392 | return function validateProcessorsImpl(eventName) {
|
393 | ...
|
394 | };
|
395 | });
|
396 |
|
397 | ```
|
398 |
|
399 | ### Built-in Events
|
400 |
|
401 | Dgeni itself triggers the following events during documentation generation:
|
402 |
|
403 | * `generationStart`: triggered after the injector has been configured and before the processors begin
|
404 | their work.
|
405 | * `generationEnd`: triggered after the processors have all completed their work successfully.
|
406 | * `processorStart`: triggered just before the call to `$process`, for each processor.
|
407 | * `processorEnd`: triggered just after `$process` has completed successfully, for each processor.
|
408 |
|
409 | ## License
|
410 |
|
411 | Apache 2
|