Merge pull request #40 from raphinesse/breaking-changes

Major usability & maintainability improvements 
diff --git a/README.md b/README.md
index 6768763..160eceb 100644
--- a/README.md
+++ b/README.md
@@ -29,27 +29,31 @@
 ## Usage:
 
 ```
-var create = require('cordova-create');
+const create = require('cordova-create');
 
-create(dir, id, name, cfg, extEvents);
+await create(dest, opts);
 ```
 
-- `dir` - directory where the project will be created. Required.
-- `id` - app id. Required (but can be "undefined").
-- `name` - app name. Required (but can be "undefined").
-- `cfg` - extra config to be saved in .cordova/config.json Required (but can be "{}").
-- `extEvents` - An EventEmitter instance that will be used for logging purposes. Required (but can be "undefined").
+### Parameters
 
-An example of `cfg` which would fetch a cordova template from npm (or git):
+#### `dest`
+_Required_. Path to the destination where the project will be created. Must be an empty dir if it exists.
+
+#### `opts`
+_Optional_. Supports following properties.
 
 ```
-var cfg = {
-    lib: {
-        www: {
-            template: true,
-            url: 'cordova-app-hello-world',
-            version: ''
-        }
-    }
-};
+{
+    // Attributes to be set in package.json & config.xml
+    id: String,
+    name: String,
+    version: String,
+
+    // The path/url/package-name to the template that should be used
+    template: String,
+
+    // An EventEmitter instance that will be used for logging purposes
+    // (actually it only needs to implement a compatible `emit` method)
+    events: EventEmitter
+}
 ```
diff --git a/index.js b/index.js
index 2ddec33..0ce0636 100644
--- a/index.js
+++ b/index.js
@@ -29,47 +29,10 @@
 var validateIdentifier = require('valid-identifier');
 
 var fetch = require('cordova-fetch');
-var events = require('cordova-common').events;
 var CordovaError = require('cordova-common').CordovaError;
 var ConfigParser = require('cordova-common').ConfigParser;
-var CordovaLogger = require('cordova-common').CordovaLogger.get();
 
-const DEFAULT_VERSION = '1.0.0';
-
-/**
- * Sets up to forward events to another instance, or log console.
- * This will make the create internal events visible outside
- * @param  {EventEmitter} externalEventEmitter An EventEmitter instance that will be used for
- *   logging purposes. If no EventEmitter provided, all events will be logged to console
- * @return {EventEmitter}
- */
-function setupEvents (externalEventEmitter) {
-    if (externalEventEmitter) {
-        // This will make the platform internal events visible outside
-        events.forwardEventsTo(externalEventEmitter);
-    // There is no logger if external emitter is not present,
-    // so attach a console logger
-    } else {
-        CordovaLogger.subscribe(events);
-    }
-    return events;
-}
-
-module.exports = cordovaCreateLegacyAdapter;
-
-/**
-* Legacy interface. See README for documentation
-*/
-function cordovaCreateLegacyAdapter (dir, id, name, cfg, extEvents) {
-    // Unwrap and shallow-clone that nasty nested config object
-    const opts = Object.assign({}, ((cfg || {}).lib || {}).www);
-
-    if (id) opts.id = id;
-    if (name) opts.name = name;
-    if (extEvents) opts.extEvents = extEvents;
-
-    return cordovaCreate(dir, opts);
-}
+module.exports = cordovaCreate;
 
 /**
  * Creates a new cordova project in the given directory.
@@ -79,6 +42,7 @@
  * @returns {Promise}           Resolves when project creation has finished.
  */
 function cordovaCreate (dest, opts = {}) {
+    let emit;
     // TODO this is to avoid having a huge diff. Remove later.
     let dir = dest;
 
@@ -94,8 +58,8 @@
         // Shallow copy opts
         opts = Object.assign({}, opts);
 
-        events = setupEvents(opts.extEvents);
-        events.emit('verbose', 'Using detached cordova-create');
+        emit = getEventEmitter(opts);
+        emit('verbose', 'Using detached cordova-create');
 
         // Make absolute.
         dir = path.resolve(dir);
@@ -108,54 +72,38 @@
             throw new CordovaError('App id contains a reserved word, or is not a valid identifier.');
         }
 
-        // This was changed from "uri" to "url", but checking uri for backwards compatibility.
-        opts.url = opts.url || opts.uri;
-
-        if (!opts.url) {
-            opts.url = require.resolve('cordova-app-hello-world');
-            opts.template = true;
+        if (!opts.template) {
+            opts.template = require.resolve('cordova-app-hello-world');
         }
 
         // Ensure that the destination is outside the template location
-        if (pathIsInside(dir, opts.url)) {
+        if (pathIsInside(dir, opts.template)) {
             throw new CordovaError(
-                `Cannot create project "${dir}" inside the template used to create it "${opts.url}".`
+                `Cannot create project "${dir}" inside the template used to create it "${opts.template}".`
             );
         }
     })
         .then(function () {
             // Finally, Ready to start!
-            events.emit('log', 'Creating a new cordova project.');
-
-            // If symlink, don't fetch
-            if (opts.link) {
-                return opts.url;
-            }
+            emit('log', 'Creating a new cordova project.');
 
             // Use cordova-fetch to obtain npm or git templates
-            if (opts.template && isRemoteUri(opts.url)) {
-                var target = opts.url;
-                events.emit('verbose', 'Using cordova-fetch for ' + target);
+            if (isRemoteUri(opts.template)) {
+                var target = opts.template;
+                emit('verbose', 'Using cordova-fetch for ' + target);
                 return fetch(target, getSelfDestructingTempDir(), {});
             } else {
                 // If assets are not online, resolve as a relative path on local computer
-                return path.resolve(opts.url);
+                return path.resolve(opts.template);
             }
         })
-        .then(function (input_directory) {
-            var import_from_path = input_directory;
+        .then(function (templatePath) {
+            var import_from_path;
 
-            // handle when input wants to specify sub-directory (specified in index.js as "dirname" export);
-            var isSubDir = false;
             try {
-                var templatePkg = requireFresh(input_directory);
-                if (templatePkg && templatePkg.dirname) {
-                    import_from_path = templatePkg.dirname;
-                    isSubDir = true;
-                }
+                import_from_path = requireFresh(templatePath).dirname;
             } catch (e) {
-                events.emit('verbose', 'index.js does not specify valid sub-directory: ' + input_directory);
-                isSubDir = false;
+                throw new CordovaError(templatePath + ' is not a valid template');
             }
 
             if (!fs.existsSync(import_from_path)) {
@@ -170,180 +118,45 @@
 
             try {
                 // Copy files from template to project
-                if (opts.template) {
-                    events.emit('verbose', 'Copying assets.');
-                    copyTemplateFiles(import_from_path, dir, isSubDir);
-                }
-
-                // If --link, link merges, hooks, www, and config.xml (and/or copy to root)
-                if (opts.link) {
-                    events.emit('verbose', 'Symlinking assets.');
-                    linkFromTemplate(import_from_path, dir);
-                }
-
-                // If following were not copied/linked from template, copy from stock app hello world
-                // TODO: get stock package.json if template does not contain package.json;
-                copyIfNotExists(stockAssetPath('www'), path.join(dir, 'www'));
-                copyIfNotExists(stockAssetPath('hooks'), path.join(dir, 'hooks'));
-                var configXmlExists = projectConfig(dir); // moves config to root if in www
-                if (!configXmlExists) {
-                    fs.copySync(stockAssetPath('config.xml'), path.join(dir, 'config.xml'));
-                }
+                emit('verbose', 'Copying assets.');
+                fs.copySync(import_from_path, dir);
             } catch (e) {
                 if (!dirAlreadyExisted) {
                     fs.removeSync(dir);
                 }
-                if (process.platform.slice(0, 3) === 'win' && e.code === 'EPERM') {
-                    throw new CordovaError('Symlinks on Windows require Administrator privileges');
-                }
                 throw e;
             }
 
-            var pkgjsonPath = path.join(dir, 'package.json');
-            // Update package.json name and version fields
-            if (fs.existsSync(pkgjsonPath)) {
-                var pkgjson = requireFresh(pkgjsonPath);
+            // Write out id, name and version to config.xml
+            const configPath = path.join(dir, 'config.xml');
+            const conf = new ConfigParser(configPath);
 
-                // Pkjson.displayName should equal config's name.
-                if (opts.name) {
-                    pkgjson.displayName = opts.name;
-                }
-                // Pkjson.name should equal config's id.
-                if (opts.id) {
-                    pkgjson.name = opts.id.toLowerCase();
-                } else {
-                    // Use default name.
-                    pkgjson.name = 'helloworld';
-                }
+            conf.setPackageName(opts.id || conf.packageName() || 'com.example.cordova.app');
+            conf.setName(opts.name || conf.name() || 'Cordova Example App');
+            conf.setVersion(opts.version || conf.version() || '1.0.0');
 
-                pkgjson.version = DEFAULT_VERSION;
-                fs.writeFileSync(pkgjsonPath, JSON.stringify(pkgjson, null, 4), 'utf8');
-            }
+            conf.write();
 
-            // Create basic project structure.
-            fs.ensureDirSync(path.join(dir, 'platforms'));
-            fs.ensureDirSync(path.join(dir, 'plugins'));
+            // Copy values from config.xml to package.json
+            const pkgJsonPath = path.join(dir, 'package.json');
+            if (fs.existsSync(pkgJsonPath)) {
+                const pkgJson = requireFresh(pkgJsonPath);
 
-            var configPath = path.join(dir, 'config.xml');
-            // only update config.xml if not a symlink
-            if (!fs.lstatSync(configPath).isSymbolicLink()) {
-                // Write out id, name and default version to config.xml
-                var conf = new ConfigParser(configPath);
-                if (opts.id) conf.setPackageName(opts.id);
-                if (opts.name) conf.setName(opts.name);
-                conf.setVersion(DEFAULT_VERSION);
-                conf.write();
+                Object.assign(pkgJson, {
+                    name: conf.packageName().toLowerCase(),
+                    displayName: conf.name(),
+                    version: conf.version()
+                });
+
+                fs.writeJsonSync(pkgJsonPath, pkgJson, { spaces: 2 });
             }
         });
 }
 
-/**
- * Recursively copies folder to destination if folder is not found in destination (including symlinks).
- * @param  {string} src for copying
- * @param  {string} dst for copying
- * @return No return value
- */
-function copyIfNotExists (src, dst) {
-    if (!fs.existsSync(dst) && src) {
-        fs.copySync(src, dst);
-    }
-}
-
-/**
- * Copies template files, and directories into a Cordova project directory.
- * If the template is a www folder, the www folder is simply copied
- * Otherwise if the template exists in a subdirectory everything is copied
- * Otherwise package.json, RELEASENOTES.md, .git, NOTICE, LICENSE, COPYRIGHT, and .npmignore are not copied over.
- * A template directory, and project directory must be passed.
- * templateDir - Template directory
- * projectDir - Project directory
- * isSubDir - boolean is true if template has subdirectory structure (see code around line 229)
- */
-function copyTemplateFiles (templateDir, projectDir, isSubDir) {
-    var copyPath;
-    // if template is a www dir
-    if (path.basename(templateDir) === 'www') {
-        copyPath = path.resolve(templateDir);
-        fs.copySync(copyPath, path.resolve(projectDir, 'www'));
-    } else {
-        var templateFiles = fs.readdirSync(templateDir);
-        // Remove directories, and files that are unwanted
-        if (!isSubDir) {
-            var excludes = ['package.json', 'RELEASENOTES.md', '.git', 'NOTICE', 'LICENSE', 'COPYRIGHT', '.npmignore'];
-            templateFiles = templateFiles.filter(function (value) {
-                return excludes.indexOf(value) < 0;
-            });
-        }
-        // Copy each template file after filter
-        templateFiles.forEach(f => {
-            copyPath = path.resolve(templateDir, f);
-            fs.copySync(copyPath, path.resolve(projectDir, f));
-        });
-    }
-}
-
-/**
- * Find config file in project directory or www directory
- * If file is in www directory, move it outside
- * @param  {String} project directory to be searched
- * @return {String or False} location of config file; if none exists, returns false
- */
-function projectConfig (projectDir) {
-    var rootPath = path.join(projectDir, 'config.xml');
-    var wwwPath = path.join(projectDir, 'www', 'config.xml');
-    if (fs.existsSync(rootPath)) {
-        return rootPath;
-    } else if (fs.existsSync(wwwPath)) {
-        fs.renameSync(wwwPath, rootPath);
-        return wwwPath;
-    }
-    return false;
-}
-
-/**
- * Removes existing files and symlinks them if they exist.
- * Symlinks folders: www, merges, hooks
- * Symlinks file: config.xml (but only if it exists outside of the www folder)
- * If config.xml exists inside of template/www, COPY (not link) it to project/
- * */
-function linkFromTemplate (templateDir, projectDir) {
-    var linkSrc, linkDst, linkFolders, copySrc, copyDst;
-    function rmlinkSync (src, dst, type) {
-        if (src && dst) {
-            fs.removeSync(dst);
-            if (fs.existsSync(src)) {
-                fs.symlinkSync(src, dst, type);
-            }
-        }
-    }
-    // if template is a www dir
-    if (path.basename(templateDir) === 'www') {
-        linkSrc = path.resolve(templateDir);
-        linkDst = path.join(projectDir, 'www');
-        rmlinkSync(linkSrc, linkDst, 'dir');
-        copySrc = path.join(templateDir, 'config.xml');
-    } else {
-        linkFolders = ['www', 'merges', 'hooks'];
-        // Link each folder
-        for (var i = 0; i < linkFolders.length; i++) {
-            linkSrc = path.join(templateDir, linkFolders[i]);
-            linkDst = path.join(projectDir, linkFolders[i]);
-            rmlinkSync(linkSrc, linkDst, 'dir');
-        }
-        linkSrc = path.join(templateDir, 'config.xml');
-        linkDst = path.join(projectDir, 'config.xml');
-        rmlinkSync(linkSrc, linkDst, 'file');
-        copySrc = path.join(templateDir, 'www', 'config.xml');
-    }
-    // if template/www/config.xml then copy to project/config.xml
-    copyDst = path.join(projectDir, 'config.xml');
-    if (!fs.existsSync(copyDst) && fs.existsSync(copySrc)) {
-        fs.copySync(copySrc, copyDst);
-    }
-}
-
-function stockAssetPath (p) {
-    return path.join(require('cordova-app-hello-world').dirname, p);
+function getEventEmitter ({ events }) {
+    return events
+        ? (...args) => events.emit(...args)
+        : () => {};
 }
 
 // Creates temp dir that is deleted on process exit
diff --git a/spec/create.spec.js b/spec/create.spec.js
index ef84270..821ed37 100644
--- a/spec/create.spec.js
+++ b/spec/create.spec.js
@@ -24,7 +24,6 @@
 var requireFresh = require('import-fresh');
 
 var create = require('..');
-var events = require('cordova-common').events;
 var CordovaError = require('cordova-common').CordovaError;
 var ConfigParser = require('cordova-common').ConfigParser;
 const { tmpDir, createWith, createWithMockFetch, expectRejection } = require('./helpers');
@@ -34,9 +33,11 @@
 const appVersion = '1.0.0';
 const project = path.join(tmpDir, appName);
 
-// Setup and teardown test dirs
+let opts;
+
 beforeEach(function () {
     fs.emptyDirSync(tmpDir);
+    opts = { name: appName, id: appId };
 });
 afterAll(function () {
     process.chdir(path.join(__dirname, '..')); // Needed to rm the dir on Windows.
@@ -47,25 +48,21 @@
     const error = new CordovaError('is not a valid identifier');
 
     it('should reject reserved words from start of id', function () {
-        return expectRejection(create(project, 'int.bob', appName, {}, events), error);
+        opts.id = 'int.bob';
+        return expectRejection(create(project, opts), error);
     });
 
     it('should reject reserved words from end of id', function () {
-        return expectRejection(create(project, 'bob.class', appName, {}, events), error);
+        opts.id = 'bob.class';
+        return expectRejection(create(project, opts), error);
     });
 });
 
 describe('create end-to-end', function () {
 
     function checkCommonArtifacts () {
-        // Check that top level dirs exist
-        var dirs = ['hooks', 'platforms', 'plugins', 'www'];
-        dirs.forEach(function (d) {
-            expect(path.join(project, d)).toExist();
-        });
-
-        // Check that README.md exists inside of hooks
-        expect(path.join(project, 'hooks', 'README.md')).toExist();
+        // Check that www dir exist
+        expect(path.join(project, 'www')).toExist();
 
         // Check that index.html exists inside of www
         expect(path.join(project, 'www', 'index.html')).toExist();
@@ -85,7 +82,6 @@
         var configXml = new ConfigParser(path.join(project, 'config.xml'));
         expect(configXml.packageName()).toEqual(appId);
         expect(configXml.name()).toEqual(appName);
-        expect(configXml.version()).toEqual(appVersion);
     }
 
     // Check that we got package.json and it was updated correctly
@@ -93,7 +89,6 @@
         const pkg = requireFresh(path.join(project, 'package.json'));
         expect(pkg.name).toEqual(appId);
         expect(pkg.displayName).toEqual(appName);
-        expect(pkg.version).toEqual(appVersion);
     }
 
     // Check that we got no package.json
@@ -105,21 +100,18 @@
     function checkDefaultTemplate () {
         const pkg = requireFresh(path.join(project, 'package.json'));
         expect(pkg.author).toEqual('Apache Cordova Team');
+        expect(pkg.version).toEqual(appVersion);
 
         const configXml = new ConfigParser(path.join(project, 'config.xml'));
         expect(configXml.author()).toEqual('Apache Cordova Team');
+        expect(configXml.version()).toEqual(appVersion);
     }
 
     // Check that we did not use the default template
     function checkNotDefaultTemplate () {
         const configXml = new ConfigParser(path.join(project, 'config.xml'));
         expect(configXml.author()).not.toEqual('Apache Cordova Team');
-    }
-
-    function checkProjectCreatedWithFixtureTemplate () {
-        checkCommonArtifacts();
-        checkNoPackageJson();
-        checkNotDefaultTemplate();
+        expect(configXml.version()).toEqual('0.0.1');
     }
 
     function checkProjectCreatedWithDefaultTemplate () {
@@ -131,361 +123,107 @@
     it('should successfully run without template and use default hello-world app', function () {
         // Create a real project with no template
         // use default cordova-app-hello-world app
-        return create(project, appId, appName, {}, events)
+        return create(project, opts)
             .then(checkProjectCreatedWithDefaultTemplate);
     });
 
     it('should successfully run with Git URL', function () {
         // Create a real project with git URL as template
-        var config = {
-            lib: {
-                www: {
-                    url: 'https://github.com/apache/cordova-app-hello-world',
-                    template: true
-                }
-            }
-        };
-        return createWithMockFetch(project, appId, appName, config, events)
+        opts.template = 'https://github.com/apache/cordova-app-hello-world';
+        return createWithMockFetch(project, opts)
             .then(fetchSpy => {
                 expect(fetchSpy).toHaveBeenCalledTimes(1);
-                expect(fetchSpy.calls.argsFor(0)[0]).toBe(config.lib.www.url);
+                expect(fetchSpy.calls.argsFor(0)[0]).toBe(opts.template);
             })
             .then(checkProjectCreatedWithDefaultTemplate);
     });
 
     it('should successfully run with NPM package (specific version)', function () {
         // Create a real project with npm module as template
-        var config = {
-            lib: {
-                www: {
-                    template: true,
-                    url: 'phonegap-template-vue-f7-tabs@1'
-                }
-            }
-        };
-        return createWithMockFetch(project, appId, appName, config, events)
+        opts.template = 'phonegap-template-vue-f7-tabs@1';
+        return createWithMockFetch(project, opts)
             .then(fetchSpy => {
                 expect(fetchSpy).toHaveBeenCalledTimes(1);
-                expect(fetchSpy.calls.argsFor(0)[0]).toBe(config.lib.www.url);
+                expect(fetchSpy.calls.argsFor(0)[0]).toBe(opts.template);
             })
             .then(checkProjectCreatedWithDefaultTemplate);
     });
 
     it('should successfully run with NPM package (no specific version)', function () {
         // Create a real project with npm module as template
-        var config = {
-            lib: {
-                www: {
-                    template: true,
-                    url: 'phonegap-template-vue-f7-tabs'
-                }
-            }
-        };
-        return createWithMockFetch(project, appId, appName, config, events)
+        opts.template = 'phonegap-template-vue-f7-tabs';
+        return createWithMockFetch(project, opts)
             .then(fetchSpy => {
                 expect(fetchSpy).toHaveBeenCalledTimes(1);
-                expect(fetchSpy.calls.argsFor(0)[0]).toBe(config.lib.www.url);
+                expect(fetchSpy.calls.argsFor(0)[0]).toBe(opts.template);
             })
             .then(checkProjectCreatedWithDefaultTemplate);
     });
 
-    it('should successfully run with template not having a package.json at toplevel', function () {
-        var config = {
-            lib: {
-                www: {
-                    template: true,
-                    url: path.join(__dirname, 'templates', 'nopackage_json')
-                }
-            }
-        };
-        return create(project, appId, appName, config, events)
-            .then(checkProjectCreatedWithFixtureTemplate);
+    it('should successfully run with local template having no package.json in template dir', function () {
+        opts.template = path.join(__dirname, 'templates/withsubdirectory');
+        return create(project, opts)
+            .then(checkCommonArtifacts)
+            .then(checkNoPackageJson)
+            .then(checkNotDefaultTemplate);
     });
 
-    it('should successfully run with template having package.json and no sub directory', function () {
-        var config = {
-            lib: {
-                www: {
-                    template: true,
-                    url: path.join(__dirname, 'templates', 'withpackage_json')
-                }
-            }
-        };
-        return create(project, appId, appName, config, events)
-            .then(checkProjectCreatedWithFixtureTemplate);
-    });
-
-    it('should successfully run with template having package.json, and subdirectory, and no package.json in subdirectory', function () {
-        var config = {
-            lib: {
-                www: {
-                    template: true,
-                    url: path.join(__dirname, 'templates', 'withsubdirectory')
-                }
-            }
-        };
-        return create(project, appId, appName, config, events)
-            .then(checkProjectCreatedWithFixtureTemplate);
-    });
-
-    it('should successfully run with template having package.json, and subdirectory, and package.json in subdirectory', function () {
-        var config = {
-            lib: {
-                www: {
-                    template: true,
-                    url: path.join(__dirname, 'templates', 'withsubdirectory_package_json')
-                }
-            }
-        };
-        return create(project, appId, appName, config, events)
+    it('should successfully run with local template having package.json in template dir', function () {
+        opts.template = path.join(__dirname, 'templates/withsubdirectory_package_json');
+        return create(project, opts)
             .then(checkCommonArtifacts)
             .then(checkPackageJson)
             .then(checkNotDefaultTemplate);
     });
 
-    it('should successfully run config.xml in the www folder and move it outside', function () {
-        var config = {
-            lib: {
-                www: {
-                    template: true,
-                    url: path.join(__dirname, 'templates', 'config_in_www')
-                }
-            }
-        };
-        return create(project, appId, appName, config, events)
-            .then(checkProjectCreatedWithFixtureTemplate);
-    });
-
-    it('should successfully run with www folder as the template', function () {
-        var config = {
-            lib: {
-                www: {
-                    template: true,
-                    url: path.join(__dirname, 'templates', 'config_in_www', 'www')
-                }
-            }
-        };
-        return create(project, appId, appName, config, events)
-            .then(checkProjectCreatedWithFixtureTemplate);
-    });
-
     it('should successfully run with existing, empty destination', function () {
         fs.ensureDirSync(project);
-        return create(project, appId, appName, {}, events)
+        return create(project, opts)
             .then(checkProjectCreatedWithDefaultTemplate);
     });
-
-    describe('when --link-to is provided', function () {
-        function allowSymlinkErrorOnWindows (err) {
-            const onWindows = process.platform.slice(0, 3) === 'win';
-            const isSymlinkError = err && String(err.message).startsWith('Symlinks on Windows');
-            if (onWindows && isSymlinkError) {
-                pending(err.message);
-            } else {
-                throw err;
-            }
-        }
-
-        it('when passed www folder should not move www/config.xml, only copy and update', function () {
-            function checkSymWWW () {
-                // Check if top level dirs exist.
-                var dirs = ['hooks', 'platforms', 'plugins', 'www'];
-                dirs.forEach(function (d) {
-                    expect(path.join(project, d)).toExist();
-                });
-                expect(path.join(project, 'hooks', 'README.md')).toExist();
-
-                // Check if www files exist.
-                expect(path.join(project, 'www', 'index.html')).toExist();
-
-                // Check www/config exists
-                expect(path.join(project, 'www', 'config.xml')).toExist();
-                // Check www/config.xml was not updated.
-                var configXml = new ConfigParser(path.join(project, 'www', 'config.xml'));
-                expect(configXml.packageName()).toEqual('io.cordova.hellocordova');
-                expect(configXml.version()).toEqual('0.0.1');
-                expect(configXml.description()).toEqual('this is the correct config.xml');
-
-                // Check that config.xml was copied to project/config.xml
-                expect(path.join(project, 'config.xml')).toExist();
-                configXml = new ConfigParser(path.join(project, 'config.xml'));
-                expect(configXml.description()).toEqual('this is the correct config.xml');
-                // Check project/config.xml was updated.
-                expect(configXml.packageName()).toEqual(appId);
-                expect(configXml.version()).toEqual('1.0.0');
-
-                // Check that we got no package.json
-                expect(path.join(project, 'package.json')).not.toExist();
-
-                // Check that www is really a symlink,
-                // and project/config.xml , hooks and merges are not
-                expect(fs.lstatSync(path.join(project, 'www')).isSymbolicLink()).toBe(true);
-                expect(fs.lstatSync(path.join(project, 'hooks')).isSymbolicLink()).not.toBe(true);
-                expect(fs.lstatSync(path.join(project, 'config.xml')).isSymbolicLink()).not.toBe(true);
-            }
-            var config = {
-                lib: {
-                    www: {
-                        template: true,
-                        url: path.join(__dirname, 'templates', 'config_in_www', 'www'),
-                        link: true
-                    }
-                }
-            };
-            return create(project, appId, appName, config, events)
-                .then(checkSymWWW)
-                .catch(allowSymlinkErrorOnWindows);
-        });
-
-        it('with subdirectory should not update symlinked project/config.xml', function () {
-            function checkSymSubDir () {
-                // Check if top level dirs exist.
-                var dirs = ['hooks', 'platforms', 'plugins', 'www'];
-                dirs.forEach(function (d) {
-                    expect(path.join(project, d)).toExist();
-                });
-                expect(path.join(project, 'hooks', 'README.md')).toExist();
-
-                // index.js and template subdir folder should not exist (inner files should be copied to the project folder)
-                expect(path.join(project, 'index.js')).not.toExist();
-                expect(path.join(project, 'template')).not.toExist();
-
-                // Check if www files exist.
-                expect(path.join(project, 'www', 'index.html')).toExist();
-
-                // Check that www, and config.xml is really a symlink
-                expect(fs.lstatSync(path.join(project, 'www')).isSymbolicLink()).toBe(true);
-                expect(fs.lstatSync(path.join(project, 'config.xml')).isSymbolicLink()).toBe(true);
-
-                // Check that config.xml was not updated. (symlinked config does not get updated!)
-                var configXml = new ConfigParser(path.join(project, 'config.xml'));
-                expect(configXml.packageName()).toEqual('io.cordova.hellocordova');
-                expect(configXml.version()).toEqual('0.0.1');
-
-                // Check that we got the right config.xml
-                expect(configXml.description()).toEqual('this is the correct config.xml');
-
-                // Check that we got package.json (the correct one) and it was changed
-                var pkjson = requireFresh(path.join(project, 'package.json'));
-                // Pkjson.name should equal config's id.
-                expect(pkjson.name).toEqual(appId.toLowerCase());
-                expect(pkjson.valid).toEqual('true');
-            }
-            var config = {
-                lib: {
-                    www: {
-                        template: true,
-                        url: path.join(__dirname, 'templates', 'withsubdirectory_package_json'),
-                        link: true
-                    }
-                }
-            };
-            return create(project, appId, appName, config, events)
-                .then(checkSymSubDir)
-                .catch(allowSymlinkErrorOnWindows);
-        });
-
-        it('with no config should create one and update it', function () {
-            function checkSymNoConfig () {
-                // Check if top level dirs exist.
-                var dirs = ['hooks', 'platforms', 'plugins', 'www'];
-                dirs.forEach(function (d) {
-                    expect(path.join(project, d)).toExist();
-                });
-                expect(path.join(project, 'hooks', 'hooks.file')).toExist();
-                expect(path.join(project, 'merges', 'merges.file')).toExist();
-
-                // Check if www files exist.
-                expect(path.join(project, 'www', 'index.html')).toExist();
-
-                // Check that config.xml was updated.
-                var configXml = new ConfigParser(path.join(project, 'config.xml'));
-                expect(configXml.packageName()).toEqual(appId);
-
-                // Check that www, hooks, merges are really a symlink; config is not
-                expect(fs.lstatSync(path.join(project, 'www')).isSymbolicLink()).toBe(true);
-                expect(fs.lstatSync(path.join(project, 'hooks')).isSymbolicLink()).toBe(true);
-                expect(fs.lstatSync(path.join(project, 'merges')).isSymbolicLink()).toBe(true);
-                expect(fs.lstatSync(path.join(project, 'config.xml')).isSymbolicLink()).not.toBe(true);
-            }
-
-            var config = {
-                lib: {
-                    www: {
-                        template: true,
-                        url: path.join(__dirname, 'templates', 'noconfig'),
-                        link: true
-                    }
-                }
-            };
-            return create(project, appId, appName, config, events)
-                .then(checkSymNoConfig)
-                .catch(allowSymlinkErrorOnWindows);
-        });
-
-    });
 });
 
 describe('when shit happens', function () {
     it('should fail when dir is missing', function () {
         return expectRejection(
-            create(null, appId, appName, {}, events),
+            create(null, opts),
             new CordovaError('Directory not specified')
         );
     });
 
     it('should fail when dir already exists', function () {
         return expectRejection(
-            create(__dirname, appId, appName, {}, events),
+            create(__dirname, opts),
             new CordovaError('Path already exists and is not empty')
         );
     });
 
     it('should fail when destination is inside template', function () {
-        const config = {
-            lib: {
-                www: {
-                    url: path.join(tmpDir, 'template')
-                }
-            }
-        };
-        const destination = path.join(config.lib.www.url, 'destination');
+        opts.template = path.join(tmpDir, 'template');
         return expectRejection(
-            create(destination, appId, appName, config, events),
+            create(path.join(opts.template, 'destination'), opts),
             new CordovaError('inside the template')
         );
     });
 
     it('should fail when fetch fails', function () {
-        const config = {
-            lib: {
-                www: {
-                    template: true,
-                    url: 'http://localhost:123456789/cordova-create'
-                }
-            }
-        };
         const fetchError = new Error('Fetch fail');
         const failingFetch = jasmine.createSpy('failingFetch')
             .and.callFake(() => Promise.reject(fetchError));
+
+        opts.template = 'http://localhost:123456789/cordova-create';
         return expectRejection(
-            createWith({ fetch: failingFetch })(project, appId, appName, config),
+            createWith({ fetch: failingFetch })(project, opts),
             fetchError
         );
-
     });
 
-    it('should fail when template does not exist', function () {
-        const config = {
-            lib: {
-                www: {
-                    url: path.join(__dirname, 'doesnotexist')
-                }
-            }
-        };
+    // FIXME: we need to improve isRemote to make this different from the test above
+    xit('should fail when template does not exist', function () {
+        opts.template = path.join(__dirname, 'doesnotexist');
         return expectRejection(
-            create(project, appId, appName, config, events),
-            new CordovaError('Could not find directory')
+            create(project, opts),
+            new CordovaError('not a valid template')
         );
     });
 });
diff --git a/spec/helpers.js b/spec/helpers.js
index bc48248..399f292 100644
--- a/spec/helpers.js
+++ b/spec/helpers.js
@@ -23,10 +23,6 @@
 
 const rewire = require('rewire');
 
-// Disable regular console output during tests
-const CordovaLogger = require('cordova-common').CordovaLogger;
-CordovaLogger.get().setLevel(CordovaLogger.ERROR);
-
 // Temporary directory to use for all tests
 const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cordova-create-tests-'));
 
diff --git a/spec/templates/config_in_www/www/config.xml b/spec/templates/config_in_www/www/config.xml
deleted file mode 100644
index ccf0e68..0000000
--- a/spec/templates/config_in_www/www/config.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
--->
-<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
-    <name>HelloCordova</name>
-    <description>this is the correct config.xml</description>
-    <author email="dev@cordova.apache.org" href="http://cordova.io">
-        Apache Cordova Test Team
-    </author>
-    <content src="index.html" />
-    <!-- Whitelist configuration. Refer to https://cordova.apache.org/docs/en/edge/guide_appdev_whitelist_index.md.html -->
-    <plugin name="cordova-plugin-whitelist" spec="1" />
-    <access origin="*" />
-    <allow-intent href="http://*/*" />
-    <allow-intent href="https://*/*" />
-    <allow-intent href="tel:*" />
-    <allow-intent href="sms:*" />
-    <allow-intent href="mailto:*" />
-    <allow-intent href="geo:*" />
-    <platform name="android">
-        <allow-intent href="market:*" />
-    </platform>
-    <platform name="ios">
-        <allow-intent href="itms:*" />
-        <allow-intent href="itms-apps:*" />
-    </platform>
-</widget>
diff --git a/spec/templates/config_in_www/www/index.html b/spec/templates/config_in_www/www/index.html
deleted file mode 100644
index 646f9cb..0000000
--- a/spec/templates/config_in_www/www/index.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE html>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing,
-    software distributed under the License is distributed on an
-    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-     KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
--->
-<html>
-    <head>
-        <!--
-        Customize this policy to fit your own app's needs. For more guidance, see:
-            https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
-        Some notes:
-            * gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
-            * https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
-            * Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
-                * Enable inline JS: add 'unsafe-inline' to default-src
-        -->
-        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
-        <meta name="format-detection" content="telephone=no">
-        <meta name="msapplication-tap-highlight" content="no">
-        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
-        <link rel="stylesheet" type="text/css" href="css/index.css">
-        <title>Hello World</title>
-    </head>
-    <body>
-        <div class="app">
-            <h1>Apache Cordova</h1>
-            <div id="deviceready" class="blink">
-                <p class="event listening">Connecting to Device</p>
-                <p class="event received">Device is Ready</p>
-            </div>
-        </div>
-        <script type="text/javascript" src="cordova.js"></script>
-        <script type="text/javascript" src="js/index.js"></script>
-    </body>
-</html>
diff --git a/spec/templates/noconfig/hooks/hooks.file b/spec/templates/noconfig/hooks/hooks.file
deleted file mode 100644
index e69de29..0000000
--- a/spec/templates/noconfig/hooks/hooks.file
+++ /dev/null
diff --git a/spec/templates/noconfig/merges/merges.file b/spec/templates/noconfig/merges/merges.file
deleted file mode 100644
index e69de29..0000000
--- a/spec/templates/noconfig/merges/merges.file
+++ /dev/null
diff --git a/spec/templates/noconfig/www/index.html b/spec/templates/noconfig/www/index.html
deleted file mode 100644
index 646f9cb..0000000
--- a/spec/templates/noconfig/www/index.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE html>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing,
-    software distributed under the License is distributed on an
-    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-     KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
--->
-<html>
-    <head>
-        <!--
-        Customize this policy to fit your own app's needs. For more guidance, see:
-            https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
-        Some notes:
-            * gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
-            * https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
-            * Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
-                * Enable inline JS: add 'unsafe-inline' to default-src
-        -->
-        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
-        <meta name="format-detection" content="telephone=no">
-        <meta name="msapplication-tap-highlight" content="no">
-        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
-        <link rel="stylesheet" type="text/css" href="css/index.css">
-        <title>Hello World</title>
-    </head>
-    <body>
-        <div class="app">
-            <h1>Apache Cordova</h1>
-            <div id="deviceready" class="blink">
-                <p class="event listening">Connecting to Device</p>
-                <p class="event received">Device is Ready</p>
-            </div>
-        </div>
-        <script type="text/javascript" src="cordova.js"></script>
-        <script type="text/javascript" src="js/index.js"></script>
-    </body>
-</html>
diff --git a/spec/templates/nopackage_json/config.xml b/spec/templates/nopackage_json/config.xml
deleted file mode 100644
index 1e821e0..0000000
--- a/spec/templates/nopackage_json/config.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
--->
-<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
-    <name>HelloCordova</name>
-    <description>this is the very correct config.xml</description>
-    <author email="dev@cordova.apache.org" href="http://cordova.io">
-        Apache Cordova Test Team
-    </author>
-    <content src="index.html" />
-    <!-- Whitelist configuration. Refer to https://cordova.apache.org/docs/en/edge/guide_appdev_whitelist_index.md.html -->
-    <plugin name="cordova-plugin-whitelist" spec="1" />
-    <access origin="*" />
-    <allow-intent href="http://*/*" />
-    <allow-intent href="https://*/*" />
-    <allow-intent href="tel:*" />
-    <allow-intent href="sms:*" />
-    <allow-intent href="mailto:*" />
-    <allow-intent href="geo:*" />
-    <platform name="android">
-        <allow-intent href="market:*" />
-    </platform>
-    <platform name="ios">
-        <allow-intent href="itms:*" />
-        <allow-intent href="itms-apps:*" />
-    </platform>
-</widget>
diff --git a/spec/templates/nopackage_json/www/index.html b/spec/templates/nopackage_json/www/index.html
deleted file mode 100644
index 646f9cb..0000000
--- a/spec/templates/nopackage_json/www/index.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE html>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing,
-    software distributed under the License is distributed on an
-    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-     KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
--->
-<html>
-    <head>
-        <!--
-        Customize this policy to fit your own app's needs. For more guidance, see:
-            https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
-        Some notes:
-            * gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
-            * https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
-            * Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
-                * Enable inline JS: add 'unsafe-inline' to default-src
-        -->
-        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
-        <meta name="format-detection" content="telephone=no">
-        <meta name="msapplication-tap-highlight" content="no">
-        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
-        <link rel="stylesheet" type="text/css" href="css/index.css">
-        <title>Hello World</title>
-    </head>
-    <body>
-        <div class="app">
-            <h1>Apache Cordova</h1>
-            <div id="deviceready" class="blink">
-                <p class="event listening">Connecting to Device</p>
-                <p class="event received">Device is Ready</p>
-            </div>
-        </div>
-        <script type="text/javascript" src="cordova.js"></script>
-        <script type="text/javascript" src="js/index.js"></script>
-    </body>
-</html>
diff --git a/spec/templates/withpackage_json/config.xml b/spec/templates/withpackage_json/config.xml
deleted file mode 100644
index 4b7e53e..0000000
--- a/spec/templates/withpackage_json/config.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
--->
-<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
-    <name>HelloCordova</name>
-    <description>
-        A sample Apache Cordova application that responds to the deviceready event.
-    </description>
-    <author email="dev@cordova.apache.org" href="http://cordova.io">
-        Apache Cordova Test Team
-    </author>
-    <content src="index.html" />
-    <!-- Whitelist configuration. Refer to https://cordova.apache.org/docs/en/edge/guide_appdev_whitelist_index.md.html -->
-    <plugin name="cordova-plugin-whitelist" spec="1" />
-    <access origin="*" />
-    <allow-intent href="http://*/*" />
-    <allow-intent href="https://*/*" />
-    <allow-intent href="tel:*" />
-    <allow-intent href="sms:*" />
-    <allow-intent href="mailto:*" />
-    <allow-intent href="geo:*" />
-    <platform name="android">
-        <allow-intent href="market:*" />
-    </platform>
-    <platform name="ios">
-        <allow-intent href="itms:*" />
-        <allow-intent href="itms-apps:*" />
-    </platform>
-</widget>
diff --git a/spec/templates/withpackage_json/pacakge.json b/spec/templates/withpackage_json/pacakge.json
deleted file mode 100644
index ef6f89e..0000000
--- a/spec/templates/withpackage_json/pacakge.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "name": "template",
-  "version": "1.0.0",
-  "description": "Apache Cordova Application",
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/apache/cordova-app-hello-world.git"
-  },
-  "license": "Apache-2.0",
-  "scripts": {
-    "preinstall": "echo \"Yay npm preinstall script\" ",
-    "postinstall": "echo \"Yay npm postinstall script\" "
-  }
-}
\ No newline at end of file
diff --git a/spec/templates/withpackage_json/www/index.html b/spec/templates/withpackage_json/www/index.html
deleted file mode 100644
index 646f9cb..0000000
--- a/spec/templates/withpackage_json/www/index.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE html>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing,
-    software distributed under the License is distributed on an
-    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-     KIND, either express or implied.  See the License for the
-    specific language governing permissions and limitations
-    under the License.
--->
-<html>
-    <head>
-        <!--
-        Customize this policy to fit your own app's needs. For more guidance, see:
-            https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
-        Some notes:
-            * gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
-            * https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
-            * Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
-                * Enable inline JS: add 'unsafe-inline' to default-src
-        -->
-        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
-        <meta name="format-detection" content="telephone=no">
-        <meta name="msapplication-tap-highlight" content="no">
-        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
-        <link rel="stylesheet" type="text/css" href="css/index.css">
-        <title>Hello World</title>
-    </head>
-    <body>
-        <div class="app">
-            <h1>Apache Cordova</h1>
-            <div id="deviceready" class="blink">
-                <p class="event listening">Connecting to Device</p>
-                <p class="event received">Device is Ready</p>
-            </div>
-        </div>
-        <script type="text/javascript" src="cordova.js"></script>
-        <script type="text/javascript" src="js/index.js"></script>
-    </body>
-</html>