Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding blueprints for documented ember objects #80

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

```
...({
Expand Down
29 changes: 29 additions & 0 deletions blueprints/component/files/__root__/__path__/__name__.js
Original file line number Diff line number Diff line change
@@ -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
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{yield}}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the template can be removed since it's no different from the original blueprint.

77 changes: 77 additions & 0 deletions blueprints/component/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* eslint-env node */
// Note - this is the exact same as ember's normal component index.js
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't dug deep enough into this PR yet so this may be a premature question, but if this content is the same as what is already present why do we need this file?


var stringUtil = require('ember-cli-string-utils');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 = '';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

} else {
templatePath = pathUtil.getRelativeParentPath(options.entity.name) +
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'templates/components/' + stringUtil.dasherize(options.entity.name);
}
importTemplate = 'import layout from \'' + templatePath + '\';\n';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

contents = '\n layout';
}

return {
importTemplate: importTemplate,
contents: contents,
path: getPathOption(options)
};
}
};
28 changes: 28 additions & 0 deletions blueprints/controller/files/__root__/__path__/__name__.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Ember from 'ember';

/**
* @module
* @augments ember/Controller
*/
export default Ember.Controller.extend({
// -------------------------------------------------------------------------
// Dependencies

// -------------------------------------------------------------------------
// Attributes

// -------------------------------------------------------------------------
// Actions

// -------------------------------------------------------------------------
// Events

// -------------------------------------------------------------------------
// Properties

// -------------------------------------------------------------------------
// Observers

// -------------------------------------------------------------------------
// Methods
});
5 changes: 5 additions & 0 deletions blueprints/controller/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* eslint-env node */

module.exports = {
description: 'Generates a controller with ember-style-guide documentation in place.'
};
28 changes: 28 additions & 0 deletions blueprints/mixin/files/__root__/mixins/__name__.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Ember from 'ember';

/**
* @module
* @augments ember/Mixin
*/
export default Ember.Mixin.create({
// -------------------------------------------------------------------------
// Dependencies

// -------------------------------------------------------------------------
// Attributes

// -------------------------------------------------------------------------
// Actions

// -------------------------------------------------------------------------
// Events

// -------------------------------------------------------------------------
// Properties

// -------------------------------------------------------------------------
// Observers

// -------------------------------------------------------------------------
// Methods
});
5 changes: 5 additions & 0 deletions blueprints/mixin/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* eslint-env node */

module.exports = {
description: 'Generates a mixin with ember-style-guide documentation in place.'
};
28 changes: 28 additions & 0 deletions blueprints/route/files/__root__/__path__/__name__.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Ember from 'ember';

/**
* @module
* @augments ember/Route
*/
export default Ember.Route.extend({
// -------------------------------------------------------------------------
// Dependencies

// -------------------------------------------------------------------------
// Attributes

// -------------------------------------------------------------------------
// Actions

// -------------------------------------------------------------------------
// Events

// -------------------------------------------------------------------------
// Properties

// -------------------------------------------------------------------------
// Observers

// -------------------------------------------------------------------------
// Methods
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{outlet}}
147 changes: 147 additions & 0 deletions blueprints/route/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/* eslint-env node */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this file like blueprints/component/index.js, where its the same content as already exists? If so, the same question I posed for blueprints/component/index.js also applies to this one.


var fs = require('fs-extra');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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());
}