{"id":13778341,"url":"https://github.com/dustinspecker/generator-ng-poly","last_synced_at":"2025-04-06T02:09:26.317Z","repository":{"id":18592182,"uuid":"21796735","full_name":"dustinspecker/generator-ng-poly","owner":"dustinspecker","description":"Yeoman generator for modular AngularJS apps with Gulp and optional Polymer support","archived":false,"fork":false,"pushed_at":"2017-07-20T05:42:09.000Z","size":1196,"stargazers_count":237,"open_issues_count":32,"forks_count":49,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-03-30T00:11:04.408Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dustinspecker.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-07-13T18:03:26.000Z","updated_at":"2024-03-12T17:03:12.000Z","dependencies_parsed_at":"2022-07-10T07:30:21.805Z","dependency_job_id":null,"html_url":"https://github.com/dustinspecker/generator-ng-poly","commit_stats":null,"previous_names":[],"tags_count":146,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dustinspecker%2Fgenerator-ng-poly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dustinspecker%2Fgenerator-ng-poly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dustinspecker%2Fgenerator-ng-poly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dustinspecker%2Fgenerator-ng-poly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dustinspecker","download_url":"https://codeload.github.com/dustinspecker/generator-ng-poly/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247423515,"owners_count":20936626,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T18:00:53.140Z","updated_at":"2025-04-06T02:09:26.298Z","avatar_url":"https://github.com/dustinspecker.png","language":"JavaScript","funding_links":[],"categories":["Developer"],"sub_categories":[],"readme":"# generator-ng-poly\n[![NPM version](https://badge.fury.io/js/generator-ng-poly.svg)](http://badge.fury.io/js/generator-ng-poly)\n[![Build Status](https://travis-ci.org/dustinspecker/generator-ng-poly.svg?branch=master)](https://travis-ci.org/dustinspecker/generator-ng-poly)\n[![Coverage Status](https://img.shields.io/coveralls/dustinspecker/generator-ng-poly.svg)](https://coveralls.io/r/dustinspecker/generator-ng-poly?branch=master)\n[![All Contributors](https://img.shields.io/badge/all_contributors-12-orange.svg?style=flat-square)](#contributors)\n\n[![Code Climate](https://codeclimate.com/github/dustinspecker/generator-ng-poly/badges/gpa.svg)](https://codeclimate.com/github/dustinspecker/generator-ng-poly)\n[![Dependencies](https://david-dm.org/dustinspecker/generator-ng-poly.svg)](https://david-dm.org/dustinspecker/generator-ng-poly/#info=dependencies\u0026view=table)\n[![DevDependencies](https://david-dm.org/dustinspecker/generator-ng-poly/dev-status.svg)](https://david-dm.org/dustinspecker/generator-ng-poly/#info=devDependencies\u0026view=table)\n\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)\n[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)\n\n\u003e [Yeoman](http://yeoman.io) generator for modular AngularJS apps with Gulp and optional Polymer support\n\n*Inspired by [John Papa](https://github.com/johnpapa)'s [Angular Style Guide](https://github.com/johnpapa/angular-styleguide) and [Todd Motto](https://github.com/toddmotto)'s [AngularJS styleguide](https://github.com/toddmotto/angularjs-styleguide).*\n\n## Purpose\n\nThis generator focuses on organizing Angular components by feature (home, about, video player, etc.) instead of by type (controller, service, directive, etc.) to encourage the development of self-contained, reusable components.\n\nA typical workflow with this generator consists of creating an Angular module ([ng-poly:module](#module)) and then generating controllers, directives, etc. for this module to create a new feature.\n\n**Polymer is just an added feature, but it isn't required to utilize this generator.**\n\n## Usage\n\nInstall `generator-ng-poly`:\n\n```\nnpm install -g bower gulp yo generator-ng-poly\n```\n\nIf TypeScript is going to be used, `tsd` will need to be installed:\n\n```\nnpm install -g tsd\n```\n\nRun `yo ng-poly`\nYeoman will then ask for an app name and language preferences.\n\n**If using Node 0.12, there is a bug in Yeoman or Node causing yeoman generators to hang. With ng-poly, if after it outputs the generated home module files it hangs, then it is safe to enter `Ctrl+C`, etc. The project is good to go and everything else should work normally.**\n\nRun `gulp` to build and start the development environment. [More detail on Gulp tasks](#gulp-tasks-in-detail)\n\n## User Groups\n\nPlease feel free to ask any questions on our [GitHub Issues](https://github.com/dustinspecker/generator-ng-poly/issues) or [Google Group](https://groups.google.com/forum/#!forum/generator-ng-poly).\n\n## Generators\n\nAvailable generators:\n* AngularJS\n  - [ng-poly](#app) (a.k.a. [ng-poly:app](#app))\n  - [ng-poly:constant](#constant)\n  - [ng-poly:controller](#controller)\n  - [ng-poly:decorator](#decorator)\n  - [ng-poly:directive](#directive)\n  - [ng-poly:factory](#factory)\n  - [ng-poly:filter](#filter)\n  - [ng-poly:module](#module)\n  - [ng-poly:provider](#provider)\n  - [ng-poly:route](#route)\n  - [ng-poly:service](#service)\n  - [ng-poly:value](#value)\n  - [ng-poly:view](#view)\n* Polymer\n  - [ng-poly:element](#element)\n\nLanguages and Features supported:\n  * Angular Versions\n    - 1.2.\\*, 1.3.\\*, 1.4.\\*\n  * Markup\n    - HAML, HTML, Jade\n  * Application scripting languages\n    - CoffeeScript, EcmaScript2015 (ES6) with Babel, JavaScript (ES5), TypeScript\n  * Testing scripting languages\n    - CoffeeScript, EcmaScript2015 (ES6) with Babel, JavaScript (ES5), TypeScript†\n  * Style languages\n    - CSS, LESS, SCSS, Stylus\n  * Routers\n    - Angular Route, UI Router\n  * Unit testing\n    - Jasmine (Karma as the test runner) for AngularJS\n    - Mocha with Chai (Karma as the test runner) for AngularJS\n  * e2e testing\n    - Jasmine (ran with Protractor) for AngularJS\n    - Mocha, Chai, and Chai as Promised (ran with Protractor) for AngularJS\n  * Frameworks (scaffolds simple navbar)\n    - Angular Material (1.3.* or higher only)\n      - Doesn't scaffold navbar, yet\n    - Bootstrap with AngularStrap\n    - Bootstrap with UI Bootstrap\n    - Foundation with Angular Foundation\n  * Polymer\n    - Core, Paper\n  * Task runners\n    - Gulp\n  * Other supported Bower packages:\n    - Angular Animate\n    - Angular Cookies\n    - Angular Messages\n    - Angular Resource\n    - Angular Sanitize\n    - Angular Touch\n    - Font Awesome\n    - Lo-Dash\n    - Restangular\n\n[Configurations](#configurations):\n  * Syntax\n    - [Controller As](#controller-as-syntax)\n    - [Directive TemplateUrl](#directive-templateurl)\n\n† e2e tests are not supported in TypeScript. JavaScript will instead be used for e2e tests.\n\n### Gulp Tasks Briefing\n`gulp` will start a localhost and open in the default browser\n\nUsing `--stage prod` will concat and minify HTML, CSS, and Angular modules.\n\n`gulp build` will compile the assets\n\n`gulp dev` will call the build task and setup the development environment\n\n`gulp unitTest` will run unit tests via Karma and create code coverage reports\n\n`gulp webdriverUpdate` will download the Selenium server standalone and Chrome driver for e2e testing\n\n`gulp e2eTest` will run e2e tests via Protractor (must start a localhost before running `gulp e2eTest`)\n\n[Gulp Tasks in Detail](#gulp-tasks-in-detail)\n\n* * *\n**All generators ask for a module name except app and element. All generators except app take a name as an argument. A name can be written with CamelCase or hyphens.**\n\nGenerators requiring a module can take a module option to bypass the prompt:\n```\nyo ng-poly:view newView --module=home/kitchen\n```\n**A module value of `app` will add the new components to the module defined in app.js or app.coffee.**\n* * *\n\n**Examples are shown with HTML, LESS, JavaScript, Jasmine, and UI Router as the app configuration.**\n\n### App\nAsks for application name and language preferences to scaffold out an application with a home module. It will also ask if tests should be placed in the `app/` or `tests/` directory. It'll ask for some additional Bower dependencies and then install npm and Bower dependencies.\n\nExample:\n\nRun `yo ng-poly` to get started. ng-poly will then asks you some questions:\n\n```\n[?] What is the app's name?\n[?] Which version of Angular should be used?\n[?] Which structure should be used?\n[?] Which is the preferred markup language?\n[?] Which is the preferred application scripting language?\n[?] Want to use Controller As syntax?\n[?] Should directives be generated using a templateUrl (and markup file) instead of an inline template?\n[?] By default, should the route generator create controllers?\n[?] Which is the preferred test scripting language?\n[?] Which is the preferred unit testing framework?\n[?] Which is the preferred e2e testing framework?\n[?] Which is the preferred style language?\n[?] Should Polymer support be enabled?\n[?] Should a framework be setup?\n[?] Should ngRoute be used instead of UI Router?\n[?] Which additional Bower components should be installed?\n```\n\nng-poly makes some assumptions, but these can be overridden.\n\n| Option | Default Value| Info |\n| -------| ------------ | ---- |\n| host | localhost | BrowserSync and Protractor will use this host. |\n| port | 3000 | BrowserSync and Protractor will use this port. |\n| app-dir | app | Source code will be generated here. |\n| unit-test-dir | app | Unit tests will be generated here. |\n| skip-controller | false | Should the route generator *skip* creating a controller? |\n| skip-install | false | Should ng-poly skip installing Bower and npm dependencies? |\n\nExample: `yo ng-poly --port=8080 --app-dir=src` to override the default port and app directory.\n\nA **module-only** structure produces:\n```\nroot/\n├── app/\n│   ├── fonts/ (empty)\n│   ├── home/\n│   │   ├── home-module.{coffee,es6,js,ts}\n│   │   ├── home-routes.{coffee,es6,js,ts}\n│   │   ├── home.{css,less,scss,styl}\n│   │   ├── home.tpl.{haml,html,jade}\n│   │   ├── home-controller.{coffee,es6,js,ts}\n│   │   └── home-controller_test.{coffee,es6,js,ts}\n│   ├── images/ (empty)\n│   ├── app-module.{coffee,es6,js,ts}\n│   ├── app-routes.{coffee,es6,js,ts}\n│   └── index.{haml,html,jade}\n├── bower_components/\n├── e2e/\n│   └── home/\n│       ├── home.po.{coffee,es6,js}\n│       └── home_test.{coffee,es6,js}\n├── gulp/\n│   ├── analyze.js\n│   ├── build.js\n│   ├── test.js\n│   └── watch.js\n├── node_modules/\n├── typings/*\n├── .bowerrc\n├── .editorconfig\n├── .eslintrc\n├── .gitignore\n├── .jscsrc\n├── .jshintrc\n├── .yo-rc.json\n├── bower.json\n├── build.config.js\n├── Gulpfile.js\n├── karma.config.js\n├── package.json\n├── protractor.config.js\n├── README.md\n├── tsd.json*\n└── tslint.json*\n```\n\nA **module-type** structure produces:\n```\nroot/\n├── app/\n│   ├── fonts/ (empty)\n│   ├── home/\n│   │   ├── controllers/\n│   │   │   ├── home-controller.{coffee,es6,js,ts}\n│   │   │   └── home-controller_test.{coffee,es6,js,ts}\n│   │   ├── views/\n│   │   │   ├── home.{css,less,scss,styl}\n│   │   │   └── home.tpl.{haml,html,jade}\n│   │   ├── home-module.{coffee,es6,js,ts}\n│   │   └── home-routes.{coffee,es6,js,ts}\n│   ├── images/ (empty)\n│   ├── app-module.{coffee,es6,js,ts}\n│   ├── app-routes.{coffee,es6,js,ts}\n│   └── index.{haml,html,jade}\n├── bower_components/\n├── e2e/\n│   └── home/\n│       ├── home.po.{coffee,es6,js}\n│       └── home_test.{coffee,es6,js}\n├── gulp/\n│   ├── analyze.js\n│   ├── build.js\n│   ├── test.js\n│   └── watch.js\n├── node_modules/\n├── typings/*\n├── .bowerrc\n├── .editorconfig\n├── .eslintrc\n├── .gitignore\n├── .jscsrc\n├── .jshintrc\n├── .yo-rc.json\n├── bower.json\n├── build.config.js\n├── Gulpfile.js\n├── karma.config.js\n├── package.json\n├── protractor.config.js\n├── README.md\n├── tsd.json*\n└── tslint.json*\n```\n\\* Only TypeScript projects will have this.\n### Constant\nGenerates a constant and its test.\n\nExample:\n```\nyo ng-poly:constant theHero\n[?] Which module is this for?\n```\n\nProduces `app/module/the-hero-constant.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc service\n   * @name module.constant:theHero\n   *\n   * @description\n   *\n   */\n  angular\n    .module('module')\n    .constant('theHero', 0);\n}());\n\n```\n\nProduces `app/module/the-hero-constant_test.js`:\n```javascript\n/*global describe, beforeEach, it, expect, inject, module*/\n'use strict';\n\ndescribe('theHero', function () {\n  var constant;\n\n  beforeEach(module('module'));\n\n  beforeEach(inject(function (theHero) {\n    constant = theHero;\n  }));\n\n  it('should equal 0', function () {\n    expect(constant).toBe(0);\n  });\n});\n\n```\n\n### Controller\nGenrates a controller and its test.\n\nExample:\n```\nyo ng-poly:controller micro\n[?] Which module is this for?\n```\n\nProduces `app/module/micro-controller.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc object\n   * @name module.controller:MicroCtrl\n   * @requires $scope\n   *\n   * @description\n   *\n   */\n  angular\n    .module('module')\n    .controller('MicroCtrl', MicroCtrl);\n\n  function MicroCtrl($scope) {\n    $scope.micro = {};\n    $scope.micro.ctrlName = 'MicroCtrl';\n  }\n}());\n\n```\n\nProduces `app/module/micro-controller_test.js`:\n```javascript\n/*global describe, beforeEach, it, expect, inject, module*/\n'use strict';\n\ndescribe('MicroCtrl', function () {\n  var scope;\n\n  beforeEach(module('module'));\n\n  beforeEach(inject(function ($rootScope, $controller) {\n    scope = $rootScope.$new();\n    $controller('MicroCtrl', {$scope: scope});\n  }));\n\n  it('should have ctrlName as MicroCtrl', function () {\n    expect(scope.micro.ctrlName).toEqual('MicroCtrl');\n  });\n});\n\n```\n\n### Decorator\nGenerates a decorator and its test.\n\nExample:\n```\nyo ng-poly:decorator awesomeService\n[?] Which module is this for?\n```\n\n**Note: If decorating a service starting with a `$` you must escape it like:**\n\n`yo ng-poly:decorator \\$state`\n\nProduces `app/module/awesome-service-decorator.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc decorator\n   * @name home.decorator:awesomeService\n   * @restrict EA\n   * @element\n   *\n   * @description\n   *\n   */\n  angular\n    .module('module')\n    .config(decorator);\n\n  function decorator($provide) {\n    $provide.decorator('awesomeService', function ($delegate) {\n      $delegate.simpleFunction = function () {\n        return 'awesomeService';\n      };\n      return $delegate;\n    });\n  }\n}());\n\n```\n\nProduces: `app/module/awesome-service-decorator_test.js`:\n```javascript\n/*global describe, beforeEach, it, expect, inject, module*/\n'use strict';\n\ndescribe('awesomeService', function () {\n  var decorator;\n\n  beforeEach(module('module'));\n\n  beforeEach(inject(function (awesomeService) {\n    decorator = awesomeService;\n  }));\n\n  it('should have simpleFunction return awesomeService', function () {\n    expect(decorator.simpleFunction()).toEqual('awesomeService');\n  });\n});\n\n```\n\n### Directive\nGenerates a directive, its template, and its test.\n\nExample:\n```\nyo ng-poly:directive fancy-button\n[?] Which module is this for?\n```\n\nProduces `app/module/fancy-button-directive.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc directive\n   * @name module.directive:fancyButton\n   * @restrict EA\n   * @element\n   *\n   * @description\n   *\n   * @example\n     \u003cexample module=\"module\"\u003e\n       \u003cfile name=\"index.html\"\u003e\n        \u003cfancy-button\u003e\u003c/fancy-button\u003e\n       \u003c/file\u003e\n     \u003c/example\u003e\n   *\n   */\n  angular\n    .module('module')\n    .directive('fancyButton', fancyButton);\n\n  function fancyButton() {\n    return {\n      restrict: 'EA',\n      scope: {},\n      templateUrl: 'module/fancy-button-directive.tpl.html',\n      replace: false,\n      controller: function (scope) {\n        scope.fancyButton = {};\n        scope.fancyButton.name = 'fancyButton';\n      },\n      link: function (scope, element, attrs) {\n        /*jshint unused:false */\n        /*eslint \"no-unused-vars\": [2, {\"args\": \"none\"}]*/\n      }\n    };\n  }\n}());\n\n```\n\nProduces `app/module/fancy-button-directive.tpl.html`:\n```html\n\u003cdiv\u003e{{fancyButton.name}}\u003c/div\u003e\n```\n\nProduces `app/module/fancy-button-directive_test.js`:\n```javascript\n/*global describe, beforeEach, it, expect, inject, module*/\n'use strict';\n\ndescribe('fancyButton', function () {\n  var scope;\n  var element;\n\n  beforeEach(module('module', 'module/fancy-button-directive.tpl.html'));\n\n  beforeEach(inject(function ($compile, $rootScope) {\n    scope = $rootScope.$new();\n    element = $compile(angular.element('\u003cfancy-button\u003e\u003c/fancy-button\u003e'))(scope);\n  }));\n\n  it('should have correct text', function () {\n    scope.$apply();\n    expect(element.isolateScope().fancyButton.name).toEqual('fancyButton');\n  });\n});\n\n```\n**The directive's template (HAML, HTML, or Jade) is converted to a temporary module automatically for testing.**\n\n### Factory\nGenerates a factory and its test.\n\nExample:\n```\nyo ng-poly:factory cake\n[?] Which module is this for?\n```\n\nProduces `app/module/cake-factory.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc service\n   * @name module.factory:Cake\n   *\n   * @description\n   *\n   */\n  angular\n    .module('module')\n    .factory('Cake', Cake);\n\n  function Cake() {\n    var CakeBase = {};\n    CakeBase.someValue = 'Cake';\n    CakeBase.someMethod = function () {\n      return 'Cake';\n    };\n    return CakeBase;\n  }\n}());\n\n```\n\nProduces `app/module/Cake-factory_test.js`:\n```javascript\n/*global describe, beforeEach, it, expect, inject, module*/\n'use strict';\n\ndescribe('Cake', function () {\n  var factory;\n\n  beforeEach(module('module'));\n\n  beforeEach(inject(function (Cake) {\n    factory = Cake;\n  }));\n\n  it('should have someValue be Cake', function () {\n    expect(factory.someValue).toEqual('Cake');\n  });\n\n  it('should have someMethod return Cake', function () {\n    expect(factory.someMethod()).toEqual('Cake');\n  });\n});\n\n```\n\n### Filter\nGenerates a filter and its test.\n\nExample:\n```\nyo ng-poly:filter coffee\n[?] Which module is this for?\n```\n\nProduces `app/module/coffee-filter.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc filter\n   * @name module.filter:coffee\n   *\n   * @description\n   *\n   * @param {Array} input The array to filter\n   * @returns {Array} The filtered array\n   *\n   */\n  angular\n    .module('module')\n    .filter('coffee', coffee);\n\n  function coffee() {\n    return function (input) {\n      var temp = [];\n      angular.forEach(input, function (item) {\n        if(item \u003e 3) {\n          temp.push(item);\n        }\n      });\n      return temp;\n    };\n  }\n}());\n\n```\n\nProduces `app/module/coffee-filter_test.js`:\n```javascript\n/*global describe, beforeEach, it, expect, inject, module*/\n'use strict';\n\ndescribe('coffee', function () {\n  beforeEach(module('module'));\n\n  it('should filter our numbers not greater than 3', inject(function ($filter) {\n    expect($filter('coffee')([1,2,3,4])).toEqual([4]);\n  }));\n});\n\n```\n\n### Module\nGenerates a new module and create a new route. Updates parent module's dependencies.\n\n**Top Level Example:**\n```\nyo ng-poly:module top\n```\n\nProduces `app/top/top-module.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /* @ngdoc object\n   * @name top\n   * @description\n   *\n   */\n  angular\n    .module('top', [\n      'ui.router'\n    ]);\n}());\n\n```\n\nProduces `pp/top/top-routes.js`:\n```javascript\n(function () {\n  'use strict';\n\n  angular\n    .module('top')\n    .config(config);\n\n  function config($stateProvider) {\n    $stateProvider\n      .state('top', {\n        url: '/top',\n        templateUrl: 'top/top.tpl.html',\n        controller: 'TopCtrl'\n      });\n  }\n}());\n\n```\n\nProduces `app/top/top-controller.js`, `app/top/top-controller_test.js`, `app/top/top.tpl.html`, `app/top/top.less`, `e2e/top/top.po.js`, `e2e/top/top_test.js`\n\nUpdates `app/app-module.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /* @ngdoc object\n   * @name module\n   * @requires $urlRouterProvider\n   * @description\n   *\n   */\n  angular\n    .module('module', [\n      'ui.router',\n      'home',\n      'top'\n    ]);\n}());\n\n```\n\n* * *\n\n**Deep Level Example:**\n```\nyo ng-poly:module top/bottom\n```\n\nProduces `app/top/bottom/bottom-module.js`, `app/top/boottom/bottom-routes.js`, `app/top/bottom/bottom-controller.js`, `app/top/bottom/bottom-controller_test.js`, `app/top/bottom/bottom.tpl.html`, `app/top/bottom/bottom.less`, `e2e/bottom/bottom.po.js`, `e2e/bottom/bottom_test.js`\n\nUpdates `app/top/top-module.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /* @ngdoc object\n   * @name top\n   * @requires $stateProvider\n   *\n   * @description\n   *\n   */\n  angular\n    .module('top', [\n      'ui.router',\n      'top.bottom'\n    ]);\n}());\n\n```\n\n**Notice the module in `app/top/bottom/` is called 'top.bottom'. All tests in this directory use this nomenclature, as well.**\n\n* * *\n**Deeper Level Example:**\n```\nyo ng-poly:module top/bottom/bottomest\n```\n\nProduces 'bottom.bottomest' module and routes, a controller, controller test, style, and a view in `app/top/bottom/bottomest/`\n\nUpdates 'top.bottom' module with the new 'bottom.bottemest' module as a dependency.\n\n* * *\n**Deeperestier Level Example:**\n\nIt just keeps going...\n\n* * *\n**Empty modules**\n\nBy running `ng-poly:module newHome --empty` a module's routes file will **not** be created.\n\nThe module file will omit the router dependency:\n```javascript\n(function () {\n  'use strict';\n\n  /* @ngdoc object\n   * @name newHome\n   *\n   * @description\n   *\n   */\n  angular\n    .module('newHome', [\n    ]);\n}());\n\n```\n\n### Provider\nGenerates a provider and its test.\n\nExample:\n```\nyo ng-poly:provider bacon\n[?] Which module is this for?\n```\n\nProduces `app/module/bacon-provider.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc service\n   * @name module.provider:Bacon\n   *\n   * @description\n   *\n   */\n  angular\n    .module('module')\n    .provider('Bacon', Bacon);\n\n  function Bacon() {\n    return {\n      $get: function () {\n        return 'Bacon';\n      }\n    };\n  }\n}());\n\n```\n\nProduces `app/module/Bacon-provider_test.js`:\n```javascript\n/*global describe, beforeEach, it, expect, inject, module*/\n'use strict';\n\ndescribe('Bacon', function () {\n  var provider;\n\n  beforeEach(module('module'));\n\n  beforeEach(inject(function (Bacon) {\n    provider = Bacon;\n  }));\n\n  it('should equal Bacon', function () {\n    expect(provider).toEqual('Bacon');\n  });\n});\n\n```\n\n### Route\nAdds a new route and generates a controller and view. The name provided is used as state name for UI Router and as the route URL for ngRoute. Yeoman will then ask for the module to add the route to, the URL for the route (UI Router only), and the templateUrl. It will also generate an e2e test and a Page Object model for the new route.\n\nExample:\n```\nyo ng-poly:route your-place\n[?] Which module is this for?\n[?] What's the URL for this route? (UI Router only)\n[?] What's the templateURL for this route?\n```\n\nUpdates `app/module/module-module.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /* @ngdoc object\n   * @name module\n   * @requires $stateProvider\n   *\n   * @description\n   *\n   */\n  angular\n    .module('module', [\n      'ui.router'\n    ]);\n\n  angular\n    .module('module')\n    .config(config);\n\n  function config($stateProvider) {\n    $stateProvider\n      .state('module', {\n        url: '/module',\n        templateUrl: 'module/module.tpl.html',\n        controller: 'ModuleCtrl'\n      })\n      .state('yourPlace', {\n        url: '/yourPlace',\n        templateUrl: 'module/your-place.tpl.html',\n        controller: 'YourPlaceCtrl'\n      });\n  }\n}());\n\n```\n\nProduces `e2e/your-place/your-place.po.js`:\n```javascript\n/*global element, by*/\n'use strict';\n\nvar YourPlacePage = function () {\n  this.text = element(by.tagName('p'));\n  this.heading = element(by.tagName('h2'));\n};\n\nmodule.exports = YourPlacePage;\n```\n\nProduces `e2e/your-place/your-place_test.js`:\n```javascript\n/*global describe, beforeEach, it, browser, expect */\n'use strict';\n\nvar buildConfigFile = require('findup-sync')('build.config.js')\n  , buildConfig = require(buildConfigFile)\n  , YourPlacePagePo = require('./your-place.po');\n\ndescribe('Your place page', function () {\n  var yourPlacePage;\n\n  beforeEach(function () {\n    yourPlacePage = new YourPlacePagePo();\n    browser.driver.get(buildConfig.host + ':' + buildConfig.port + '/#/yourPlace');\n  });\n\n  it('should say YourPlaceCtrl', function () {\n    expect(yourPlacePage.heading.getText()).toEqual('yourPlace');\n    expect(yourPlacePage.text.getText()).toEqual('YourPlaceCtrl');\n  });\n});\n\n```\n\nProduces `app/module/your-place-controller.js`, `app/module/your-place-controller_test.js`, `app/module/your-place.tpl.html`, and `app/module/your-place.less`\n\n**Currently, the module must have an existing state for another to be added.**\n\n* * *\nThe route generator can take URL and templateUrl options, as well.\n```\nyo ng-poly:route yourPlace --url=yourPlace --template-url=your-place\n```\nThe URL will automatically be prepended with `/` and and the templateUrl will be appended with `.tpl.html`.\n* * *\n\n### Service\nGenerates a service and its test.\n\nExample:\n```\nyo ng-poly:service cheap-or-good\n[?] Which module is this for?\n```\n\nProduces `app/module/cheap-or-good-service.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc service\n   * @name home.service:CheapOrGood\n   *\n   * @description\n   *\n   */\n  angular\n    .module('module')\n    .service('CheapOrGood', CheapOrGood);\n\n  function CheapOrGood() {\n    var self = this;\n\n    self.get = function get() {\n      return 'CheapOrGood';\n    };\n  }\n}());\n\n```\n\nProduces `app/module/cheap-or-good-service_test.js`:\n```javascript\n/*global describe, beforeEach, it, expect, inject, module*/\n'use strict';\n\ndescribe('CheapOrGood', function () {\n  var service;\n\n  beforeEach(module('module'));\n\n  beforeEach(inject(function (CheapOrGood) {\n    service = CheapOrGood;\n  }));\n\n  it('should equal CheapOrGood', function () {\n    expect(service.get()).toEqual('CheapOrGood');\n  });\n});\n\n```\n\n### Value\nGenerates a value and its test.\n\nExample:\n```\nyo ng-poly:value morals\n[?] Which module is this for?\n```\n\nProduces `app/module/morals-value.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc service\n   * @name module.constant:morals\n   *\n   * @description\n   *\n   */\n  angular\n    .module('module')\n    .value('morals', 0);\n}());\n\n```\n\nProduces `app/module/morals-value_test.js`:\n```javascript\n/*global describe, beforeEach, it, expect, inject, module*/\n'use strict';\n\ndescribe('morals', function () {\n  var value;\n\n  beforeEach(module('module'));\n\n  beforeEach(inject(function (morals) {\n    value = morals;\n  }));\n\n  it('should equal 0', function () {\n    expect(value).toBe(0);\n  });\n});\n\n```\n\n### View\nGenerates a view and its style.\n\nExample:\n```\nyo ng-poly:view nice\n[?] Which module is this for?\n```\n\nProduces `app/module/nice-view.tpl.html`:\n```html\n\u003ch2\u003enice\u003c/h2\u003e\n\u003cp\u003e{{nice.ctrlName}}\u003c/p\u003e\n```\n\nProduces an empty file `app/module/nice-view.less`\n\n* * *\n\n### Element\nGenerates a Polymer element.\n\nExample:\n```\nyo ng-poly:element gold-silver\n```\n\nProduces `app/components/gold-silver/gold-silver.less`:\n```css\n:host {\n  height: 100px;\n  width: 100px;\n  display: inline-block;\n}\n```\n\nProduces `app/components/gold-silver/gold-silver.html`:\n```html\n\u003clink rel='import' href='../polymer/polymer.html'\u003e\n\n\u003cpolymer-element name='gold-silver'\u003e\n  \u003ctemplate\u003e\n    \u003clink rel='stylesheet' href='gold-silver.css'\u003e\n    \u003cdiv\u003e{{name}}\u003c/div\u003e\n  \u003c/template\u003e\n\n  \u003cscript src='gold-silver.js'\u003e\u003c/script\u003e\n\u003c/polymer-element\u003e\n```\n\nProduces `app/components/gold-silver/gold-silver.js`:\n```javascript\n/*global Polymer*/\n(function () {\n  'use strict';\n\n  var element = new Polymer({\n    is: 'gold-silver',\n    ready: function () {\n      console.log('gold-silver');\n    }\n  });\n\n  return element;\n}());\n```\n\n* * *\n\n## Configurations\n\nIt is possible to override some configurations initially specified when `yo ng-poly` was ran.\n\nEach generator is able to take the following arguments. For example, `yo ng-poly:module test --skip-controller=true` will override the configuration settings for everything generated by this command.\n\n| Option | Possible Values| Description |\n| ------ | -------------- | ----------- |\n| directive-template-url | true, false | Use external markup files and templateUrl instead of template in directives |\n| skip-controller | true, false | Skip creating controllers when generating routes and modules |\n\n**It's not recommended to mix ngRoute and UI Router, but it's possible.**\n\n### Controller As Syntax\n\nThis generator has support for the Controller As syntax. Yeoman will ask if this should be enabled when `ng-poly:app` is ran.\n\nThis will generate controllers like:\n\n```javascript\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc object\n   * @name home.controller:HomeCtrl\n   *\n   * @description\n   *\n   */\n  angular\n    .module('home')\n    .controller('HomeCtrl', HomeCtrl);\n\n  function () {\n    var vm = this;\n    vm.ctrlName = 'HomeCtrl';\n  }\n}());\n```\n\n...and their tests like:\n\n```javascript\n/*global describe, beforeEach, it, expect, inject, module*/\n'use strict';\n\ndescribe('HomeCtrl', function () {\n  var ctrl;\n\n  beforeEach(module('home'));\n\n  beforeEach(inject(function ($rootScope, $controller) {\n    ctrl = $controller('HomeCtrl');\n  }));\n\n  it('should have ctrlName as HomeCtrl', function () {\n    expect(ctrl.ctrlName).toEqual('HomeCtrl');\n  });\n});\n\n```\n\nIt'll also modify the state's controller like:\n\n```javascript\n(function () {\n  'use strict';\n\n  /* @ngdoc object\n   * @name home\n   * @requires $stateProvider\n   *\n   * @description\n   *\n   */\n  angular\n    .module('home', [\n      'ui.router'\n    ]);\n\n  angular\n    .module('home')\n    .config(config);\n\n  function config($stateProvider) {\n    $stateProvider\n      .state('home', {\n        url: '/home',\n        templateUrl: 'home/home.tpl.html',\n        controller: 'HomeCtrl as home'\n      });\n  }\n}());\n\n```\n\nDirectives will be generated like:\n\n```javascript\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc directive\n   * @name home.directive:fancyButton\n   * @restrict EA\n   * @element\n   *\n   * @description\n   *\n   * @example\n     \u003cexample module=\"home\"\u003e\n       \u003cfile name=\"index.html\"\u003e\n        \u003cfancy-button\u003e\u003c/fancy-button\u003e\n       \u003c/file\u003e\n     \u003c/example\u003e\n   *\n   */\n  angular\n    .module('home')\n    .directive('fancyButton', fancyButton);\n\n  function fancyButton() {\n    return {\n      restrict: 'EA',\n      scope: {},\n      templateUrl: 'home/fancy-button-directive.tpl.html',\n      replace: false,\n      controllerAs: 'fancyButton',\n      controller: function () {\n        var vm = this;\n        vm.name = 'fancyButton';\n      },\n      link: function (scope, element, attrs) {\n        /*jshint unused:false */\n        /*eslint \"no-unused-vars\": [2, {\"args\": \"none\"}]*/\n      }\n    };\n  }\n}());\n\n```\n\nLastly, views will be generated like:\n\n```html\n\u003ch2\u003ehome\u003c/h2\u003e\n\u003cp\u003e{{home.ctrlName}}\u003c/p\u003e\n```\n\n### Directive TemplateUrl\n\nThis generator has supporting for creating directives with inline templates and external markup files using templateUrl.\n\nIf Directive TemplateUrl is enabled, directives will be created as described [above](#directive).\n\nIf Directive TemplateUrl is disabled, directives will be created like below.\n\nExample:\n```\nyo ng-poly:directive fancy-button\n[?] Which module is this for?\n```\n\nProduces `app/module/fancy-button-directive.js`:\n```javascript\n(function () {\n  'use strict';\n\n  /**\n   * @ngdoc directive\n   * @name module.directive:fancyButton\n   * @restrict EA\n   * @element\n   *\n   * @description\n   *\n   * @example\n     \u003cexample module=\"module\"\u003e\n       \u003cfile name=\"index.html\"\u003e\n        \u003cfancy-button\u003e\u003c/fancy-button\u003e\n       \u003c/file\u003e\n     \u003c/example\u003e\n   *\n   */\n  angular\n    .module('module')\n    .directive('fancyButton', fancyButton);\n\n  function fancyButton() {\n    return {\n      restrict: 'EA',\n      scope: {},\n      template: '\u003cdiv\u003e{{fancyButton.name}}\u003c/div\u003e',\n      replace: false,\n      controller: function (scope) {\n        scope.fancyButton = {};\n        scope.fancyButton.name = 'fancyButton';\n      },\n      link: function (scope, element, attrs) {\n        /*jshint unused:false */\n        /*eslint \"no-unused-vars\": [2, {\"args\": \"none\"}]*/\n      }\n    };\n  }\n}());\n\n```\n\nProduces `app/module/fancy-button-directive_test.js`:\n```javascript\n/*global describe, beforeEach, it, expect, inject, module*/\n'use strict';\n\ndescribe('fancyButton', function () {\n  var scope;\n  var element;\n\n  beforeEach(module('module'));\n\n  beforeEach(inject(function ($compile, $rootScope) {\n    scope = $rootScope.$new();\n    element = $compile(angular.element('\u003cfancy-button\u003e\u003c/fancy-button\u003e'))(scope);\n  }));\n\n  it('should have correct text', function () {\n    scope.$apply();\n    expect(element.isolateScope().fancyButton.name).toEqual('fancyButton');\n  });\n});\n\n```\n\n* * *\n\n## Gulp Tasks in Detail\n\n*Items in italics are only ran in --stage=prod*\n\nAvailable tasks:\n- `gulp` or `gulp default`\n - Runs `gulp dev`\n- `gulp dev`\n - Runs `gulp build` and starts BrowserSync and Gulp's watch\n- `gulp build`\n - Runs `gulp analyze`\n - Runs `gulp clean` to delete build directory\n - Runs `gulp markup` to compile Haml and Jade to HTML\n - Runs `gulp styles` to compile Less, SCSS, and Stylus (with Nib), add vendor prefixes, *modify images and font URLs*, *concat*, *minify*, and *rev*\n - Runs `gulp scripts` to compile ES2015, CoffeeScript, and TypeScript, *injects HTML templates in $templateCache*, *sorts Angular files*, *annotates*, *minifies*, and *rev*\n - Runs `gulp inject` to inject sorted JS and CSS source files into build/index.html\n - Runs `gulp bowerCopy` to *modify image and font URLs in vendor CSS files*, *concat vendor CSS*, *minify vendor CSS*, *rev vendor CSS*, copy vendor CSS to build, *concat vendor JS*, *minify vendor JS and leave licenses intact*, copy vendor JS to build\n - Runs `gulp bowerInject` to inject vendor CSS and JS into build/index.html\n - Runs `gulp bowerAssets` to copy over any vendor image and fonts to build/\n - Runs `gulp fonts` to copy app fonts to build/\n - Runs `gulp images` to copy app images to build/\n - Runs `gulp copyTemplates` to copy compiled templates to a separate test directory used for unit testing\n - Runs `gulp deleteTemplates` to *delete templates in build*\n- `gulp unitTest`\n - Runs `gulp lint`\n - Runs `gulp clean:test` to delete previous compiled unit tests\n - Runs `gulp buildTests` to compile CoffeeScript, ES2015, and TypeScript unit tests\n - Runs `gulp build`\n - Runs `gulp karmaFiles` to automatically configure Bower dependencies, directive templates, sorted build JS files, and unit tests for Karma\n - Run unit tests with Karma\n- `gulp e2eTest`\n - Runs `gulp lint`\n - Runs `gulp build`\n - Runs `gulp build:e2eTest` to compile CoffeeScript, ES2015, and TypeScript tests\n - Runs Protractor to perform e2eTest (**app needs to be running via `gulp default`**)\n- `gulp webdriverUpdate` downloads Selenium and webdrivers for e2e testing\n- `gulp analyze`\n - Analyzes source and test code with CoffeeLint, TSLint, ESLint, JSHint, and JSCS\n - Uses Plato to inspect source and test for complexity and maintainability\n\n* * *\n\n## How to Add Polymer elements\n\nCurrently, this process isn't as simple as desired. **Pull requests are greatly appreciated to help this process in any way.**\n\nFor this, we're going to install and setup `paper-toolbar`.\n\n1. Run `bower install --save polymerelements/paper-toolbar` to download `paper-toolbar` and its dependencies.\n1. Digging through `bower_components/paper-toolbar/`, we can determine it needs to have `paper-toolbar/paper-toolbar.html`, `paper-styles/paper-styles.html`, and `polymer/polymer`. We then dig through `bower_components/paper-styles/` to find it needs `paper-styles/paper-styles.html`, `paper-styles/color.html`, `paper-styles/default-theme.html`, `paper-styles/shadow.html`, `paper-styles/typography.html`, `iron-flex-layout/iron-flex-layout.html`, and `iron-flex-layout/classes/iron-flex-layout.html`. Then we dig through `iron-flex-layout/iron-flex-layout` to find out we just need to additionally include `iron-flex-layout/iron-flex-layout/classes/iron-shadow-flex-layout.html`.\n1. Edit the `components` task in `gulp/build.js` to include polymerBowerAssetsToCopy like:\n\n  ```javascript\n  polymerBowerAssetsToCopy = [\n    'polymer/polymer*.html',\n    'iron-flex-layout/iron-flex-layout.html',\n    'iron-flex-layout/classes/*.html',\n    'paper-styles/{color,default-theme,paper-styles,shadow.html,typography.html}',\n    'paper-toolbar/paper-toolbar.html'\n  ].map(function (file) {\n    return bowerDir + file;\n  });\n  ```\n\n1. Edit the `componentsInject` task in `gulp/build.js` to include\n\n  ```javascript\n  var polymerAssetsToInject = [\n    'polymer/polymer.html',\n    'paper-styles/paper-styles.html'\n  ].map(function (file) {\n    return config.buildComponents + file;\n  });\n  ```\n\n1. Now, we can use the `\u003cpaper-toolbar\u003e` element in our code.\n\n**Note: for custom components, we just need to include them in `polymerAssetsToInject`. They are all automically copied.**\n* * *\n\n## Contributors\nThanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n| [\u003cimg src=\"https://avatars.githubusercontent.com/u/2449282?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eDustin Specker\u003c/sub\u003e](http://dustinspecker.com)\u003cbr /\u003e[💻](https://github.com/dustinspecker/generator-ng-poly/commits?author=dustinspecker) [📖](https://github.com/dustinspecker/generator-ng-poly/commits?author=dustinspecker) [⚠️](https://github.com/dustinspecker/generator-ng-poly/commits?author=dustinspecker) | [\u003cimg src=\"https://avatars.githubusercontent.com/u/211327?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eBinh Nguyen\u003c/sub\u003e](https://github.com/ngbinh)\u003cbr /\u003e[💻](https://github.com/dustinspecker/generator-ng-poly/commits?author=ngbinh) [📖](https://github.com/dustinspecker/generator-ng-poly/commits?author=ngbinh) [⚠️](https://github.com/dustinspecker/generator-ng-poly/commits?author=ngbinh) | [\u003cimg src=\"https://avatars.githubusercontent.com/u/2411585?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eRoman C. Podolski\u003c/sub\u003e](https://github.com/RomanCPodolski)\u003cbr /\u003e[💻](https://github.com/dustinspecker/generator-ng-poly/commits?author=RomanCPodolski) | [\u003cimg src=\"https://avatars.githubusercontent.com/u/1423875?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eDavid Brown\u003c/sub\u003e](http://bit.ly/lndbgh)\u003cbr /\u003e[💻](https://github.com/dustinspecker/generator-ng-poly/commits?author=TheOneTheOnlyDavidBrown) [📖](https://github.com/dustinspecker/generator-ng-poly/commits?author=TheOneTheOnlyDavidBrown) | [\u003cimg src=\"https://avatars.githubusercontent.com/u/656302?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eDavid Steinkopff\u003c/sub\u003e](https://github.com/zeitiger)\u003cbr /\u003e[💻](https://github.com/dustinspecker/generator-ng-poly/commits?author=zeitiger) | [\u003cimg src=\"https://avatars.githubusercontent.com/u/1281379?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eFrode Egeland\u003c/sub\u003e](http://www.onsentipster.com)\u003cbr /\u003e[💻](https://github.com/dustinspecker/generator-ng-poly/commits?author=egeland) [⚠️](https://github.com/dustinspecker/generator-ng-poly/commits?author=egeland) | [\u003cimg src=\"https://avatars.githubusercontent.com/u/857700?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eScott Busche\u003c/sub\u003e](https://github.com/busches)\u003cbr /\u003e[💻](https://github.com/dustinspecker/generator-ng-poly/commits?author=busches) |\n| :---: | :---: | :---: | :---: | :---: | :---: | :---: |\n| [\u003cimg src=\"https://avatars.githubusercontent.com/u/4741812?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eRafael Zeffa\u003c/sub\u003e](http://rafaelhz.github.io)\u003cbr /\u003e[💻](https://github.com/dustinspecker/generator-ng-poly/commits?author=rafaelhz) [⚠️](https://github.com/dustinspecker/generator-ng-poly/commits?author=rafaelhz) | [\u003cimg src=\"https://avatars.githubusercontent.com/u/1016365?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003ePatrickJS\u003c/sub\u003e](http://angularclass.com)\u003cbr /\u003e[📖](https://github.com/dustinspecker/generator-ng-poly/commits?author=gdi2290) | [\u003cimg src=\"https://avatars.githubusercontent.com/u/55122?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eTiago de Assis Gonçalves\u003c/sub\u003e](http://br.linkedin.com/in/tiagoassisgoncalves)\u003cbr /\u003e[💻](https://github.com/dustinspecker/generator-ng-poly/commits?author=legiao) | [\u003cimg src=\"https://avatars.githubusercontent.com/u/1576014?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eRuslan Stelmachenko\u003c/sub\u003e](https://github.com/xak2000)\u003cbr /\u003e[💻](https://github.com/dustinspecker/generator-ng-poly/commits?author=xak2000) | [\u003cimg src=\"https://avatars.githubusercontent.com/u/3155133?v=3\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eJeff Arese Vilar\u003c/sub\u003e](https://github.com/Jeffarese)\u003cbr /\u003e[💻](https://github.com/dustinspecker/generator-ng-poly/commits?author=Jeffarese) |\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification.\nContributions of any kind welcome!\n\n### License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdustinspecker%2Fgenerator-ng-poly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdustinspecker%2Fgenerator-ng-poly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdustinspecker%2Fgenerator-ng-poly/lists"}