UNPKG

13.3 kBMarkdownView Raw
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
5The node.js documentation generation utility by angular.js and other projects.
6
7Dgeni is pronounced like the girl name Jenny ([/ˈdʒɛni/](https://en.wikipedia.org/wiki/Help:IPA_for_English)),
8i.e the `d` is silent and the `g` is soft.
9
10## Getting started
11
12Try 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
14Watch 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
21There 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
26Do check them out and thanks to [Ilya](https://github.com/wingedfox) and [Bound State Software](https://github.com/boundstate)
27for putting these projects together.
28
29## Installation
30
31You'll need node.js and a bunch of npm modules installed to use Dgeni. Get node.js from here:
32http://nodejs.org/.
33
34In the project you want to document you install Dgeni by running:
35
36```
37npm install dgeni --save-dev
38```
39
40This will install Dgeni and any modules that Dgeni depends upon.
41
42
43## Running Dgeni
44
45Dgeni on its own doesn't do much. You must configure it with **Packages** that contain **Services**
46and **Processors**. It is the **Processors** that actually convert your source files to
47documentation files.
48
49To run the processors we create a new instance of `Dgeni`, providing to it an array of **Packages**
50to load. Then simply call the `generate()` method on this instance. The `generate()` method runs the
51processors asynchronously and returns a **Promise** that gets fulfilled with the generated documents.
52
53```js
54var Dgeni = require('dgeni');
55
56var packages = [require('./myPackage')];
57
58var dgeni = new Dgeni(packages);
59
60dgeni.generate().then(function(docs) {
61 console.log(docs.length, 'docs generated');
62});
63```
64
65### Running from the Command Line
66
67Dgeni is normally used from a build tool such as Gulp or Grunt but it does also come with a
68command line tool.
69
70If you install Dgeni globally then you can run it from anywhere:
71
72```bash
73npm install -g dgeni
74dgeni some/package.js
75```
76
77If Dgeni is only installed locally then you either have to specify the path explicitly:
78
79```bash
80npm install dgeni
81node_modules/.bin/dgeni some/package.js
82```
83
84or 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
97The usage is:
98
99
100```bash
101dgeni path/to/mainPackage [path/to/other/packages ...] [--log level]
102```
103
104You must provide the path to one or more Dgeni Packages to load. You can, optionally, set
105the logging level.
106
107
108## Packages
109
110**Services**, **Processors**, configuration values and templates are be bundled into a `Package`. Packages
111can depend upon other Packages. In this way you can build up your custom configuration on
112top of an existing configuration.
113
114### Defining a Package
115
116Dgeni 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
120var Package = require('dgeni').Package;
121var myPackage = new Package('myPackage', ['packageDepencency1', 'packageDependency2']);
122
123myPackage.processor(require('./processors/processor1'));
124myPackage.processor(require('./processors/processor2'));
125
126myPackage.factory(require('./services/service1'));
127myPackage.factory(require('./services/service2'));
128
129myPackage.config(function(processor1, service2) {
130 service2.someProperty = 'some value';
131 processor1.specialService = service2;
132});
133```
134
135
136## Services
137
138Dgeni makes significant use of **Dependency Injection (DI)** to instantiate objects. Objects that
139will be instantiated by the DI system must be provided by a **factory function**, which is registered
140in a **Package**, either as a **Processor**, by `myPackage.processor(factoryFn)`, or as a **Service**,
141by `myPackage.factory(factoryFn)`.
142
143### Defining a Service
144
145The parameters to a factory function are dependencies on other services that the DI system must find
146or instantiate and provide to the factory function.
147
148**car.js**:
149```js
150module.exports = function car(engine, wheels) {
151 return {
152 drive: function() {
153 engine.start();
154 wheels.turn();
155 }
156 };
157};
158```
159
160Here we have defined a `car` service, which depends upon two other services, `engine` and `wheels`
161defined elsewhere. Note that this `car` service doesn't care how and where these dependencies are
162defined. It relies on the DI system to provide them when needed.
163
164The `car` service returned by the factory function is an object containing one method, `drive()`,
165which in turn calls methods on `engine` and `wheels`.
166
167
168### Registering a Service
169
170You then register the Service with a Package:
171
172**myPackage.js**:
173```jsv
174var Package = require('dgeni').Package;
175
176module.exports = new Package('myPackage')
177 .factory(require('./car'));
178```
179
180This car Service is then available to any other Service, Processor or configuration block:
181
182```js
183var Package = require('dgeni').Package;
184
185module.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
202one after another in a pipeline. Each Processor takes the collection documents from the previous
203Processor and manipulates it, maybe inserting new documents or adding meta data to documents that are
204there already.
205
206Processors can expose properties that tell Dgeni where in the pipeline they should be run and
207how 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
215to validate the properties of this Processor.
216
217
218**Note that the validation feature has been moved to its own Dgeni Package `processorValidation`.
219Currently dgeni automatically adds this new package to a new instance of dgeni so that is still available
220for backward compatibility. In a future release this package will be moved to `dgeni-packages`.**
221
222### Defining a Processor
223
224You define Processors just like you would a Service:
225
226**myDocProcessor.js**:
227```js
228module.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
246You then register the Processor with a Package:
247**myPackage.js**:
248```jsv
249var Package = require('dgeni').Package;
250
251module.exports = new Package('myPackage')
252 .processor(require('./myDocProcessor'));
253```
254
255### Asynchronous Processing
256
257The `$process(docs)` method can be synchronous or asynchronous:
258
259* If synchronous then it should return `undefined` or a new array of documents.
260If 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`
262or a new collection of documents. By returning a **Promise**, the processor tells Dgeni
263that it is asynchronous and Dgeni will wait for the promise to resolve before calling the
264next processor.
265
266
267Here is an example of an asynchronous **Processor**
268```js
269var qfs = require('q-io/fs');
270module.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
283The [dgeni-packages repository](https://github.com/angular/dgeni-packages) contains many Processors -
284from 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
287rendering Processor.
288
289* `jsdoc` - depends upon `base` and adds Processors and Services to support parsing and
290extracting jsdoc style tags from comments in code.
291
292* `typescript` - depends upon `base` and adds Processors and Services to support parsing and
293extracting jsdoc style tags from comments in TypeScript (*.ts) code.
294
295* `nunjucks` - provides a [nunjucks](http://mozilla.github.io/nunjucks/) based rendering
296engine.
297
298* `ngdoc` - depends upon `jsdoc` and `nunjucks` and adds additional processing for the
299AngularJS extensions to jsdoc.
300
301* `examples` - depends upon `jsdoc` and provides Processors for extracting examples from jsdoc
302comments and converting them to files that can be run.
303
304* `dgeni` - support for documenting dgeni Packages.
305
306
307### Pseudo Marker Processors
308
309You can define processors that don't do anything but act as markers for stages of the
310processing. You can use these markers in `$runBefore` and `$runAfter` properties to ensure
311that your Processor is run at the right time.
312
313The **Packages** in dgeni-packages define some of these marker processors. Here is a list
314of 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
339You can configure the **Services** and **Processors** defined in a **Package** or its dependencies
340by registering **Configuration Blocks** with the **Package**. These are functions that can be
341injected with **Services** and **Processors** by the DI system, giving you the opportunity to
342set properties on them.
343
344
345### Registering a Configuration Block
346
347You register a **Configuration Block** by calling `config(configFn)` on a Package.
348
349```js
350myPackage.config(function(readFilesProcessor) {
351 readFilesProcessor.sourceFiles = ['src/**/*.js'];
352});
353```
354
355## Dgeni Events
356
357In Dgeni you can trigger and handle **events** to allow packages to take part in the processing
358lifecycle of the documentation generation.
359
360
361### Triggering Events
362
363You trigger an event simply by calling `triggerEvent(eventName, ...)` on a `Dgeni` instance.
364
365The `eventName` is a string that identifies the event to be triggered, which is used to wire up
366event handlers. Additional arguments are passed through to the handlers.
367
368Each handler that is registered for the event is called in series. The return value
369from the call is a promise to the event being handled. This allows event handlers to be async.
370If any handler returns a rejected promise the event triggering is cancelled and the rejected
371promise is returned.
372
373For example:
374
375```js
376var eventPromise = dgeni.triggerEvent('someEventName', someArg, otherArg);
377```
378
379### Handling Events
380
381You register an event handler in a `Package`, by calling `handleEvent(eventName, handlerFactory)` on
382the package instance. The handlerFactory will be used by the DI system to get the handler, which allows
383you to inject services to be available to the handler.
384
385The handler factory should return the handler function. This function will receive all the arguments passed
386to the `triggerHandler` method. As a minimum this will include the `eventName`.
387
388For example:
389
390```js
391myPackage.eventHandler('generationStart', function validateProcessors(log, dgeni) {
392 return function validateProcessorsImpl(eventName) {
393 ...
394 };
395});
396
397```
398
399### Built-in Events
400
401Dgeni 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
411Apache 2