ionic
Version:
A tool for creating and developing Ionic Framework mobile apps.
912 lines (702 loc) • 26 kB
JavaScript
var fs = require('fs'),
os = require('os'),
request = require('request'),
ncp = require('ncp').ncp,
path = require('path'),
parseUrl = require('url').parse,
shelljs = require('shelljs/global'),
argv = require('optimist').boolean(['no-cordova', 'sass', 'list', 'w']).argv,
prompt = require('prompt'),
colors = require('colors'),
Q = require('q'),
open = require('open'),
xml2js = require('xml2js'),
IonicProject = require('./project'),
IonicTemplates = require('./templates').IonicTask,
IonicStore = require('./store').IonicStore,
Task = require('./task').Task;
IonicStats = require('./stats').IonicStats;
var IonicTask = function() {};
// The URL for the cordova wrapper project
IonicTask.WRAPPER_REPO_NAME = 'ionic-app-base';
IonicTask.DEFAULT_APP = {
"plugins": [
"org.apache.cordova.device",
"org.apache.cordova.console",
"com.ionic.keyboard"
],
"sass": false
};
IonicTask.prototype = new Task();
IonicTask.prototype.run = function(ionic) {
this.ionic = ionic;
var self = this;
if(argv.list || argv.l) {
new IonicTemplates().run(ionic);
return;
}
if(argv._.length < 2) {
return this.ionic.fail('Invalid command', 'start');
}
if(argv._[1] == '.') {
console.log('Please name your Ionic project something meaningful other than \'.\''.red);
return
}
// Grab the app's relative directory name
this.appDirectory = argv._[1];
// Grab the name of the app from -a or --app. Defaults to appDirectory if none provided
this.appName = argv.appname || argv['app-name'] || argv.a;
if(!this.appName) {
var appNameSplit = this.appDirectory.split('/');
appNameSplit = appNameSplit[ appNameSplit.length -1 ].split('\\');
this.appName = appNameSplit[ appNameSplit.length -1 ];
}
// get a packge name, like com.ionic.myapp
this.packageName = argv.id || argv.i;
this.ionicAppId = argv['io-app-id'];
this.isCordovaProject = (argv.cordova !== false && !argv.w);
// start project template can come from cmd line args -t, --template, or the 3rd arg, and defaults to tabs
this.template = (argv.template || argv.t || argv._[2] || 'tabs');
// figure out the full path
this.targetPath = path.resolve(this.appDirectory);
console.log('Creating Ionic app in folder', this.targetPath, 'based on', this.template.bold, 'project');
// Make sure to create this
if( fs.existsSync(this.targetPath) ) {
// prompt for log
console.log('\nThe directory'.error.bold, this.targetPath, 'already exists.'.error.bold);
console.log('Would you like to overwrite the directory with this new project?');
var promptProperties = {
areYouSure: {
name: 'areYouSure',
description: '(yes/no):'.yellow.bold,
required: true
}
};
prompt.override = argv;
prompt.message = '';
prompt.delimiter = '';
prompt.start();
prompt.get({properties: promptProperties}, function (err, promptResult) {
if(err) {
return console.log(err);
}
var areYouSure = promptResult.areYouSure.toLowerCase().trim();
if(areYouSure == 'yes' || areYouSure == 'y') {
rm('-rf', self.targetPath);
self.startApp();
}
});
} else {
// create the app directory
fs.mkdirSync(this.targetPath);
this.startApp();
}
};
IonicTask.prototype.startApp = function() {
var self = this;
self.fetchWrapper()
.then(function(){
return self.fetchSeed();
})
.then(function(){
return self.loadAppSetup();
})
.then(function(){
return self.initCordova();
})
.then(function(){
return self.setupSass();
})
.then(function(){
return self.finalize();
})
.catch(function(err) {
console.error('Error: Unable to initalize app:', err);
return self.ionic.fail('');
});
};
IonicTask.prototype.fetchWrapper = function() {
var q = Q.defer();
var self = this;
var repoUrl = 'https://github.com/driftyco/' + IonicTask.WRAPPER_REPO_NAME + '/archive/master.zip';
Ionic.fetchArchive(self.targetPath, repoUrl).then(function() {
var repoFolderName = IonicTask.WRAPPER_REPO_NAME + '-master';
cp('-R', self.targetPath + '/' + repoFolderName + '/.', self.targetPath);
rm('-rf', self.targetPath + '/' + repoFolderName + '/');
cd(self.targetPath);
if(!self.isCordovaProject) {
// remove any cordova files/directories if they only want the www
var cordovaFiles = ['hooks/', 'platforms/', 'plugins/', 'config.xml'];
for(var x=0; x<cordovaFiles.length; x++) {
rm('-rf', self.targetPath + '/' + cordovaFiles[x]);
}
}
q.resolve(self.targetPath);
}, function(err) {
q.reject(err);
}).catch(function(err) {
return self.ionic.fail('Error: Unable to fetch wrapper repo: ' + err);
});
return q.promise;
};
IonicTask.prototype.fetchSeed = function() {
// Codepen: http://codepen.io/ionic/pen/GpCst
if( /\/\/codepen.io\//i.test(this.template) ) {
this.seedType = 'codepen';
return this.fetchCodepen();
}
if(/plnkr.co\//i.test(this.template)) {
this.seedType = 'plnkr';
return this.fetchPlnkr();
}
if( /creator:/i.test(this.template) ) {
this.seedType = 'creator';
return this.fetchCreatorApp();
}
// Github URL: http://github.com/myrepo/
if( /\/\/github.com\//i.test(this.template) ) {
this.seedType = 'github';
return this.fetchGithubStarter(this.template);
}
// Local Directory: /User/starterapp
if( (this.template.indexOf('/') > -1 || this.template.indexOf('\\') > -1) && (this.template.indexOf('http://') === -1 && this.template.indexOf('https://') === -1)) {
console.log('local', this.template);
this.seedType = 'local';
return this.fetchLocalStarter();
}
// Ionic Github Repo
this.seedType = 'ionic-starter';
return this.fetchIonicStarter();
};
IonicTask.prototype.loadAppSetup = function() {
var q = Q.defer();
this.appSetup = IonicTask.DEFAULT_APP;
var appJsonPath = path.join(this.targetPath, 'www', 'app.json');
if(fs.existsSync(appJsonPath)) {
try {
this.appSetup = JSON.parse( fs.readFileSync(appJsonPath) );
rm('-rf', appJsonPath);
} catch(e) {
console.log( 'app.json error:', e);
}
}
q.resolve();
return q;
};
IonicTask.prototype.fetchCreatorApp = function() {
var self = this;
var appId = this.template.split(':')[1];
var downloadUrl = Ionic.IONIC_DASH + path.join('/api/v1/creator', appId, 'download/html');
var wwwPath = path.join(this.targetPath, 'www');
console.log('\nDownloading Creator Prototype:'.bold, downloadUrl);
var q = Q.defer();
var proxy = process.env.PROXY || null;
request({ url: downloadUrl, proxy: proxy }, function(err, res, html) {
if(!err && res && res.statusCode === 200) {
//html = self.convertTemplates(html);
fs.writeFileSync(path.join(wwwPath, 'index.html'), html, 'utf8');
} else {
console.log('Unable to fetch', err, res.statusCode);
q.reject(res);
}
q.resolve();
});
return Q.all([q]);
};
IonicTask.prototype.fetchCodepen = function() {
var self = this;
var codepenUrl = this.template.split('?')[0].split('#')[0];
var wwwPath = path.join(this.targetPath, 'www');
//Given any of these urls:
// http://codepen.io/ionic/pen/QwamEW
// http://codepen.io/ionic/live/QwamEW
// http://codepen.io/ionic/details/QwamEW/
// http://codepen.io/ionic/full/QwamEW/
// we want to parse out and get the /pen/ID link if its not already a /pen link
if (codepenUrl.indexOf('/pen') == -1) {
if(codepenUrl[codepenUrl.length - 1] == '/') {
codepenUrl = codepenUrl.substr(0, codepenUrl.length - 1);
}
var codePenSplit = codepenUrl.split('/')
var codePenId = codePenSplit[codePenSplit.length - 1];
var codePenOrg = codePenSplit[3];
codepenUrl = ['http://codepen.io/', codePenOrg, '/pen/', codePenId].join('')
}
console.log('\nDownloading Codepen:'.bold, codepenUrl);
var qHTML = Q.defer();
var qCSS = Q.defer();
var qJS = Q.defer();
var proxy = process.env.PROXY || process.env.http_proxy || null;
request({ url: codepenUrl + '.html', proxy: proxy }, function(err, res, html) {
if(!err && res && res.statusCode === 200) {
html = html || '';
if(html.indexOf('<!DOCTYPE html>') < 0) {
html = '<!DOCTYPE html>\n' + html;
}
var resources = ' <link href="css/style.css" rel="stylesheet">\n' +
' <script src="js/app.js"></script>\n';
if(self.isCordovaProject) {
resources += ' <script src="cordova.js"></script>\n';
}
resources += ' </head>';
html = html.replace(/<\/head>/i, '\n' + resources);
html = self.convertTemplates(html);
fs.writeFileSync(path.join(wwwPath, 'index.html'), html, 'utf8');
}
qHTML.resolve();
});
request({ url: codepenUrl + '.css', proxy: proxy }, function(err, res, css) {
if(!err && res && res.statusCode === 200) {
css = css || '';
var cssPath = path.join(wwwPath, 'css');
if(!fs.existsSync(cssPath)) {
fs.mkdirSync(cssPath);
}
css = css.replace("cursor: url('http://ionicframework.com/img/finger.png'), auto;", '');
fs.writeFileSync(path.join(cssPath, 'style.css'), css, 'utf8');
}
qCSS.resolve();
});
request({ url: codepenUrl + '.js', proxy: proxy }, function(err, res, js) {
if(!err && res && res.statusCode === 200) {
js = js || '';
var jsPath = path.join(wwwPath, 'js');
if(!fs.existsSync(jsPath)) {
fs.mkdirSync(jsPath);
}
fs.writeFileSync(path.join(jsPath, 'app.js'), js, 'utf8');
}
qJS.resolve();
});
return Q.all([qHTML.promise, qCSS.promise, qJS.promise]);
};
IonicTask.prototype.convertTemplates = function(html) {
var templates = [];
var self = this;
try {
var scripts = html.match(/<script [\s\S]*?<\/script>/gi);
scripts.forEach(function(scriptElement){
if(scriptElement.indexOf('text/ng-template') > -1) {
var lines = scriptElement.split('\n');
for(var x=0; x<lines.length; x++) {
try {
if(lines[x].substr(0, 6) === ' ') {
lines[x] = lines[x].substr(6);
}
} catch(lE){}
}
var data = lines.join('\n');
var id = data.match(/ id=["|'](.*?)["|']/i)[0];
id = id.replace(/'/g, '"').split('"')[1];
data = data.replace(/<script [\s\S]*?>/gi, '');
data = data.replace(/<\/script>/gi, '');
data = data.trim();
templates.push({
path: id,
scriptElement: scriptElement,
html: data
});
}
});
}catch(e){}
try {
templates.forEach(function(tmpl){
var tmpPath = path.join(self.targetPath, 'www', path.dirname(tmpl.path));
if(!fs.existsSync(tmpPath)) {
fs.mkdirSync(tmpPath);
}
tmpPath = path.join(self.targetPath, 'www', tmpl.path);
fs.writeFileSync(tmpPath, tmpl.html, 'utf8');
html = html.replace( tmpl.scriptElement, '' );
html = html.replace( / \n \n/g, '' );
});
}catch(e){}
return html;
};
IonicTask.prototype.fetchLocalStarter = function() {
var self = this;
var q = Q.defer();
try {
cd('..');
var localStarterPath = path.resolve(this.template);
if( !fs.existsSync(localStarterPath) ) {
self.ionic.fail('Unable to find local starter template: ' + localStarterPath);
q.reject();
return q.promise;
}
console.log('\nCopying files to www from:'.bold, localStarterPath);
// Move the content of this repo into the www folder
cp('-Rf', path.join(localStarterPath, '*'), path.join(self.targetPath, 'www'));
q.resolve();
} catch(e) {
q.reject(e);
}
cd(self.targetPath);
return q.promise;
};
IonicTask.prototype.fetchIonicStarter = function() {
// Get the starter project repo name:
var repoName = 'ionic-starter-' + this.template;
// Get the URL for the starter project repo:
var repoUrl = 'https://github.com/driftyco/' + repoName;
return this.fetchGithubStarter(repoUrl);
};
IonicTask.prototype.fetchGithubStarter = function(repoUrl) {
var self = this;
var q = Q.defer();
// https://github.com/driftyco/ionic-starter-tabs/
var urlParse = parseUrl(repoUrl);
var pathSplit = urlParse.pathname.replace(/\//g, ' ').trim().split(' ');
if(!urlParse.hostname || urlParse.hostname.toLowerCase() !== 'github.com' || pathSplit.length !== 2) {
console.log( ('Invalid Github URL: ' + repoUrl).error );
console.log( ('Example of a valid URL: https://github.com/driftyco/ionic-starter-tabs/').error );
self.ionic.fail('');
q.reject();
return q.promise;
}
var repoName = pathSplit[1];
var repoFolderName = repoName + '-master';
// ensure there's an ending /
if(repoUrl.substr(repoUrl.length -1) !== '/') {
repoUrl += '/';
}
repoUrl += 'archive/master.zip';
Ionic.fetchArchive(self.targetPath, repoUrl).then(function() {
try {
// Move the content of this repo into the www folder
cp('-Rf', self.targetPath + '/' + repoFolderName + '/.', 'www');
// Clean up start template folder
rm('-rf', self.targetPath + '/' + repoFolderName + '/');
q.resolve();
} catch(e) {
q.reject(e);
}
}).catch(function(err) {
console.error('More info available at: \nhttp://ionicframework.com/getting-started/\nhttps://github.com/driftyco/ionic-cli');
return self.ionic.fail('');
});
return q.promise;
};
IonicTask.prototype.initCordova = function() {
var self = this;
var q = Q.defer();
if(this.isCordovaProject) {
// update the config.xml file from cmd line args
this.updateConfigXml();
if(this.ionic.hasFailed) return;
var cmds = [];
// add plugins
for(var x=0; x<self.appSetup.plugins.length; x++) {
cmds.push('ionic plugin add ' + self.appSetup.plugins[x]);
}
// platform add android with --android flag
if(argv.android) {
cmds.push('ionic platform add android');
}
// platform add ios with --android flag
if(argv.ios) {
cmds.push('ionic platform add ios');
}
console.log('Initializing cordova project'.bold);
exec(cmds.join(' && '),
function(err, stdout, stderr) {
if(err) {
self.ionic.fail('Unable to add plugins. Perhaps your version of Cordova is too old. ' +
'Try updating (npm install -g cordova), removing this project folder, and trying again.');
q.reject(stderr);
} else {
q.resolve(stdout);
}
});
} else {
q.resolve();
}
return q.promise;
};
IonicTask.prototype.updateConfigXml = function() {
var self = this;
console.log('\nUpdate config.xml'.bold);
try {
var configXmlPath = self.targetPath + '/config.xml';
var configString = fs.readFileSync(configXmlPath, { encoding: 'utf8' });
var parseString = xml2js.parseString;
parseString(configString, function (err, jsonConfig) {
if(err) {
return self.ionic.fail('Error parsing config.xml: ' + err);
}
if(!self.packageName) {
var packageName = self.appDirectory + (self.appDirectory !== 'tmp' ? Math.round((Math.random() * 899999) + 100000) : '');
self.packageName = 'com.ionicframework.' + packageName.replace(/\./g, '');
}
jsonConfig.widget.$.id = self.packageName.replace(/ /g, '').replace(/-/g, '').replace(/_/g, '').toLowerCase().trim();
jsonConfig.widget.name = [ self.appName ];
var xmlBuilder = new xml2js.Builder();
configString = xmlBuilder.buildObject(jsonConfig);
fs.writeFile(configXmlPath, configString, function(err) {
if(err) {
return self.ionic.fail('Error saving config.xml file: ' + err);
}
});
});
} catch(e) {
return self.ionic.fail('Error updating config.xml file: ' + e);
}
};
IonicTask.prototype.setupSass = function() {
this.hasSass = false;
if(argv.sass || this.appSetup.sass) {
// auto setup sass if they set the option
console.log('setup sass'.green.bold);
var IonicSetupTask = require('./setup').IonicTask
var setupTask = new IonicSetupTask();
this.hasSass = true;
return setupTask.sassSetup(this.ionic);
}
// didn't ask to setup sass, so resolve it
var q = Q.defer();
q.resolve();
return q.promise;
};
IonicTask.prototype.updateLibFiles = function() {
var libPath = argv.lib || argv.l || 'lib/ionic';
// create a symlink if the path exists locally
var libSymlinkPath = path.resolve(libPath);
if( fs.existsSync(libSymlinkPath) ) {
// rename the existing lib/ionic directory before creating symlink
var wwwIonicCssPath = path.resolve('www/lib/ionic/css');
if( fs.existsSync(wwwIonicCssPath) ) {
mv( wwwIonicCssPath, path.resolve('www/lib/ionic/css_local') );
}
var wwwIonicJsPath = path.resolve('www/lib/ionic/js');
if( fs.existsSync(wwwIonicJsPath) ) {
mv( wwwIonicJsPath, path.resolve('www/lib/ionic/js_local') );
}
var wwwIonicFontsPath = path.resolve('www/lib/ionic/fonts');
if( fs.existsSync(wwwIonicFontsPath) ) {
mv( wwwIonicFontsPath, path.resolve('www/lib/ionic/fonts_local') );
}
var libCssSymlinkPath = path.join(libSymlinkPath, 'css');
console.log('Create www/lib/ionic/css symlink to ' + libCssSymlinkPath);
fs.symlinkSync(libCssSymlinkPath, wwwIonicCssPath);
var libJsSymlinkPath = path.join(libSymlinkPath, 'js');
console.log('Create www/lib/ionic/js symlink to ' + libJsSymlinkPath);
fs.symlinkSync(libJsSymlinkPath, wwwIonicJsPath);
var libFontsSymlinkPath = path.join(libSymlinkPath, 'fonts');
console.log('Create www/lib/ionic/fonts symlink to ' + libFontsSymlinkPath);
fs.symlinkSync(libFontsSymlinkPath, wwwIonicFontsPath);
libPath = 'lib/ionic';
}
if(libPath == 'lib/ionic' && (this.seedType == 'ionic-starter' || /ionic-starter/i.test(this.template))) {
// don't bother if its still is the default which comes with the starters
return;
}
// path did not exist locally, so manually switch out the path in the html
var libFiles = 'ionic.css ionic.min.css ionic.js ionic.min.js ionic.bundle.js ionic.bundle.min.js ionic-angular.js ionic-angular.min.js'.split(' ');
function isLibFile(tag) {
if(tag) {
tag = tag.toLowerCase();
for(var x=0; x<libFiles.length; x++) {
if( tag.indexOf(libFiles[x]) > -1 ) {
return true;
}
}
}
}
function changeLibPath(originalUrl) {
var splt = originalUrl.split('/');
var newUrl = [ libPath ];
var filename = splt[ splt.length - 1 ];
if(filename.indexOf('.css') > -1) {
newUrl.push('css');
} else if(filename.indexOf('.js') > -1) {
newUrl.push('js');
}
newUrl.push(filename);
return newUrl.join('/');
}
function replaceResource(html, originalTag) {
originalTag = originalTag.replace(/'/g, '"');
var splt = originalTag.split('"');
var newTagArray = [];
for(var x=0; x<splt.length; x++) {
if( isLibFile(splt[x]) ) {
newTagArray.push( changeLibPath(splt[x]) );
} else {
newTagArray.push( splt[x] );
}
}
var newTag = newTagArray.join('"');
return html.replace(originalTag, newTag);
}
function getLibTags(html) {
var resourceTags = [];
var libTags = [];
try{
resourceTags = resourceTags.concat( html.match(/<script (.*?)>/gi) );
}catch(e){}
try{
resourceTags = resourceTags.concat( html.match(/<link (.*?)>/gi) );
}catch(e){}
for(var x=0; x<resourceTags.length; x++) {
if( isLibFile(resourceTags[x]) ) {
libTags.push(resourceTags[x]);
}
}
return libTags;
}
try {
console.log('Replacing Ionic lib references with ' + libPath);
var indexPath = path.join(this.targetPath, 'www', 'index.html');
var html = fs.readFileSync(indexPath, 'utf8');
var libTags = getLibTags(html);
for(var x=0; x<libTags.length; x++) {
var originalTag = libTags[x];
html = replaceResource(html, originalTag);
}
fs.writeFileSync(indexPath, html, 'utf8');
} catch(e) {
this.ionic.fail('Error updating lib files: ' + e);
}
};
IonicTask.prototype.promptLogin = function() {
var ionicConfig = new IonicStore('ionic.config');
if(ionicConfig) {
// Check if we already asked
var didPrompt = ionicConfig.get('accountPrompt');
if(didPrompt == 'y') {
/*
console.log('\n' + 'New!'.green.bold + ' Create an ionic.io account and try the View App!\n' + Ionic.IONIC_DASH + '/signup');
*/
return;
}
ionicConfig.set('accountPrompt', 'y');
ionicConfig.save();
}
console.log('\nCreate an ionic.io account to use the Ionic View app and other features?');
var promptProperties = {
shouldCreate: {
name: 'shouldCreate',
description: '(Y/n):'.yellow.bold,
}
};
prompt.override = argv;
prompt.message = '';
prompt.delimiter = '';
prompt.start();
prompt.get({properties: promptProperties}, function (err, promptResult) {
if(err) {
return console.log(err);
}
var areYouSure = promptResult.shouldCreate.toLowerCase().trim();
if(areYouSure.toLowerCase() != 'n') {
// If they want to, let's open a thing
open(Ionic.IONIC_DASH + '/signup');
}
});
};
IonicTask.prototype.finalize = function() {
var self = this;
this.updateLibFiles();
try {
var packageFilePath = path.resolve('package.json');
var packageData = require(packageFilePath);
packageData.name = encodeURIComponent( this.appName.toLowerCase().replace(/\s+/g, '-') );
packageData.description = this.appName + ': An Ionic project';
fs.writeFileSync(packageFilePath, JSON.stringify(packageData, null, 2), 'utf8');
} catch(e) {}
try {
// create the ionic.project file and
// set the app name
var project = IonicProject.create();
if(this.ionicAppId) {
project.set('app_id', this.ionicAppId);
}
project.set('name', this.appName);
project.save(this.targetPath);
} catch(e) {}
try {
// update the app name in the bower.json file
var ionicBower = require('./bower').IonicBower;
ionicBower.setAppName(this.appName);
} catch(e) {}
try {
// remove the README file in the root because it
// doesn't make sense because its the README for the repo
// and not helper text while developing an app
fs.unlinkSync(this.targetPath + '/README.md');
} catch(e) {}
try {
// remove the README file in the www root because it
// doesn't make sense because its the README for the repo
// and not helper text while developing an app
fs.unlinkSync(this.targetPath + '/www/README.md');
} catch(e) {}
this.printQuickHelp();
this.ionic.printNewsUpdates(true).then(function() {
self.promptLogin();
});
IonicStats.t();
};
IonicTask.prototype.printQuickHelp = function() {
console.log('\nYour Ionic project is ready to go!'.green.bold, 'Some quick tips:');
console.log('\n * cd into your project:', ('$ cd ' + this.appDirectory).bold);
if(!this.hasSass) {
console.log('\n * Setup this project to use Sass:', 'ionic setup sass'.bold);
}
console.log('\n * Develop in the browser with live reload:', 'ionic serve'.bold);
if(this.isCordovaProject) {
console.log('\n * Add a platform (ios or Android):', 'ionic platform add ios [android]'.bold);
console.log(' Note: iOS development requires OS X currently'.small);
console.log(' See the Android Platform Guide for full Android installation instructions:'.small);
console.log(' https://cordova.apache.org/docs/en/edge/guide_platforms_android_index.md.html'.small);
console.log('\n * Build your app:', 'ionic build <PLATFORM>'.bold);
console.log('\n * Simulate your app:', 'ionic emulate <PLATFORM>'.bold);
console.log('\n * Run your app on a device:', 'ionic run <PLATFORM>'.bold);
console.log('\n * Package an app using Ionic package service:', 'ionic package <MODE> <PLATFORM>'.bold);
}
console.log('\nFor more help use', 'ionic --help'.bold, 'or visit the Ionic docs:', 'http://ionicframework.com/docs\n'.bold);
};
IonicTask.prototype.fetchPlnkr = function fetchPlnkr() {
var self = this;
var q = Q.defer();
var plnkrUrl = this.template.split('?')[0].split('#')[0];
var plnkrId = null;
//Given any of these urls - we need to extract the ID
//http://embed.plnkr.co/dFvL8n/preview
//http://run.plnkr.co/plunks/dFvL8n/#/tabs/friends
//http://api.plnkr.co/plunks/dFvL8n
// http://embed.plnkr.co/BZrnKPlCJt93orQp58H3/preview
//To download, we want http://api.plnkr.co/plunks/dFvL8n.zip
if (plnkrUrl[plnkrUrl.length - 1] == '/') {
plnkrUrl = plnkrUrl.substr(0, plnkrUrl.length -1);
}
var plnkrSplit = plnkrUrl.split('/');
// api link - need zip on end.
if (plnkrUrl.indexOf('embed.plnkr.co') != -1) {
plnkrId = plnkrSplit[3];
} else if (plnkrUrl.indexOf('run.plnkr.co') != -1 || plnkrUrl.indexOf('api.plnkr.co') != -1) {
plnkrId = plnkrSplit[plnkrSplit.length - 1];
if(plnkrId.indexOf('.zip') != -1) {
plnkrId = plnkrId.replace('.zip', '')
}
}
plnkrUrl = ['http://api.plnkr.co/plunks/', plnkrId, '.zip'].join('');
console.log('\nDownloading Plnkr url:', plnkrUrl)
var extractPath = path.join(self.targetPath, 'plnkr');
Ionic.fetchArchive(extractPath, plnkrUrl)
.then(function() {
// console.log('Done downloading')
try {
// Move the content of this repo into the www folder
var copyDir = [extractPath, '/*'].join('');
cp('-Rf', copyDir, 'www');
// Clean up start template folder
rm('-rf', extractPath + '/');
q.resolve();
} catch(e) {
q.reject(e);
}
})
return q.promise;
}
exports.IonicTask = IonicTask;