技术控

    今日:11| 主题:49448
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] Documenting your Angular app using Dgeni in 10 easy steps

[复制链接]
火包友 发表于 2016-10-3 00:28:00
147 2

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
The following is a guest post by    @sebastpelletier. Don’t hate on me, as my hair styling techniques are not as good as Todd’s ;)  

  Having worked on Enterprise-grade solutions, documentation is always an issue. It’s either outdated, deprecated or worse, there’s no documentation! Generating documentation of your Angular application is easy using Dgeni, which is ironically not well documented for a documentation generator.
  In this example I will show you how you can easily document your AngularJS application using Dgeni, and then output that documentation into a separate application!
  Table of contents

  
       
  • Why you should document your code   
  • 1. Installing NPM dependencies   
  • 2. Create folder structure   
  • 3. Setup configuration file   
  • 4. Creating static documentation   
  • 5. Basic export to HTML partials   
  • 6. Creating an Angular app to show the documentation   
  • 7. Creating a processor for our Angular index page   
  • 8. Generating a list of pages for our sidebar   
  • 9. Documenting a Module, Controller, Directive and Service   
  • 10. Compile and deploy  
  What’s Dgeni

  Dgeni (pronounced Jenny) is an extremely powerful NodeJS documentation generation utility. It was built by people from the Angular team, so it does make everything easy to document Angular projects although it can be used for other projects as well. AngularJS, Ionic Framework, Protractor and Angular Material are currently using Dgeni in production to generate their documentation.
  The main feature of Dgeni is to convert your source files to documentation files. You can convert them to a full HTML page, partials, or something else. It has a modular core and offers multiple plugins (packages). You configure your base package using Processors and Services to customize how you want to generate your documentation.
  All of your documentation needs to be written in a form of JSDoc, which is a standard for Javascript documentation (although ESDoc is picking up!), and is written inline in the source code. The various Dgeni Processors will then scan and convert your source files to documentation files. This also means that it supports many of the standard JSDoc directives, so if you are already writting JSDoc today, your work won’t be lost :)
  Dgeni does not provide a web application to display the output files, but it allows you to do what you want with it. It’s up to the developer to decide and n this example we’ll actually wrap our documentation in a simple Angular app.
  Why you should document your code

  There are many reasons why you should document your code, but we won’t be getting into specifics in this article. The main reason I will evoke here is that it allows your code to be more concise and clear, and this is extremely important when you are working in a team environment.
  Working on large scale projects with multiple files, deadlines, employees leaving, code refactorings & rewrites, these things make it hard to keep track.
  Having a up-to-date documentation will allow you to:
  
       
  • Remember the code you wrote 6 months ago   
  • Easily bring someone new into the project   
  • Easily understand each other’s code more clearly   
  • Document business rules and complex algorythms   
  • Document dependencies between modules and services  
  1. Installing NPM dependencies

  We will need a couple of NodeJS packages for documenting our application: - Dgeni, our documentation generator - Dgeni Packages, which are a collection of dgeni packages for generating documentation from source code - Canonical Path (optional), used to generate absolute paths for your source files - LoDash (optional), JavaScript utility library
  We can easily install all of those dependencies using NPM:
  1. npm i dgeni dgeni-packages canonical-path lodash --save-dev
复制代码
You will also need to use Gulp or Grunt to run Dgeni, so I suggest you install it. In my case, it’s already in use in my project so it doesn’t require any installation. Please note that you can also run Dgeni directly in Node, you would only need to create a script for the generation.
  If you are not using Gulp or Grunt in your project, install it globally as this will allow you to follow along and generate the documentation
  1. npm i gulp -g
复制代码
2. Create folder structure

  First thing we are going to do is create a    docsfolder where we will have our configuration files, our static content as well as the actual documentation. In this case, I opted to simply put it in the same directory under    build, but you could package it in a    distfolder if you want.  
  Create the following folder structure in the root folder of your application
  1. ├── docs/
  2. │   ├── app/
  3. │   ├── config/
  4. │   │  ├── processors/
  5. │   │  ├── templates/
  6. │   │  ├── index.js
  7. │   ├── content/
复制代码
Under    config, we will be creating our configuration file (index.js) and we will also be adding our Processors and Templates. In the future you can also add Services and Tag Definitions (to parse your own custom tags)  
  Under    content, we will be adding our static documentation. Dgeni reads    .mdfiles by default (using the ngDocFileReader) and will convert them to HTML partials once it’s setup correctly.  
  3. Setup configuration file

  Now, let’s open up    /docs/config/index.js, and let’s start configuring this beast !  
  1. var path = require('canonical-path');
  2. var packagePath = __dirname;
  3. var Package = require('dgeni').Package;
  4. // Create and export a new Dgeni package
  5. // We will use Gulp later on to generate that package
  6. // Think of packages as containers, our 'myDoc' package contains other packages
  7. // which themselves include processors, services, templates...
  8. module.exports = new Package('myDoc', [
  9.     require('dgeni-packages/ngdoc'),
  10.     require('dgeni-packages/nunjucks')
  11. ])
复制代码
Alright, so we’ve loaded Dgeni, our dgeni packages dependencies and created a new package for us to generate documentation. Next step, we will tell Dgeni which files we want to process and where to output them
  Setup the file reading and writing

  1. .config(function(log, readFilesProcessor, writeFilesProcessor) {
  2.     // Set the log level to 'info', switch to 'debug' when troubleshooting
  3.     log.level = 'info';
  4.     // Specify the base path used when resolving relative paths to source and output files
  5.     readFilesProcessor.basePath = path.resolve(packagePath, '../..');
  6.     // Specify our source files that we want to extract
  7.     readFilesProcessor.sourceFiles = [
  8.         { include: 'src/app/**/**/*.js', basePath: 'src/app' }, // All of our application files
  9.     ];
  10.     // Use the writeFilesProcessor to specify the output folder for the extracted files
  11.     writeFilesProcessor.outputFolder = 'docs/build';
  12. })
复制代码
Setup the templates

  Next, let’s specify where are custom templates are located
  1. .config(function(templateFinder) {
  2.     // Specify where the templates are located
  3.     templateFinder.templateFolders.unshift(path.resolve(packagePath, 'templates'));
  4. })
复制代码
Looks pretty simple so far? We are merely using the default Dgeni processors to specify how we want to process and then convert our source files. Next, let’s setup how we want to convert the source files for each document type
  Setup the Dgeni processors

  1. .config(function(computePathsProcessor) {
  2.     // Here we are defining what to output for our docType Module
  3.     //
  4.     // Each angular module will be extracted to it's own partial
  5.     // and will act as a container for the various Components, Controllers, Services in that Module
  6.     // We are basically specifying where we want the output files to be located
  7.     computePathsProcessor.pathTemplates.push({
  8.         docTypes: ['module'],
  9.         pathTemplate: '${area}/${name}',
  10.         outputPathTemplate: 'partials/${area}/${name}.html'
  11.     });
  12.     // Doing the same thing but for regular types like Services, Controllers, etc...
  13.     // By default they are grouped in a componentGroup and processed
  14.     // via the generateComponentGroupsProcessor internally in Dgeni
  15.     computePathsProcessor.pathTemplates.push({
  16.         docTypes: ['componentGroup'],
  17.         pathTemplate: '${area}/${moduleName}/${groupType}',
  18.         outputPathTemplate: 'partials/${area}/${moduleName}/${groupType}.html'
  19.     });
  20. })
复制代码
And… that’s it! Although Dgeni as been lightly configured, if you we’re to run a Gulp/Grunt task, and even though we haven’t actually started documenting anything, we can see the Dgeni pipeline and how it’s going through each different type of processors and performing various actions.
  But we’ll discuss about setup for generating code later on, now’s let’s talk about creating static documentation.
  4. Creating static documentation

  You may be wondering, Why would I want to do static documentation? Well, you may want to document other things besides the code. You may have a Developer guide, REST API References, Tutorials, Notes, Information regarding Unit & E2E tests, libraries behind used in the project… basically anything you can think of!
  Once you load the    dgeni-packagesmodule Dgeni is able to parse    @ngdoctags. We can actually use the    overviewtag from ngDoc to create our static documentation, but wouldn’t it be nice if we kept the tag as-is and just created a new doctype for Dgeni to parse? That’s exactly what we are going to do!  
  In this example we’ll add a simple developer guide, just to show you how easy it is to had static documentation.
  Let’s start out by creating these Markdown files
  1. ├── docs/
  2. │   ├── app/
  3. │   ├── config/
  4. │   ├── content/
  5. │   │  ├── api/
  6. │   │  │   ├── index.md
  7. │   │  ├── guide/
  8. │   │  │   ├── index.md
  9. │   │  │   ├── howTo.md
复制代码
Now that we’ve created those placeholders files and folders, let’s write some content! Open up    guide/howTo.mdand type the following  
  1. @ngdoc content
  2. @name How to write documentation
  3. @description
  4. # Lorem Ipsum
  5. Aenean ornare odio elit, eget facilisis ipsum molestie ac. Nam bibendum a nibh ut ullamcorper.
  6. Donec non felis gravida, rutrum ante mattis, sagittis urna. Sed quam quam, facilisis vel cursus at.
  7. ## Foo
  8. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin varius suscipit erat, non porta nunc molestie a.
  9. Nam blandit justo eget volutpat posuere. Etiam in ex fringilla, semper massa posuere, feugiat eros.
  10. ## Bar
  11. Vestibulum vel tellus id felis lacinia tristique sollicitudin et lorem. Donec fermentum,
  12. velit nec fringilla consectetur, dolor nibh bibendum velit, sed porta augue eros ut enim.
复制代码
You can also do the same in your other 2 pages, these will serve as the index pages for the    apiand    guidepages of our documentation app. You can also add other folders and other Markdown files if you like, Dgeni will parse the files the same way as the others and generate HTML partials. The    apifolder (and section) is where your code-generated documentation will be located, Dgeni uses that folder by default.  
  Adding our static content to Dgeni

  Now that we’ve added static content, we need to tell Dgeni where that content is located, and setup the computePathsProcessor so we can output the content to HTML partials. Let’s do this now!
  First, let’s add the Markdown files to the sourceFiles list:
  1. // Remember the sourceFiles section we added earlier? Let's now add our .md file to the list !
  2. readFilesProcessor.sourceFiles = [
  3.     { include: 'src/app/**/**/*.js', basePath: 'src/app' }, // All of our application files
  4.     // Our static Markdown documents
  5.     // We are specifying the path and telling Dgeni to use the ngdocFileReader
  6.     // to parse the Markdown files to HTMLs
  7.     { include: 'docs/content/**/*.md', basePath: 'docs/content', fileReader: 'ngdocFileReader' }
  8. ];
复制代码
Now, let’s setup the computePathsProcessor to output the files to HTML partials:
  1. npm i gulp -g0
复制代码
#### Create the content template We also need to create a template for our document of type    contentelse Dgeni will throw an exception. Let’s create a    content.template.htmlfile under    /docs/config/templatesand include the following  
  1. npm i gulp -g1
复制代码
5. Basic export to HTML partials

  Now that most of the configuration is done, we’ll create a Gulp task to generate the documentation. Open up your    gulpfile.jsand add the following  
  1. npm i gulp -g2
复制代码
Now we can open up the command line, navigate to your project folder and run the Gulp task we wrote above.
  1. npm i gulp -g3
复制代码
This should be the output:
  1. npm i gulp -g4
复制代码
If you open up the    docs/buildfolder you should see the exported HTML partials… but isn’t this a little bit boring? They are just plain HTML partials and are not very exciting. We have all these files, but nothing to showcase them! As mentioned previously, Dgeni doesn’t come with an application to show the output files, the developer is free to use what he/she wants.  
  And we are going to do just that! We’ll be wrapping up all of our documentation in a simple Angular application.
  One thing to note is that Dgeni doesn’t remove the partials while generating the docs. I advise you add another task that will clean up the    /buildfolder before it generates the documentation.  

  6. Creating an Angular app to show the documentation

  Now let’s create the Angular app that will house and show our HTML partials. Our app will be pretty simple and will only contain:
  
       
  • Root app module (app.module.js)   
  • Root app config & state definitions (app.config.js)   
  • Api Controller (api.js)   
  • Guide Controller (guide.js)   
  • Index view (index.html)   
  • Bootstrap (for quick styling purposes)   
  • Angular and UI-Router (multiple ui-views)  
  Creating our Angular app files

  Create    app.module.jsand    app.config.jsunder    /docs/appand add the following.  
  1. npm i gulp -g5
复制代码
We’ll get back to the Controller later on, so for now create    api.jsand    guide.jsand insert the following placeholder code  
  1. npm i gulp -g6
复制代码
Creating our index page

  Alright, moving on, we now need to create our index template. Create    indexPage.template.htmlunder    /docs/config/template:  
  1. npm i gulp -g7
复制代码
We could just add that index file directly in    /app, but we’re actually going to generate the page using a processor we will create ourselves. Dgeni will then run the processor and output our index template.  
  7. Creating a processor for our Angular index page

  Now, let’s configure Dgeni to compile our index page. Create    index-page.jsunder    /docs/config/processors  
  1. npm i gulp -g8
复制代码
Adding the index page processor to the pipeline

  Then, we need to tell Dgeni about this new processor! Let’s add it in our config file
  1. npm i gulp -g9
复制代码
If we run the Gulp task we defined earlier, you’ll see this processor added to the pipeline
  1. ├── docs/
  2. │   ├── app/
  3. │   ├── config/
  4. │   │  ├── processors/
  5. │   │  ├── templates/
  6. │   │  ├── index.js
  7. │   ├── content/0
复制代码
And if you look into your    buildfolder, you’ll see the processed index.html! That might seem like an unnecessary step, but Dgeni can output all the files we need to display our documentation app in the folder of our choosing. That means that we don’t need an external process to copy the index file.  
  8. Generating a list of pages for our sidebar

  Now, we will need to tell Angular about all of our HTML partials. First, let’s create a javascript template so that our processors can write data to it. Create    constant.data.template.jsunder the    templatesfolder.  
  1. ├── docs/
  2. │   ├── app/
  3. │   ├── config/
  4. │   │  ├── processors/
  5. │   │  ├── templates/
  6. │   │  ├── index.js
  7. │   ├── content/1
复制代码
We’ve created a template, now we need Dgeni that grab all of our partials and store that information in our constants. For that we need to create new processors, let’s start with the processor for the API pages.
  Creating the ‘API’ processor

  1. ├── docs/
  2. │   ├── app/
  3. │   ├── config/
  4. │   │  ├── processors/
  5. │   │  ├── templates/
  6. │   │  ├── index.js
  7. │   ├── content/2
复制代码
Creating the ‘Guide’ processor

  We also need to do the same for the Guide pages, althought it’s a much simpler processor.
  1. ├── docs/
  2. │   ├── app/
  3. │   ├── config/
  4. │   │  ├── processors/
  5. │   │  ├── templates/
  6. │   │  ├── index.js
  7. │   ├── content/3
复制代码
Adding the processors

  Now, we need to add those 2 processors to the Dgeni pipeline in the config file
  1. ├── docs/
  2. │   ├── app/
  3. │   ├── config/
  4. │   │  ├── processors/
  5. │   │  ├── templates/
  6. │   │  ├── index.js
  7. │   ├── content/4
复制代码
At this point it might be a good time to try running our    gulp dgenicommand to make sure everything is working properly and we don’t have any errors.  
  1. ├── docs/
  2. │   ├── app/
  3. │   ├── config/
  4. │   │  ├── processors/
  5. │   │  ├── templates/
  6. │   │  ├── index.js
  7. │   ├── content/5
复制代码
Add the data into our Angular app

  Let’s go back to our Angular app and modify the following files. We are adding our newly generated constants and binding the data directly to the view.
  1. ├── docs/
  2. │   ├── app/
  3. │   ├── config/
  4. │   │  ├── processors/
  5. │   │  ├── templates/
  6. │   │  ├── index.js
  7. │   ├── content/6
复制代码
Creating our application states

  We also need to create states so that our Angular app can be navigated. Let’s do just that! As you will notice, it creates alot of code for 1 file, so it’s a good idea to split the routing into separate files for each section. For the case of simplicity, I opted to put all the state definitions in a single file.
  1. ├── docs/
  2. │   ├── app/
  3. │   ├── config/
  4. │   │  ├── processors/
  5. │   │  ├── templates/
  6. │   │  ├── index.js
  7. │   ├── content/7
复制代码
9. Documenting a Module, Controller, Directive and Service

  In the interest of time, I will actually be documenting an existing Angular 1.5 app.
  I’m using Todd Motto’s (the owner of this blog)    Angular 1.5 Component appas a living example. If you haven’t had the time to check it out, do so… it’s the best example of a .component() based application using UI-Router 1.0 beta using routed components.  
  The examples from this guide are also available directly in the app, under    /docs. So feel free to fork the app to see it in action, and learn about how you should be building Angular apps in 2016 at the same time!  
  Documenting a Module

  1. ├── docs/
  2. │   ├── app/
  3. │   ├── config/
  4. │   │  ├── processors/
  5. │   │  ├── templates/
  6. │   │  ├── index.js
  7. │   ├── content/8
复制代码
Documenting a Method

  Notice how we are appending the name of the Controller (or constructor in which the method is contained) to the name so it gets linked.    @paramand    @returnare actually JSDoc methods!  
  1. ├── docs/
  2. │   ├── app/
  3. │   ├── config/
  4. │   │  ├── processors/
  5. │   │  ├── templates/
  6. │   │  ├── index.js
  7. │   ├── content/9
复制代码
Documenting a Service

  Adding the    @moduleJSDoc tag allows Dgeni to understand in which module that Service is located.  
  1. var path = require('canonical-path');
  2. var packagePath = __dirname;
  3. var Package = require('dgeni').Package;
  4. // Create and export a new Dgeni package
  5. // We will use Gulp later on to generate that package
  6. // Think of packages as containers, our 'myDoc' package contains other packages
  7. // which themselves include processors, services, templates...
  8. module.exports = new Package('myDoc', [
  9.     require('dgeni-packages/ngdoc'),
  10.     require('dgeni-packages/nunjucks')
  11. ])0
复制代码
Documenting a Controller

  Controllers are a bit annoying to test because there’s no way to parse controllers in ngDoc. When you look at the Dgeni project, they recommend using the    typetag when describing a Constructor, and since Controllers are Contructors, it makes sense to use it. Also notice that we are also referencing our    @moduleso they can be linked.  
  1. var path = require('canonical-path');
  2. var packagePath = __dirname;
  3. var Package = require('dgeni').Package;
  4. // Create and export a new Dgeni package
  5. // We will use Gulp later on to generate that package
  6. // Think of packages as containers, our 'myDoc' package contains other packages
  7. // which themselves include processors, services, templates...
  8. module.exports = new Package('myDoc', [
  9.     require('dgeni-packages/ngdoc'),
  10.     require('dgeni-packages/nunjucks')
  11. ])1
复制代码
Documenting a Directive / Component

  Just like Controllers, they isn’t a way to specify a type    componentusing ngDoc. To be fair, the component method is still fairly new, so that’s not a surprise. What we can do is use the    directivetype and specify it’s a component somewhere in our name / description  
  1. var path = require('canonical-path');
  2. var packagePath = __dirname;
  3. var Package = require('dgeni').Package;
  4. // Create and export a new Dgeni package
  5. // We will use Gulp later on to generate that package
  6. // Think of packages as containers, our 'myDoc' package contains other packages
  7. // which themselves include processors, services, templates...
  8. module.exports = new Package('myDoc', [
  9.     require('dgeni-packages/ngdoc'),
  10.     require('dgeni-packages/nunjucks')
  11. ])2
复制代码
For more information on how to use all the available tags, you can look at    AngularJS - How to write documentation  
  10. Compile and deploy

  Now that we’ve got our app up and running, and we started documenting some code, we can generate our documentation once again to see how it behaves. But… how can we look at our app? We need a server !
  Setting up a simple server

  I recommend installing John Papa’s    lite-serverbecause it’s a zero-configuration & SPA-friendly server. It configures BrowserSync with a middleware so you can refresh your app and it will redirect everything to index.html (and let Angular handle the routing).  
  You can install it globally, go directly into the    buildfolder and run it (it runs from the current folder by default)  
  1. var path = require('canonical-path');
  2. var packagePath = __dirname;
  3. var Package = require('dgeni').Package;
  4. // Create and export a new Dgeni package
  5. // We will use Gulp later on to generate that package
  6. // Think of packages as containers, our 'myDoc' package contains other packages
  7. // which themselves include processors, services, templates...
  8. module.exports = new Package('myDoc', [
  9.     require('dgeni-packages/ngdoc'),
  10.     require('dgeni-packages/nunjucks')
  11. ])3
复制代码
Now, as soon as you run the server you will notice the app is not working and that’s because we never copied our application files into our    srcdirectory. You could be running the application with the files directly in the    appfolder, but I recommend you use Gulp (or the build tool you are using) to concatenate, minify and package your files into the    srcfolder.  
  You can also integrate it with your current process and package everything into your    distfolder.  
  Conclusion

  As previously mentioned, Controllers and Components have no tags associated with them, so we do have to use some tricks up our sleeves to document those elements correctly. We could also add our own processors so we can parse specific types, just like we did for our    contenttypes for our static documentation.  
  Also, Dgeni doesn’t have alot of documentation and/or tutorials, which makes it hard to learn. It was pretty much the basis of this post, not alot of people seem to know about Dgeni and I wanted to blog about it, so that others can learn :)
  Otherwise, I think Dgeni is a really powerful tool to document your Javascript application. Wrapping your code in an Angular app is one way of doing things, but there are so many possibilities. For example, Protractor is exporting all their docs to markdown files and importing them in the Jekyll website.
  That’s the real power of Dgeni, developer freedom. If only more people were using it!
友荐云推荐




上一篇:Sharing Authorization Cookies between ASP.NET 4.x and ASP.NET Core 1.0
下一篇:Convert Url Text to Hiperlink
酷辣虫提示酷辣虫禁止发表任何与中华人民共和国法律有抵触的内容!所有内容由用户发布,并不代表酷辣虫的观点,酷辣虫无法对用户发布内容真实性提供任何的保证,请自行验证并承担风险与后果。如您有版权、违规等问题,请通过"联系我们"或"违规举报"告知我们处理。

mlkljkl 发表于 2016-10-6 02:13:47
明明回贴贴
回复 支持 反对

使用道具 举报

kbkn7bSa 发表于 2016-10-29 13:03:19
做为一名新人,不敢在大声说话,也不敢得罪人,只能默默地顶完贴然后转身就走人。动作要快,姿势要帅,深藏功与名。
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表手机版
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )|网站地图 酷辣虫

© 2001-2016 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表