Skip to content

Commit

Permalink
#41 component creation allows names with letters, numbers and dashes …
Browse files Browse the repository at this point in the history
…- dashes are no longer ignored in template files
  • Loading branch information
ernscht committed Nov 22, 2015
1 parent 027ac76 commit c657985
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 55 deletions.
15 changes: 8 additions & 7 deletions app/templates/app/helpers/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ module.exports = function () {

try {
var context = arguments[arguments.length - 1],
contextDataRoot = context && context.data && context.data.root ? context.data.root : {}, // default component data from controller & view
contextDataRoot = context && context.data && context.data.root ? context.data.root : {}, // default component data from controller & view
name = 'string' === typeof arguments[0] ? arguments[0] : context.hash.name,
templateFile = context.hash.template || name.replace(/\s/g, '').replace(/-/g, '').toLowerCase(),
dataFile = name.replace(/\s/g, '').replace(/-/g, '').toLowerCase(), // default data file
passedData = null, // passed data to component helper
componentData = {}; // collected component data
folder = name.replace(/[^A-Za-z0-9-]/g, ''),
templateFile = context.hash.template || folder.toLowerCase(),
dataFile = folder.toLowerCase(), // default data file
passedData = null, // passed data to component helper
componentData = {}; // collected component data

if (arguments.length >= 3) {
if ('object' === typeof arguments[1]) {
Expand All @@ -57,7 +58,7 @@ module.exports = function () {
cfg.nitro.base_path,
component.path,
'/',
name,
folder,
'/',
templateFile + '.' + cfg.nitro.view_file_extension
);
Expand All @@ -68,7 +69,7 @@ module.exports = function () {
cfg.nitro.base_path,
component.path,
'/',
name,
folder,
'/_data/',
jsonFilename
);
Expand Down
34 changes: 22 additions & 12 deletions component/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,13 @@ module.exports = generators.Base.extend({
message: 'What\'s the name of your component?',
default: this.name,
validate: function validateString(value) {
return _.isString(value) && !_.isEmpty(value);
if (!_.isString(value) || _.isEmpty(value)) {
return 'Component name has to be a valid string';
}
if (/^[0-9]/.test(value)) {
return 'Component name must not start with a Number';
}
return true;
}
},
{
Expand All @@ -72,7 +78,13 @@ module.exports = generators.Base.extend({
{
name: 'decorator',
message: 'Would you like to create a JS decorator? Type your desired name or leave empty.',
default: this.options.decorator || ''
default: this.options.decorator || '',
validate: function validateString(value) {
if (_.isString(value) && /^[0-9]/.test(value)) {
return 'Component decorator must not start with a Number';
}
return true;
}
}
], function (props) {
this.name = props.name;
Expand Down Expand Up @@ -109,18 +121,16 @@ module.exports = generators.Base.extend({
this.log(msg);

var component = this.cfg.nitro.components[this.options.type];

var folder = this.name.replace(/[^A-Za-z0-9-]/g, '');
var files = glob.sync('**/*', {cwd: this.destinationPath(component.template), nodir: true, dot: true});
var ignores = [
// files to ignore
'.DS_Store'
];

var user = {
name: '',
email: ''
};

var gitConfig = gitconfig.sync();

if (!_.isEmpty(gitConfig) && !_.isEmpty(gitConfig.user)) {
Expand All @@ -132,21 +142,21 @@ module.exports = generators.Base.extend({
user: user,
component: {
name: this.name, // Component name, eg. Main navigation
js: _.capitalize(_.camelCase(this.name)), // Component name for use in JS files, eg. MainNavigation
js: _.capitalize(_.camelCase(this.name.replace(/^[0-9]+/, ''))), // Component name for use in JS files, eg. MainNavigation
css: _.kebabCase(this.name), // Component name for use in CSS files, eg. main-navigation
prefix: component.component_prefix || null, // CSS class prefix, eg. mod
prefix: component.component_prefix || null, // CSS class prefix, eg. m
type: this.options.type, // Component type, eg. atom, molecule etc.
file: _.kebabCase(this.name).replace(/-/g, '') // Component filename, eg. mainnavigation
file: this.name.replace(/[^A-Za-z0-9-]/g, '').toLowerCase() // Component filename, eg. main-navigation
},
modifier: {
name: this.options.modifier, // Modifier name, eg. Highlight
css: _.kebabCase(this.options.modifier), // Modifier name for use in CSS files, eg. highlight
file: _.kebabCase(this.options.modifier).replace(/-/g, '') // Modifier filename, eg.highlight
file: this.options.modifier.replace(/[^A-Za-z0-9-]/g, '').toLowerCase() // Modifier filename, eg.highlight
},
decorator: {
name: this.options.decorator, // Decorator name, eg. Highlight
js: _.capitalize(_.camelCase(this.options.decorator)), // Decorator name for use in JS files, eg. Highlight
file: _.kebabCase(this.options.decorator).replace(/-/g, '') // Modifier filename, eg.highlight
js: _.capitalize(_.camelCase(this.options.decorator.replace(/^[0-9]+/, ''))), // Decorator name for use in JS files, eg. Highlight
file: this.options.decorator.replace(/[^A-Za-z0-9-]/g, '').toLowerCase() // Modifier filename, eg.highlight
}
};

Expand Down Expand Up @@ -181,7 +191,7 @@ module.exports = generators.Base.extend({
filename = path.join(path.dirname(filename), path.basename(filename).replace(key, value));
});

this.fs.copyTpl(this.destinationPath(component.template + '/' + file), this.destinationPath(component.path + '/' + this.name + '/' + filename), replacements);
this.fs.copyTpl(this.destinationPath(component.template + '/' + file), this.destinationPath(component.path + '/' + folder + '/' + filename), replacements);
}, this);
}
}
Expand Down
109 changes: 73 additions & 36 deletions spec/componentSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var configData = {
};

describe('nitro:component', function () {
describe('when creating a component "Test"', function () {
describe('when creating a component "Test" (organism)', function () {
describe('but no modifier and decorator is given', function () {
beforeEach(function (done) {
helpers.run(path.join(__dirname, '../component'))
Expand Down Expand Up @@ -118,88 +118,125 @@ describe('nitro:component', function () {
});
});

describe('when creating a component "NavMain" with a modifier and decorator "SpecialCase"', function () {
describe('when creating a component "NavMain" (molecule) with a modifier and decorator "SpecialCase"', function () {
beforeEach(function (done) {
helpers.run(path.join(__dirname, '../component'))
.inDir(path.join(os.tmpdir(), './temp-test'), function (dir) {
fs.copySync(path.join(__dirname, '../app/templates/project'), path.join(dir, 'project'));
fs.copySync(path.join(__dirname, '../app/templates/config.json'), path.join(dir, 'config.json'));
})
.withPrompts({name: 'NavMain', type: 'organism', modifier: 'SpecialCase', decorator: 'SpecialCase'})
.withPrompts({name: 'NavMain', type: 'molecule', modifier: 'SpecialCase', decorator: 'SpecialCase'})
.on('end', done);
});

it('the component and modifier/decorator files are created', function () {
assert.file([
'components/organisms/NavMain',
'components/organisms/NavMain/navmain.html',
'components/organisms/NavMain/_data/navmain.json',
'components/organisms/NavMain/_data/navmain-specialcase.json',
'components/organisms/NavMain/css/navmain.less',
'components/organisms/NavMain/css/modifier/navmain-specialcase.less',
'components/organisms/NavMain/js/navmain.js',
'components/organisms/NavMain/js/decorator/navmain-specialcase.js',
'components/organisms/NavMain/spec/navmainSpec.js'
'components/molecules/NavMain',
'components/molecules/NavMain/navmain.html',
'components/molecules/NavMain/_data/navmain.json',
'components/molecules/NavMain/_data/navmain-specialcase.json',
'components/molecules/NavMain/css/navmain.less',
'components/molecules/NavMain/css/modifier/navmain-specialcase.less',
'components/molecules/NavMain/js/navmain.js',
'components/molecules/NavMain/js/decorator/navmain-specialcase.js',
'components/molecules/NavMain/spec/navmainSpec.js'
]);
});

it('the component css class is o-nav-main', function () {
assert.fileContent([['components/organisms/NavMain/css/navmain.less', /\.o-nav-main \{/]]);
it('the component css class is m-nav-main', function () {
assert.fileContent([['components/molecules/NavMain/css/navmain.less', /\.m-nav-main \{/]]);
});

it('the modifier css class is o-nav-main--special-case', function () {
assert.fileContent([['components/organisms/NavMain/css/modifier/navmain-specialcase.less', /\.o-nav-main--special-case \{/]]);
it('the modifier css class is m-nav-main--special-case', function () {
assert.fileContent([['components/molecules/NavMain/css/modifier/navmain-specialcase.less', /\.m-nav-main--special-case \{/]]);
});

it('the component js class is T.Module.NavMain', function () {
assert.fileContent([['components/organisms/NavMain/js/navmain.js', /T\.Module\.NavMain =/]]);
assert.fileContent([['components/molecules/NavMain/js/navmain.js', /T\.Module\.NavMain =/]]);
});

it('the decorator js class is T.Module.NavMain.SpecialCase', function () {
assert.fileContent([['components/organisms/NavMain/js/decorator/navmain-specialcase.js', /T\.Module\.NavMain\.SpecialCase =/]]);
assert.fileContent([['components/molecules/NavMain/js/decorator/navmain-specialcase.js', /T\.Module\.NavMain\.SpecialCase =/]]);
});
});

describe('when creating a component "nav-main" with a modifier and decorator "special-case"', function () {
describe('when creating a component "nav-main" (molecule) with a modifier and decorator "special-case"', function () {
beforeEach(function (done) {
helpers.run(path.join(__dirname, '../component'))
.inDir(path.join(os.tmpdir(), './temp-test'), function (dir) {
fs.copySync(path.join(__dirname, '../app/templates/project'), path.join(dir, 'project'));
fs.writeFileSync(path.join(dir, 'config.json'), ejs.render(fs.readFileSync(path.join(__dirname, '../app/templates/config.json'), 'utf8'), configData));
})
.withPrompts({name: 'nav-main', type: 'organism', modifier: 'special-case', decorator: 'special-case'})
.withPrompts({name: 'nav-main', type: 'molecule', modifier: 'special-case', decorator: 'special-case'})
.on('end', done);
});

it('the component and modifier/decorator files are created', function () {
assert.file([
'components/organisms/nav-main',
'components/organisms/nav-main/navmain.html',
'components/organisms/nav-main/_data/navmain.json',
'components/organisms/nav-main/_data/navmain-specialcase.json',
'components/organisms/nav-main/css/navmain.less',
'components/organisms/nav-main/css/modifier/navmain-specialcase.less',
'components/organisms/nav-main/js/navmain.js',
'components/organisms/nav-main/js/decorator/navmain-specialcase.js',
'components/organisms/nav-main/spec/navmainSpec.js'
'components/molecules/nav-main',
'components/molecules/nav-main/nav-main.html',
'components/molecules/nav-main/_data/nav-main.json',
'components/molecules/nav-main/_data/nav-main-special-case.json',
'components/molecules/nav-main/css/nav-main.less',
'components/molecules/nav-main/css/modifier/nav-main-special-case.less',
'components/molecules/nav-main/js/nav-main.js',
'components/molecules/nav-main/js/decorator/nav-main-special-case.js',
'components/molecules/nav-main/spec/nav-mainSpec.js'
]);
});

it('the component css class is o-nav-main', function () {
assert.fileContent([['components/organisms/nav-main/css/navmain.less', /\.o-nav-main \{/]]);
it('the component css class is m-nav-main', function () {
assert.fileContent([['components/molecules/nav-main/css/nav-main.less', /\.m-nav-main \{/]]);
});

it('the modifier css class is o-nav-main--special-case', function () {
assert.fileContent([['components/organisms/nav-main/css/modifier/navmain-specialcase.less', /\.o-nav-main--special-case \{/]]);
it('the modifier css class is m-nav-main--special-case', function () {
assert.fileContent([['components/molecules/nav-main/css/modifier/nav-main-special-case.less', /\.m-nav-main--special-case \{/]]);
});

it('the component js class is T.Module.NavMain', function () {
assert.fileContent([['components/organisms/nav-main/js/navmain.js', /T\.Module\.NavMain =/]]);
assert.fileContent([['components/molecules/nav-main/js/nav-main.js', /T\.Module\.NavMain =/]]);
});

it('the decorator js class is T.Module.NavMain.SpecialCase', function () {
assert.fileContent([['components/organisms/nav-main/js/decorator/navmain-specialcase.js', /T\.Module\.NavMain\.SpecialCase =/]]);
assert.fileContent([['components/molecules/nav-main/js/decorator/nav-main-special-case.js', /T\.Module\.NavMain\.SpecialCase =/]]);
});
});
});

describe('when creating a component "Nav Main" (molecule) with a modifier "Light.Blue"', function () {
beforeEach(function (done) {
helpers.run(path.join(__dirname, '../component'))
.inDir(path.join(os.tmpdir(), './temp-test'), function (dir) {
fs.copySync(path.join(__dirname, '../app/templates/project'), path.join(dir, 'project'));
fs.writeFileSync(path.join(dir, 'config.json'), ejs.render(fs.readFileSync(path.join(__dirname, '../app/templates/config.json'), 'utf8'), configData));
})
.withPrompts({name: 'Nav Main', type: 'molecule', modifier: 'Light.Blue'})
.on('end', done);
});

it('the component and decorator files are created', function () {
assert.file([
'components/molecules/NavMain',
'components/molecules/NavMain/navmain.html',
'components/molecules/NavMain/_data/navmain.json',
'components/molecules/NavMain/_data/navmain-lightblue.json',
'components/molecules/NavMain/css/navmain.less',
'components/molecules/NavMain/css/modifier/navmain-lightblue.less',
'components/molecules/NavMain/js/navmain.js',
'components/molecules/NavMain/spec/navmainSpec.js'
]);
});

it('the component css class is m-nav-main', function () {
assert.fileContent([['components/molecules/NavMain/css/navmain.less', /\.m-nav-main \{/]]);
});

it('the modifier css class is m-nav-main--light-blue', function () {
assert.fileContent([['components/molecules/NavMain/css/modifier/navmain-lightblue.less', /\.m-nav-main--light-blue \{/]]);
});

it('the component js class is T.Module.NavMain', function () {
assert.fileContent([['components/molecules/NavMain/js/navmain.js', /T\.Module\.NavMain =/]]);
});

});
});

0 comments on commit c657985

Please sign in to comment.