From c63437a22dac3342f6b1eaab0b1f3644aa33dbbc Mon Sep 17 00:00:00 2001 From: Jared Fuchs Date: Fri, 4 Aug 2017 10:30:30 -0400 Subject: [PATCH 1/3] Adding blueprints for documented versions of components, controllers, and routes. Copies all the same logic in each index.js, but changes the templates --- .../files/__root__/__path__/__name__.js | 29 ++++ .../__templatepath__/__templatename__.hbs | 1 + blueprints/component/index.js | 77 +++++++++ .../files/__root__/__path__/__name__.js | 28 ++++ blueprints/controller/index.js | 5 + .../route/files/__root__/__path__/__name__.js | 28 ++++ .../__templatepath__/__templatename__.hbs | 1 + blueprints/route/index.js | 147 ++++++++++++++++++ 8 files changed, 316 insertions(+) create mode 100644 blueprints/component/files/__root__/__path__/__name__.js create mode 100644 blueprints/component/files/__root__/__templatepath__/__templatename__.hbs create mode 100644 blueprints/component/index.js create mode 100644 blueprints/controller/files/__root__/__path__/__name__.js create mode 100644 blueprints/controller/index.js create mode 100644 blueprints/route/files/__root__/__path__/__name__.js create mode 100644 blueprints/route/files/__root__/__templatepath__/__templatename__.hbs create mode 100644 blueprints/route/index.js diff --git a/blueprints/component/files/__root__/__path__/__name__.js b/blueprints/component/files/__root__/__path__/__name__.js new file mode 100644 index 0000000..65191be --- /dev/null +++ b/blueprints/component/files/__root__/__path__/__name__.js @@ -0,0 +1,29 @@ +import Ember from 'ember'; +<%= importTemplate %> + +/** + * @module + * @augments ember/Component + */ +export default Ember.Component.extend({<%= contents %> + // ------------------------------------------------------------------------- + // Dependencies + + // ------------------------------------------------------------------------- + // Attributes + + // ------------------------------------------------------------------------- + // Actions + + // ------------------------------------------------------------------------- + // Events + + // ------------------------------------------------------------------------- + // Properties + + // ------------------------------------------------------------------------- + // Observers + + // ------------------------------------------------------------------------- + // Methods +}); diff --git a/blueprints/component/files/__root__/__templatepath__/__templatename__.hbs b/blueprints/component/files/__root__/__templatepath__/__templatename__.hbs new file mode 100644 index 0000000..889d9ee --- /dev/null +++ b/blueprints/component/files/__root__/__templatepath__/__templatename__.hbs @@ -0,0 +1 @@ +{{yield}} diff --git a/blueprints/component/index.js b/blueprints/component/index.js new file mode 100644 index 0000000..095298e --- /dev/null +++ b/blueprints/component/index.js @@ -0,0 +1,77 @@ +/* eslint-env node */ +// Note - this is the exact same as ember's normal component index.js + +var stringUtil = require('ember-cli-string-utils'); +var pathUtil = require('ember-cli-path-utils'); +var validComponentName = require('ember-cli-valid-component-name'); +var getPathOption = require('ember-cli-get-component-path-option'); +var path = require('path'); + +var normalizeEntityName = require('ember-cli-normalize-entity-name'); + +module.exports = { + description: 'Generates a component with ember-style-guide documentation in place. Name must contain a hyphen.', + + availableOptions: [ + { + name: 'path', + type: String, + default: 'components', + aliases: [ + { 'no-path': '' } + ] + } + ], + + fileMapTokens: function() { + return { + __path__: function(options) { + if (options.pod) { + return path.join(options.podPath, options.locals.path, options.dasherizedModuleName); + } + return 'components'; + }, + __templatepath__: function(options) { + if (options.pod) { + return path.join(options.podPath, options.locals.path, options.dasherizedModuleName); + } + return 'templates/components'; + }, + __templatename__: function(options) { + if (options.pod) { + return 'template'; + } + return options.dasherizedModuleName; + } + }; + }, + + normalizeEntityName: function(entityName) { + entityName = normalizeEntityName(entityName); + + return validComponentName(entityName); + }, + + locals: function(options) { + var templatePath = ''; + var importTemplate = ''; + var contents = ''; + // if we're in an addon, build import statement + if (options.project.isEmberCLIAddon() || options.inRepoAddon && !options.inDummy) { + if (options.pod) { + templatePath = './template'; + } else { + templatePath = pathUtil.getRelativeParentPath(options.entity.name) + + 'templates/components/' + stringUtil.dasherize(options.entity.name); + } + importTemplate = 'import layout from \'' + templatePath + '\';\n'; + contents = '\n layout'; + } + + return { + importTemplate: importTemplate, + contents: contents, + path: getPathOption(options) + }; + } +}; diff --git a/blueprints/controller/files/__root__/__path__/__name__.js b/blueprints/controller/files/__root__/__path__/__name__.js new file mode 100644 index 0000000..2b0d8f6 --- /dev/null +++ b/blueprints/controller/files/__root__/__path__/__name__.js @@ -0,0 +1,28 @@ +import Ember from 'ember'; + +/** + * @module + * @augments ember/Controller + */ +export default Ember.Controller.extend({ + // ------------------------------------------------------------------------- + // Dependencies + + // ------------------------------------------------------------------------- + // Attributes + + // ------------------------------------------------------------------------- + // Actions + + // ------------------------------------------------------------------------- + // Events + + // ------------------------------------------------------------------------- + // Properties + + // ------------------------------------------------------------------------- + // Observers + + // ------------------------------------------------------------------------- + // Methods +}); diff --git a/blueprints/controller/index.js b/blueprints/controller/index.js new file mode 100644 index 0000000..ef35631 --- /dev/null +++ b/blueprints/controller/index.js @@ -0,0 +1,5 @@ +/* eslint-env node */ + +module.exports = { + description: 'Generates a controller with ember-style-guide documentation in place.' +}; diff --git a/blueprints/route/files/__root__/__path__/__name__.js b/blueprints/route/files/__root__/__path__/__name__.js new file mode 100644 index 0000000..8721f1c --- /dev/null +++ b/blueprints/route/files/__root__/__path__/__name__.js @@ -0,0 +1,28 @@ +import Ember from 'ember'; + +/** + * @module + * @augments ember/Route + */ +export default Ember.Route.extend({ + // ------------------------------------------------------------------------- + // Dependencies + + // ------------------------------------------------------------------------- + // Attributes + + // ------------------------------------------------------------------------- + // Actions + + // ------------------------------------------------------------------------- + // Events + + // ------------------------------------------------------------------------- + // Properties + + // ------------------------------------------------------------------------- + // Observers + + // ------------------------------------------------------------------------- + // Methods +}); diff --git a/blueprints/route/files/__root__/__templatepath__/__templatename__.hbs b/blueprints/route/files/__root__/__templatepath__/__templatename__.hbs new file mode 100644 index 0000000..c24cd68 --- /dev/null +++ b/blueprints/route/files/__root__/__templatepath__/__templatename__.hbs @@ -0,0 +1 @@ +{{outlet}} diff --git a/blueprints/route/index.js b/blueprints/route/index.js new file mode 100644 index 0000000..99f09e1 --- /dev/null +++ b/blueprints/route/index.js @@ -0,0 +1,147 @@ +/* eslint-env node */ + +var fs = require('fs-extra'); +var path = require('path'); +var chalk = require('chalk'); +var stringUtil = require('ember-cli-string-utils'); +var EmberRouterGenerator = require('ember-router-generator'); + +module.exports = { + description: 'Generates a route with ember-style-guide documentation and a template, and registers the route with the router.', + + availableOptions: [ + { + name: 'path', + type: String, + default: '' + }, + { + name: 'skip-router', + type: Boolean, + default: false + }, + { + name: 'reset-namespace', + type: Boolean + } + ], + + fileMapTokens: function() { + return { + __name__: function (options) { + if (options.pod) { + return 'route'; + } + return options.locals.moduleName; + }, + __path__: function(options) { + if (options.pod) { + return path.join(options.podPath, options.locals.moduleName); + } + return 'routes'; + }, + __templatepath__: function(options) { + if (options.pod) { + return path.join(options.podPath, options.locals.moduleName); + } + return 'templates'; + }, + __templatename__: function(options) { + if (options.pod) { + return 'template'; + } + return options.locals.moduleName; + }, + __root__: function(options) { + if (options.inRepoAddon) { + return path.join('lib', options.inRepoAddon, 'addon'); + } + + if (options.inDummy) { + return path.join('tests', 'dummy', 'app'); + } + + if (options.inAddon) { + return 'addon'; + } + + return 'app'; + } + }; + }, + + locals: function(options) { + var moduleName = options.entity.name; + + if (options.resetNamespace) { + moduleName = moduleName.split('/').pop(); + } + + return { + moduleName: stringUtil.dasherize(moduleName) + }; + }, + + shouldEntityTouchRouter: function(name) { + var isIndex = name === 'index'; + var isBasic = name === 'basic'; + var isApplication = name === 'application'; + + return !isBasic && !isIndex && !isApplication; + }, + + shouldTouchRouter: function(name, options) { + var entityTouchesRouter = this.shouldEntityTouchRouter(name); + var isDummy = !!options.dummy; + var isAddon = !!options.project.isEmberCLIAddon(); + var isAddonDummyOrApp = (isDummy === isAddon); + + return (entityTouchesRouter && isAddonDummyOrApp && !options.dryRun && !options.inRepoAddon && !options.skipRouter); + }, + + afterInstall: function(options) { + updateRouter.call(this, 'add', options); + }, + + afterUninstall: function(options) { + updateRouter.call(this, 'remove', options); + } +}; + +function updateRouter(action, options) { + var entity = options.entity; + var actionColorMap = { + add: 'green', + remove: 'red' + }; + var color = actionColorMap[action] || 'gray'; + + if (this.shouldTouchRouter(entity.name, options)) { + writeRoute(action, entity.name, options); + + this.ui.writeLine('updating router'); + this._writeStatusToUI(chalk[color], action + ' route', entity.name); + } +} + +function findRouter(options) { + var routerPathParts = [options.project.root]; + + if (options.dummy && options.project.isEmberCLIAddon()) { + routerPathParts = routerPathParts.concat(['tests', 'dummy', 'app', 'router.js']); + } else { + routerPathParts = routerPathParts.concat(['app', 'router.js']); + } + + return routerPathParts; +} + +function writeRoute(action, name, options) { + var routerPath = path.join.apply(null, findRouter(options)); + var source = fs.readFileSync(routerPath, 'utf-8'); + + var routes = new EmberRouterGenerator(source); + var newRoutes = routes[action](name, options); + + fs.writeFileSync(routerPath, newRoutes.code()); +} From dc98cf401ad3fc0786cf26e0cfcc6633da701ad0 Mon Sep 17 00:00:00 2001 From: Jared Fuchs Date: Fri, 4 Aug 2017 10:37:15 -0400 Subject: [PATCH 2/3] Update README to mention blueprints folder and how to use. --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 90910cf..e396c05 100755 --- a/README.md +++ b/README.md @@ -181,7 +181,10 @@ and `@returns` tags when multiple types are represented. This commenting structure **MUST** be used as a template when creating new Component, Controller, Mixin, or Route files. Route files will not contain all of the represented structures. The "[File Structure](#file-structure-2)" Section -describes what should be placed in each section. +describes what should be placed in each section. The blueprints folder in this repo +contains blueprints to override the default generators with this file structure. +Just copy the blueprints folder to the top level of your Ember app, +and it will override the default generators with their documented versions. ``` ...({ From 7cd9013ac9a6d3d677614f2e52598293e24b61b7 Mon Sep 17 00:00:00 2001 From: Jared Fuchs Date: Fri, 4 Aug 2017 10:43:34 -0400 Subject: [PATCH 3/3] Adding Mixin blueprint as well. --- .../mixin/files/__root__/mixins/__name__.js | 28 +++++++++++++++++++ blueprints/mixin/index.js | 5 ++++ 2 files changed, 33 insertions(+) create mode 100644 blueprints/mixin/files/__root__/mixins/__name__.js create mode 100644 blueprints/mixin/index.js diff --git a/blueprints/mixin/files/__root__/mixins/__name__.js b/blueprints/mixin/files/__root__/mixins/__name__.js new file mode 100644 index 0000000..2398424 --- /dev/null +++ b/blueprints/mixin/files/__root__/mixins/__name__.js @@ -0,0 +1,28 @@ +import Ember from 'ember'; + +/** + * @module + * @augments ember/Mixin + */ +export default Ember.Mixin.create({ + // ------------------------------------------------------------------------- + // Dependencies + + // ------------------------------------------------------------------------- + // Attributes + + // ------------------------------------------------------------------------- + // Actions + + // ------------------------------------------------------------------------- + // Events + + // ------------------------------------------------------------------------- + // Properties + + // ------------------------------------------------------------------------- + // Observers + + // ------------------------------------------------------------------------- + // Methods +}); diff --git a/blueprints/mixin/index.js b/blueprints/mixin/index.js new file mode 100644 index 0000000..279eacb --- /dev/null +++ b/blueprints/mixin/index.js @@ -0,0 +1,5 @@ +/* eslint-env node */ + +module.exports = { + description: 'Generates a mixin with ember-style-guide documentation in place.' +};