diff --git a/index.js b/index.js
new file mode 100644
index 0000000000..4e52b93f40
--- /dev/null
+++ b/index.js
@@ -0,0 +1,3 @@
+module.exports = {
+ generate: require('./tooling/generate')
+};
diff --git a/package.json b/package.json
index 4ca03dd74f..98da731c23 100644
--- a/package.json
+++ b/package.json
@@ -6,13 +6,16 @@
"type": "git",
"url": "https://github.com/driftyco/ionic2.git"
},
+ "main": "index.js",
"scripts": {
"test": "gulp karma",
+ "test:generators": "jasmine-node ./tooling/spec",
"link": "npm install && gulp src && npm link"
},
"dependencies": {
"angular2": "2.0.0-alpha.44",
"es6-shim": "^0.33.6",
+ "lodash": "^3.10.1",
"@reactivex/rxjs": "5.0.0-alpha.4",
"reflect-metadata": "0.1.1",
"zone.js": "0.5.8"
@@ -47,7 +50,6 @@
"karma-chrome-launcher": "^0.1.7",
"karma-jasmine": "^0.3.5",
"lazypipe": "^0.2.3",
- "lodash": "^2.4.1",
"lunr": "^0.5.12",
"minimist": "^1.1.3",
"mkdirp": "^0.5.1",
diff --git a/tooling/generate.js b/tooling/generate.js
new file mode 100644
index 0000000000..2a2115c4d1
--- /dev/null
+++ b/tooling/generate.js
@@ -0,0 +1,229 @@
+var _ = require('lodash'),
+ fs = require('fs'),
+ // logging = require('../logging'),
+ path = require('path'),
+ shell = require('shelljs'),
+ Generate = module.exports;
+
+Generate._generators;
+
+Generate.__defineGetter__('generators', function() {
+ if (!Generate._generators) {
+ Generate._generators = Generate.loadGenerators();
+ }
+
+ return Generate._generators;
+});
+
+// options: appDirectory, generatorName, name
+Generate.generate = function generate(options) {
+ // console.log('Generate options', options);
+ if (!options) {
+ throw new Error('No options passed to generator');
+ }
+ // var generatorPath = path.join(__dirname, 'generators');
+ if (!options.generatorName) {
+ options.generatorName = 'page';
+ }
+
+ var generateOptions = {
+ appDirectory: options.appDirectory,
+ fileAndClassName: Generate.fileAndClassName(options.name),
+ javascriptClassName: Generate.javascriptClassName(options.name),
+ name: options.name
+ };
+
+ Generate.createScaffoldDirectories({appDirectory: options.appDirectory, fileAndClassName: generateOptions.fileAndClassName});
+
+ return Generate.generators[options.generatorName].run(generateOptions);
+};
+
+Generate.loadGeneratorTemplates = function loadGeneratorTemplates(generatorPath) {
+ // var generatorPath = path.join(__dirname, 'generators', generatorName);
+ 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: template, type: path.extname(template)});
+ });
+
+ return templates;
+};
+
+Generate.loadGenerator = function loadGenerator(file) {
+ var generatorPath = path.join(__dirname, 'generators', file);
+ var generateModule;
+ try {
+ generateModule = require(generatorPath);
+ } catch (ex) {
+ console.log('Error loading generator module', ex);
+ }
+ return generateModule;//page
+};
+
+Generate.loadGenerators = function loadGenerators() {
+ var generators = {};
+ fs.readdirSync(path.join(__dirname, 'generators'))
+ .forEach(function (file) {
+ var generatorName = file.replace('.js', '');
+ generators[generatorName] = Generate.loadGenerator(generatorName);
+ });
+ 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, javascriptClassName
+ 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;
+};
+
+/*
+ Will take options to render the basic page javascript template
+ the name of the component/page being rendered, ex: 'IonicTest'
+*/
+Generate.generateJsTemplate = function generateJsTemplate(name) {
+ var jsTemplatePath = path.join(__dirname, 'page.tmpl.js');
+ var options = { javascriptClassName: Generate.javascriptClassName(name), filename: Generate.fileAndClassName(name), templatePath: jsTemplatePath};
+ return Generate.renderTemplateFromFile(options);
+};
+
+/*
+ Will take options to render the basic page html template
+ the name of the component/page being rendered, ex: 'IonicTest'
+*/
+Generate.generateHtmlTemplate = function generateHtmlTemplate(name) {
+ var htmlTemplatePath = path.join(__dirname, 'page.tmpl.html');
+ return Generate.renderTemplateFromFile({ name: Generate.fileAndClassName(name), capitalizedName: Generate.capitalizeName(name) ,templatePath: htmlTemplatePath});
+};
+
+Generate.generateScssTemplate = function generateScssTemplate(name) {
+ var scssTemplatePath = path.join(__dirname, 'page.tmpl.scss');
+ return Generate.renderTemplateFromFile({ name: Generate.fileAndClassName(name), templatePath: scssTemplatePath});
+};
+
+// 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, name);
+
+ // Generate page with tabs:
+ var tabsFileAndClassName = Generate.fileAndClassName(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, 'www', 'app', tabsFileAndClassName),
+ jsPath = path.join(pagePath, [tabsFileAndClassName, '.js'].join('')),
+ htmlPath = path.join(pagePath, [tabsFileAndClassName, '.html'].join(''));
+ // scssPath = path.join(pagePath, [tabsFileAndClassName, '.scss'].join(''));
+
+ tabs.forEach(function(tab) {
+ Generate.createScaffoldDirectories(appDirectory, tab);
+ var tabJs = Generate.generateJsTemplate(appDirectory, tab);
+ var tabHtml = Generate.generateHtmlTemplate(appDirectory, tab);
+
+ })
+};
+
+Generate.generateTabHtmlTemplate = function generateTabHtmlTemplate(appDirectory, name) {
+ throw new Error('not implemented');
+};
+
+Generate.generateTabsHtmlTemplate = function generateTabsHtmlTemplate(appDirectory, name, tabs) {
+ // throw new Error('not implemented');
+ var fileAndClassName = Generate.fileAndClassName(name);
+ var javascriptClassName = Generate.javascriptClassName(name);
+ // Generate.createScaffoldDirectories(appDirectory, fileAndClassName);
+
+ var tabsData = [];
+ tabs.forEach(function(tab) {
+ var tabObj = { name: tab, javascriptClassName: Generate.javascriptClassName(tab)};
+ tabsData.push(tabObj);
+ });
+
+ var tabsHtmlTemplatePath = path.join(__dirname, 'tabs.tmpl.html');
+ return Generate.renderTemplateFromFile({tabs: tabsData, templatePath: tabsHtmlTemplatePath });
+
+ //
+ // <% _.forEach(tabs, function(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.javascriptClassName %>} from '../<%= tab.filename %>/<%= tab.filename %>';
+ // <% }); %>
+ // @Page({
+ // templateUrl: 'app/<%= filename %>/<%= filename %>.html',
+ // providers: [DataService]
+ // })
+ // class <%= javascriptClassName %> {
+ // constructor(nav: NavController) {
+ // // set the root pages for each tab
+ // <% _.forEach(tabs, function(tab) { %>
+ // this.{<%= tab.javascriptClassName %>} = <%= tab.javascriptClassName %>;
+ // <% }); %>
+ // }
+ // }
+ var fileAndClassName = Generate.fileAndClassName(name);
+ var javascriptClassName = Generate.javascriptClassName(name);
+
+ var tabsData = [];
+ tabs.forEach(function(tab) {
+ var tabObj = { name: tab, filename: Generate.fileAndClassName(tab), javascriptClassName: Generate.javascriptClassName(tab)};
+ tabsData.push(tabObj);
+ });
+
+ var tabsHtmlTemplatePath = path.join(__dirname, 'tabs.tmpl.js');
+ return Generate.renderTemplateFromFile({tabs: tabsData, templatePath: tabsHtmlTemplatePath, filename: fileAndClassName, javascriptClassName: javascriptClassName });
+};
+
+Generate.generateTabScssTemplate = function generateTabScssTemplate(appDirectory, name) {
+ throw new Error('not implemented');
+};
+
+Generate.generateTabsScssTemplate = function generateTabsScssTemplate(appDirectory, name) {
+ throw new Error('not implemented');
+};
+// end of tabs
+
+Generate.createScaffoldDirectories = function createScaffoldDirectories(options) {
+ // console.log('Create', options.appDirectory, options.fileAndClassName);
+ var componentPath = path.join(options.appDirectory, 'www', 'app', options.fileAndClassName);
+ shell.mkdir('-p', componentPath);
+};
+
+Generate.fileAndClassName = function fileAndClassName(name) {
+ return name.replace(/([a-z])([A-Z])/g, '$1-$2').replace('_', '-').toLowerCase();
+};
+
+Generate.capitalizeName = function capitalizeName(name) {
+ return name.charAt(0).toUpperCase() + name.slice(1);
+};
+
+Generate.javascriptClassName = function javascriptClassName(name) {
+ return _.capitalize(_.camelCase(name));
+};
diff --git a/tooling/generators/page-sidemenu/index.js b/tooling/generators/page-sidemenu/index.js
new file mode 100644
index 0000000000..3487cbcb9d
--- /dev/null
+++ b/tooling/generators/page-sidemenu/index.js
@@ -0,0 +1,5 @@
+var SideMenu = module.exports;
+
+SideMenu.run = function run(options) {
+
+};
diff --git a/tooling/generators/page-tabs/index.js b/tooling/generators/page-tabs/index.js
new file mode 100644
index 0000000000..3cfee84735
--- /dev/null
+++ b/tooling/generators/page-tabs/index.js
@@ -0,0 +1,6 @@
+var Generator = module.exports,
+ Generate = require('../../generate');
+
+Generator.run = function run(options) {
+ console.log('got options!', options);
+};
diff --git a/tooling/generators/page-tabs/tabs.tmpl.html b/tooling/generators/page-tabs/tabs.tmpl.html
new file mode 100644
index 0000000000..8e8314deb0
--- /dev/null
+++ b/tooling/generators/page-tabs/tabs.tmpl.html
@@ -0,0 +1,6 @@
+
+<% _.forEach(tabs, function(tab) { %>
+ ">
+
+<% }); %>
+
diff --git a/tooling/generators/page-tabs/tabs.tmpl.js b/tooling/generators/page-tabs/tabs.tmpl.js
new file mode 100644
index 0000000000..a18aee60b3
--- /dev/null
+++ b/tooling/generators/page-tabs/tabs.tmpl.js
@@ -0,0 +1,18 @@
+import {NavController, Page} from 'ionic/ionic';
+
+<% _.forEach(tabs, function(tab) { %>
+import {<%= tab.javascriptClassName %>} from '../<%= tab.filename %>/<%= tab.filename %>';
+<% }); %>
+
+@Page({
+ templateUrl: 'app/<%= filename %>/<%= filename %>.html'
+})
+export class <%= javascriptClassName %> {
+ constructor(nav: NavController) {
+ // set the root pages for each tab
+ <% _.forEach(tabs, function(tab) { %>
+ this.<%= tab.javascriptClassName %> = <%= tab.javascriptClassName %>;
+ <% }); %>
+ }
+
+}
diff --git a/tooling/generators/page/index.js b/tooling/generators/page/index.js
new file mode 100644
index 0000000000..92159ab58a
--- /dev/null
+++ b/tooling/generators/page/index.js
@@ -0,0 +1,61 @@
+/*
+ ionic g page about
+ what should happen:
+ create directories if not existing: /www, /www/app, /www/app/about
+ create files (about.html, about.scss, about.js) in /www/app/about
+*/
+var fs = require('fs'),
+ Generator = module.exports,
+ Generate = require('../../generate'),
+ path = require('path'),
+ Q = require('q');
+/*
+ Run: generate a page template from the name and save
+ it in the desired app directory
+ @options
+ name: Page name
+ appDirectory: App directory of where to save file
+*/
+Generator.run = function run(options) {
+ options.rootDirectory = options.rootDirectory || path.join('www', 'app');
+ var savePath = path.join(options.appDirectory, options.rootDirectory, options.fileAndClassName);
+
+ var templates = Generate.loadGeneratorTemplates(__dirname);
+
+ templates.forEach(function(template) {
+ var templatePath = path.join(__dirname, template.file);
+ options.templatePath = templatePath;
+ var renderedTemplate = Generate.renderTemplateFromFile(options);
+ var saveFilePath = path.join(savePath, [options.fileAndClassName, template.type].join(''));
+ // console.log('renderedTemplate', renderedTemplate, 'saving to', saveFilePath);
+ console.log('\nā Create'.blue, path.relative(options.appDirectory, saveFilePath));
+ fs.writeFileSync(saveFilePath, renderedTemplate);
+ });
+
+ return Q();
+};
+
+// var fileAndClassName = Generate.fileAndClassName(name);
+// var javascriptClassName = Generate.javascriptClassName(name);
+// Generate.createScaffoldDirectories(appDirectory, fileAndClassName);
+
+// var jsTemplate = Generate.generateJsTemplate(name);
+// var htmlTemplate = Generate.generateHtmlTemplate(name);
+// var scssTemplate = Generate.generateScssTemplate(name);
+
+// var pagePath = path.join(appDirectory, 'www', 'app', fileAndClassName),
+// jsPath = path.join(pagePath, [fileAndClassName, '.js'].join('')),
+// htmlPath = path.join(pagePath, [fileAndClassName, '.html'].join('')),
+// scssPath = path.join(pagePath, [fileAndClassName, '.scss'].join(''));
+
+// logging.logger.info('ā Create'.blue, path.relative(appDirectory, jsPath));
+// fs.writeFileSync(jsPath, jsTemplate, 'utf8');
+// logging.logger.info('ā Create'.blue, path.relative(appDirectory, htmlPath));
+// fs.writeFileSync(htmlPath, htmlTemplate, 'utf8');
+// logging.logger.info('ā Create'.blue, path.relative(appDirectory, scssPath));
+// fs.writeFileSync(scssPath, scssTemplate, 'utf8');
+
+// //TODO: Modify the main sass file (via config) to somehow update it
+// //to include this sass file.
+// //In the meantime, put a console message to alert them
+// logging.logger.info('* Tip: if youd like to use the generated sass file, use \'@import "' + path.relative(appDirectory, scssPath) + '"\' in your main sass file');
diff --git a/tooling/generators/page/page.tmpl.html b/tooling/generators/page/page.tmpl.html
new file mode 100644
index 0000000000..37a133b0b4
--- /dev/null
+++ b/tooling/generators/page/page.tmpl.html
@@ -0,0 +1,6 @@
+
+ <%= javascriptClassName %>
+
+
+
+
diff --git a/tooling/generators/page/page.tmpl.js b/tooling/generators/page/page.tmpl.js
new file mode 100644
index 0000000000..b89436f62f
--- /dev/null
+++ b/tooling/generators/page/page.tmpl.js
@@ -0,0 +1,9 @@
+import {Page, NavController} from 'ionic/ionic';
+@Page({
+ templateUrl: 'app/<%= fileAndClassName %>/<%= fileAndClassName %>.html',
+})
+export class <%= javascriptClassName %> {
+ constructor(nav: NavController) {
+ this.nav = nav;
+ }
+}
diff --git a/tooling/generators/page/page.tmpl.scss b/tooling/generators/page/page.tmpl.scss
new file mode 100644
index 0000000000..978da27ba4
--- /dev/null
+++ b/tooling/generators/page/page.tmpl.scss
@@ -0,0 +1,3 @@
+.<%= fileAndClassName %> {
+
+}