diff --git a/gulpfile.js b/gulpfile.js index d70384d591..16656f0de0 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -581,3 +581,13 @@ function buildDemoBundle(opts, done) { }); } + +gulp.task('tooling', function(){ + gulp.src('*tooling/**/*') + .pipe(gulp.dest('dist')); + + watch('tooling/**/*', function(){ + gulp.src('*tooling/**/*') + .pipe(gulp.dest('dist')); + }) +}) diff --git a/tooling/generate.js b/tooling/generate.js index 0ac43da82f..2d6d1bc276 100644 --- a/tooling/generate.js +++ b/tooling/generate.js @@ -1,11 +1,8 @@ -var _ = require('lodash'), - fs = require('fs'), - inquirer = require('inquirer'), +var fs = require('fs'), path = require('path'), - shell = require('shelljs'), - Generate = module.exports; + inquirer = require('inquirer'); -Generate._generators; +Generate = module.exports; Generate.__defineGetter__('generators', function() { if (!Generate._generators) { @@ -15,208 +12,50 @@ Generate.__defineGetter__('generators', function() { return Generate._generators; }); -Generate.log = function log() { - console.log('DEBUG'.red, arguments); -}; - -// options: appDirectory, generator, name Generate.generate = function generate(options) { - Generate.inquirer = inquirer; - // Generate.log('Generate options', options); if (!options) { throw new Error('No options passed to generator'); } - //add optional logger for CLI or other tools - if (options.log) { - Generate.log = options.log; - } - - if (options.generator && !Generate.generators[options.generator]) { - throw new Error('There is no generator available with that name: ' + options.generator + '.'); - } - if (!options.generator) { - options.generator = 'page'; + throw new Error('No generator passed to generate'); } - var generateOptions = { - appDirectory: options.appDirectory, - cssClassName: Generate.cssClassName(options.name), - fileName: Generate.fileName(options.name), - jsClassName: Generate.jsClassName(options.name), - name: options.name, - template: options.generator - }; - - try { - //Try to run the generator if it supplies a run method. - var generator = Generate.generators[options.generator]; - if (generator && generator.run) { - return Generate.generators[options.generator].run(generateOptions); - } else { - return Generate.defaultTemplates(generateOptions); - } - } catch (ex) { - console.log('Error with generation:', ex); - console.log(ex.stack); - } + var GeneratorType = Generate.loadGenerator(options.generator); + return new GeneratorType(options).run(); }; -Generate.defaultTemplates = function defaultTemplates(options) { - var template = options.template ? options.template : 'page'; - options.rootDirectory = options.rootDirectory || path.join('app'); - var savePath = path.join(options.appDirectory, options.rootDirectory, options.fileName); - - var templates = Generate.loadGeneratorTemplates(path.join(__dirname, 'generators', options.template)); - - templates.forEach(function(template) { - var templatePath = template.file; - options.templatePath = templatePath; - var renderedTemplate = Generate.renderTemplateFromFile(options); - var saveFilePath = path.join(savePath, [options.fileName, template.type].join('')); - // console.log('renderedTemplate', renderedTemplate, 'saving to', saveFilePath); - console.log('√ Create'.blue, path.relative(options.appDirectory, saveFilePath)); - fs.writeFileSync(saveFilePath, renderedTemplate); - }); -} - -Generate.loadGeneratorTemplates = function loadGeneratorTemplates(generatorPath) { - var templates = []; - fs.readdirSync(generatorPath) - .forEach(function(template) { - var type; - // Go through all the files in the folder, grab the templates, read in the file contents - // return as template type, contents - if (template.indexOf('.tmpl') == -1) { - return; - } - - templates.push({file: path.join(generatorPath, template), type: path.extname(template)}); - }); - - return templates; -}; - -Generate.loadGenerator = function loadGenerator(file) { - var generatorPath = path.join(__dirname, 'generators', file); +Generate.loadGenerator = function loadGenerator(generator) { var generateModule; try { - generateModule = require(generatorPath); - } catch (ex) { - Generate.log('Error loading generator module', ex); - Generate.log(ex.stack); + generateModule = require(path.join(__dirname, 'generators', generator)); + } catch (err) { + if (err.code === 'MODULE_NOT_FOUND') { + throw new Error('There is no generator available with the name ' + generator + '.'); + } else { + throw err; + } } return generateModule; }; +/* + Return array of filenames in the generators directory + */ Generate.loadGenerators = function loadGenerators() { var generators = {}; - fs.readdirSync(path.join(__dirname, 'generators')) - .forEach(function (file) { - if (file.indexOf('.') !== -1) { - return; - } - var generatorName = file.replace('.js', ''); - var generator = Generate.loadGenerator(generatorName); - generators[generatorName] = generator; - }); + try { + generators = fs.readdirSync(path.join(__dirname, 'generators')); + } catch(err) { + throw new Error('There was an error loading the generators list', err); + } return generators; }; -/* - Will take options to render an html, js, or scss template. - options: - they differ based on what is needed in template - For JavaScript file: filename, jsClassName - For HTML file: name, nameUppercased - templatePath: the path of the template to render (html/js/scss), ex: '/path/to/page.tmpl.html' -*/ -Generate.renderTemplateFromFile = function renderTemplateFromFile(options) { - var templateContents = fs.readFileSync(options.templatePath, 'utf8'); - var templateCompiler = _.template(templateContents); - var result = templateCompiler(options); - return result; -}; - -// Tabs - name = name of the page with the tabs, -// tabs = array of the tabs to create. -// Generate.tabPages = function tabPages(appDirectory, name, tabs) { -// Generate.createScaffoldDirectories(appDirectory, 'tabs', name); -// -// // Generate page with tabs: -// var tabsfileName = Generate.fileName(name); -// -// var tabsHtml = Generate.generateTabsHtmlTemplate(appDirectory, name, tabs); -// var tabsJs = Generate.generateTabsJsTemplate(appDirectory, name, tabs); -// // var tabsScss = Generate.generateTabsScssTemplate(appDirectory, name, tabs); -// var pagePath = path.join(appDirectory, 'app', tabsfileName), -// jsPath = path.join(pagePath, [tabsfileName, '.js'].join('')), -// htmlPath = path.join(pagePath, [tabsfileName, '.html'].join('')); -// // scssPath = path.join(pagePath, [tabsfileName, '.scss'].join('')); -// -// tabs.forEach(function(tab) { -// Generate.createScaffoldDirectories(appDirectory, 'tabs', tab); -// var tabJs = Generate.generateJsTemplate(appDirectory, tab); -// var tabHtml = Generate.generateHtmlTemplate(appDirectory, tab); -// -// }) -// }; - -Generate.generateTabJsTemplate = function generateTabJsTemplate(appDirectory, name) { - throw new Error('not implemented'); -}; - -Generate.generateTabsJsTemplate = function generateTabsJsTemplate(appDirectory, name, tabs) { - // import {NavController, Page} from 'ionic/ionic'; - // <% _.forEach(tabs, function(tab) { %> - // import {<%= tab.jsClassName %>} from '../<%= tab.filename %>/<%= tab.filename %>'; - // <% }); %> - // @Page({ - // templateUrl: 'app/<%= filename %>/<%= filename %>.html', - // providers: [DataService] - // }) - // class <%= jsClassName %> { - // constructor(nav: NavController) { - // // set the root pages for each tab - // <% _.forEach(tabs, function(tab) { %> - // this.{<%= tab.jsClassName %>} = <%= tab.jsClassName %>; - // <% }); %> - // } - // } - var fileName = Generate.fileName(name); - var jsClassName = Generate.jsClassName(name); - - var tabsData = []; - tabs.forEach(function(tab) { - var tabObj = { name: tab, filename: Generate.fileName(tab), jsClassName: Generate.jsClassName(tab)}; - tabsData.push(tabObj); +Generate.printAvailableGenerators = function printAvailableGenerators() { + console.log('Available generators:'.blue); + Generate.generators.forEach(function(generator){ + console.log(' *'.blue, generator); }); - - var tabsHtmlTemplatePath = path.join(__dirname, 'tabs.tmpl.js'); - return Generate.renderTemplateFromFile({tabs: tabsData, templatePath: tabsHtmlTemplatePath, filename: fileName, jsClassName: jsClassName }); -}; - -Generate.createScaffoldDirectories = function createScaffoldDirectories(options) { - console.log('createScaffoldDirectories', options); - // Generate.log('Create', options.appDirectory, options.fileName); - var componentPath = path.join(options.appDirectory, 'app', options.componentDirectory, options.fileName); - shell.mkdir('-p', componentPath); -}; - -Generate.fileName = function fileName(name) { - return name.replace(/([a-z])([A-Z])/g, '$1-$2').replace('_', '-').toLowerCase(); -}; - -Generate.cssClassName = function cssClassName(name) { - return Generate.fileName(name); } - -Generate.capitalizeName = function capitalizeName(name) { - return name.charAt(0).toUpperCase() + name.slice(1); -}; - -Generate.jsClassName = function jsClassName(name) { - return _.capitalize(_.camelCase(name)); -}; diff --git a/tooling/generator.js b/tooling/generator.js new file mode 100644 index 0000000000..f512d4e751 --- /dev/null +++ b/tooling/generator.js @@ -0,0 +1,67 @@ +var _ = require('lodash'), + fs = require('fs'), + path = require('path'), + shell = require('shelljs'); + +module.exports = Generator; + +function Generator(options) { + this.name = options.name; + this.type = options.generator; + this.appDirectory = options.appDirectory; +} + +Generator.prototype.run = function(){ + this.makeDirectories(); + this.renderTemplates(); +} + +Generator.prototype.makeDirectories = function(){ + if (!this.directory) { + throw new Error('Generators must define their directory in their constructor'); + } + shell.mkdir('-p', path.join(this.appDirectory, this.directory, this.name)); +} + +Generator.prototype.renderTemplates = function renderTemplates() { + var templates = this.loadTemplates(); + + templates.forEach(function(template) { + var renderedTemplate = this.renderTemplate(template); + var renderedTemplateDest = path.join(this.appDirectory, this.directory, this.name, this.name + template.extension); + console.log('√ Create'.blue, path.relative(this.appDirectory, renderedTemplateDest)); + fs.writeFileSync(renderedTemplateDest, renderedTemplate); + }, this); +} + +Generator.prototype.loadTemplates = function() { + var generatorPath = path.join(__dirname, 'generators', this.type); + var templates = []; + fs.readdirSync(generatorPath) + .forEach(function(template) { + var type; + // Go through all the files in the folder, grab the templates, read in the file contents + // return as template type, contents + if (template.indexOf('.tmpl') == -1) { + return; + } + + templates.push({path: path.join(generatorPath, template), extension: path.extname(template)}); + }, this); + + return templates; +}; + +Generator.prototype.renderTemplate = function(template) { + var templateVars = { + fileName: _.kebabCase(this.name), + directory: this.directory, + cssClassName: _.kebabCase(this.name), + jsClassName: _.capitalize(_.camelCase(this.name)) + } + + var templateContents = fs.readFileSync(template.path, 'utf8'); + var templateCompiler = _.template(templateContents); + var result = templateCompiler(templateVars); + return result; +}; \ No newline at end of file diff --git a/tooling/generators/component/component.tmpl.html b/tooling/generators/component/component.tmpl.html index c8fcf93d22..8ed6082033 100644 --- a/tooling/generators/component/component.tmpl.html +++ b/tooling/generators/component/component.tmpl.html @@ -1,3 +1,9 @@ -
- <%= jsClassName %> + +
+ {{text}}
diff --git a/tooling/generators/component/component.tmpl.js b/tooling/generators/component/component.tmpl.js index dccfeda66f..9579bfd3f0 100644 --- a/tooling/generators/component/component.tmpl.js +++ b/tooling/generators/component/component.tmpl.js @@ -1,14 +1,13 @@ -import {Component, NgIf} from 'angular2/angular2'; -import {NavController} from 'ionic/ionic'; +import {Component} from 'angular2/core'; +import {IONIC_DIRECTIVES} from 'ionic/ionic'; @Component({ - directives: [NgIf], - properties: ['value'], //Change to be whatever properties you want, ex: <<%= fileName %> value="5"> selector: '<%= fileName %>', - templateUrl: 'app/<%= fileName %>/<%= fileName %>.html' + templateUrl: '<%= directory %>/<%= fileName %>/<%= fileName %>.html', + directives: [IONIC_DIRECTIVES] // makes all Ionic directives available to your component }) export class <%= jsClassName %> { - constructor(nav: NavController) { - this.nav = nav; + constructor() { + this.text = 'Hello World, I\'m <%= jsClassName %>'; } } diff --git a/tooling/generators/component/index.js b/tooling/generators/component/index.js index 5df36f8499..192312eeb5 100644 --- a/tooling/generators/component/index.js +++ b/tooling/generators/component/index.js @@ -1,28 +1,12 @@ -var fs = require('fs'), - Generator = module.exports, - Generate = require('../../generate'), - path = require('path'), - Q = require('q'); -/* - @options - name: Page name - appDirectory: App directory of where to save file -*/ -Generator.run = function run(options) { - Generate.createScaffoldDirectories({appDirectory: options.appDirectory, componentDirectory: 'components', fileName: options.fileName}); - options.rootDirectory = options.rootDirectory || path.join('app', 'components'); +var path = require('path'), + Generator = require('../../generator'); - var savePath = path.join(options.appDirectory, options.rootDirectory, options.fileName); +module.exports = ComponentGenerator; - var templates = Generate.loadGeneratorTemplates(__dirname); +function ComponentGenerator(options) { + Generator.call(this, options); + this.directory = path.join('app', 'components'); +} - templates.forEach(function(template) { - options.templatePath = template.file; - var renderedTemplate = Generate.renderTemplateFromFile(options); - var saveFilePath = path.join(savePath, [options.fileName, template.type].join('')); - // console.log('renderedTemplate', renderedTemplate, 'saving to', saveFilePath); - console.log('√ Create'.blue, path.relative(options.appDirectory, saveFilePath)); - fs.writeFileSync(saveFilePath, renderedTemplate); - }); -}; +ComponentGenerator.prototype = Object.create(Generator.prototype);