You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ag...@apache.org on 2014/12/23 17:21:14 UTC

[2/5] docs commit: CB-6751 Rewrite docs generation to use Node instead of Ruby (close #236)

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/docs/zh/3.5.0/guide/platforms/blackberry10/upgrading.md
----------------------------------------------------------------------
diff --git a/docs/zh/3.5.0/guide/platforms/blackberry10/upgrading.md b/docs/zh/3.5.0/guide/platforms/blackberry10/upgrading.md
index 06e5202..62431f7 100644
--- a/docs/zh/3.5.0/guide/platforms/blackberry10/upgrading.md
+++ b/docs/zh/3.5.0/guide/platforms/blackberry10/upgrading.md
@@ -380,7 +380,6 @@ platform add blackberry10`.
     
         < 外掛程式名稱 ="捕獲"value="org.apache.cordova.media.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
         
-    
     自:
     
         < 外掛程式名稱 ="捕獲"value="org.apache.cordova.capture.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
@@ -406,7 +405,6 @@ platform add blackberry10`.
     
          < 外掛程式名稱 ="捕獲"value="org.apache.cordova.media.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
         
-    
     自:
     
          < 外掛程式名稱 ="捕獲"value="org.apache.cordova.capture.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
@@ -434,7 +432,6 @@ platform add blackberry10`.
     
         < 外掛程式名稱 ="捕獲"value="org.apache.cordova.media.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
         
-    
     自:
     
         < 外掛程式名稱 ="捕獲"value="org.apache.cordova.capture.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
@@ -460,7 +457,6 @@ platform add blackberry10`.
     
          < 外掛程式名稱 ="捕獲"value="org.apache.cordova.media.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
         
-    
     自:
     
          < 外掛程式名稱 ="捕獲"value="org.apache.cordova.capture.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/docs/zh/edge/guide/platforms/blackberry/upgrading.md
----------------------------------------------------------------------
diff --git a/docs/zh/edge/guide/platforms/blackberry/upgrading.md b/docs/zh/edge/guide/platforms/blackberry/upgrading.md
index 95899f2..f080461 100644
--- a/docs/zh/edge/guide/platforms/blackberry/upgrading.md
+++ b/docs/zh/edge/guide/platforms/blackberry/upgrading.md
@@ -333,7 +333,6 @@ BlackBerryOS/行動手冊:
     
         < 外掛程式名稱 ="捕獲"value="org.apache.cordova.media.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
         
-    
     自:
     
         < 外掛程式名稱 ="捕獲"value="org.apache.cordova.capture.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
@@ -359,7 +358,6 @@ BlackBerryOS/行動手冊:
     
          < 外掛程式名稱 ="捕獲"value="org.apache.cordova.media.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
         
-    
     自:
     
          < 外掛程式名稱 ="捕獲"value="org.apache.cordova.capture.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
@@ -387,7 +385,6 @@ BlackBerryOS/行動手冊:
     
         < 外掛程式名稱 ="捕獲"value="org.apache.cordova.media.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
         
-    
     自:
     
         < 外掛程式名稱 ="捕獲"value="org.apache.cordova.capture.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
@@ -413,7 +410,6 @@ BlackBerryOS/行動手冊:
     
          < 外掛程式名稱 ="捕獲"value="org.apache.cordova.media.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
         
-    
     自:
     
          < 外掛程式名稱 ="捕獲"value="org.apache.cordova.capture.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/docs/zh/edge/guide/platforms/blackberry10/upgrading.md
----------------------------------------------------------------------
diff --git a/docs/zh/edge/guide/platforms/blackberry10/upgrading.md b/docs/zh/edge/guide/platforms/blackberry10/upgrading.md
index 06e5202..62431f7 100644
--- a/docs/zh/edge/guide/platforms/blackberry10/upgrading.md
+++ b/docs/zh/edge/guide/platforms/blackberry10/upgrading.md
@@ -380,7 +380,6 @@ platform add blackberry10`.
     
         < 外掛程式名稱 ="捕獲"value="org.apache.cordova.media.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
         
-    
     自:
     
         < 外掛程式名稱 ="捕獲"value="org.apache.cordova.capture.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
@@ -406,7 +405,6 @@ platform add blackberry10`.
     
          < 外掛程式名稱 ="捕獲"value="org.apache.cordova.media.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
         
-    
     自:
     
          < 外掛程式名稱 ="捕獲"value="org.apache.cordova.capture.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
@@ -434,7 +432,6 @@ platform add blackberry10`.
     
         < 外掛程式名稱 ="捕獲"value="org.apache.cordova.media.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
         
-    
     自:
     
         < 外掛程式名稱 ="捕獲"value="org.apache.cordova.capture.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
@@ -460,7 +457,6 @@ platform add blackberry10`.
     
          < 外掛程式名稱 ="捕獲"value="org.apache.cordova.media.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
         
-    
     自:
     
          < 外掛程式名稱 ="捕獲"value="org.apache.cordova.capture.MediaCapture"/ >< 外掛程式名稱 ="連絡人"value="org.apache.cordova.pim.Contact"/ >
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/cordova/jodoc.js
----------------------------------------------------------------------
diff --git a/lib/cordova/jodoc.js b/lib/cordova/jodoc.js
new file mode 100644
index 0000000..3ee184d
--- /dev/null
+++ b/lib/cordova/jodoc.js
@@ -0,0 +1,130 @@
+/*
+       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.
+*/
+/*jslint node: true */
+/*global which, exec */
+var fs = require("fs-extra");
+var path = require("path");
+require('shelljs/global');
+
+var JoDoc = (function () {
+    'use strict';
+
+    var JO_DOC_CLI = "jodoc",
+        TEMPLATE_PATH = path.resolve(path.join(path.dirname(module.filename), '..', '..', 'template', 'docs')),
+        useLocalJoDoc = true;
+
+    /**
+    * Creates a new instance of JoDoc
+    * @param inputDirectory Directory which contains files which has to be processed.
+    * @param outputDirectory Directory to which store generated files.
+    * @param options Options for the generation process.
+    */
+    function JoDoc(inputDirectory, outputDirectory, options) {
+        this.input_directory = inputDirectory;
+        this.output_directory = outputDirectory;
+        this.options = options;
+
+        this.template_directories = [ path.join(TEMPLATE_PATH, "default") ];
+        if (options.lang) {
+            this.template_directories.push(path.join(TEMPLATE_PATH, options.lang));
+        }
+
+        this.check_dependencies();
+    }
+
+    JoDoc.prototype.check_dependencies = function () {
+        if (!which('jodoc') && !useLocalJoDoc) {
+            console.error('The jodoc script is not in your path');
+            process.exit(1);
+        }
+
+        [this.input_directory, this.template_directories[0]].forEach(function (dir) {
+            if (!fs.existsSync(dir)) {
+                console.error("The directory " + dir + " has to be present");
+                process.exit(1);
+            }
+
+            var stat = fs.lstatSync(dir);
+            if (!stat.isDirectory()) {
+                console.error("The path " + dir + " is not directory.");
+                process.exit(1);
+            }
+        });
+    };
+
+    JoDoc.prototype.run = function () {
+        var self = this,
+            currentDirectory = process.cwd(),
+            nullDevice = "/dev/null",
+            templateFile = path.join(this.output_directory, "index.html"),
+            commandLine,
+            child,
+            executableName;
+        // Copy HTML template assets
+        this.template_directories.forEach(function (templateDir) {
+            if (!fs.existsSync(templateDir)) {
+                if (self.options.verbose > 0) {
+                    console.log("Template folder " + templateDir + " not exists, skipping");
+                }
+
+                return;
+            }
+
+            var stat = fs.lstatSync(templateDir);
+            if (!stat.isDirectory()) {
+                return;
+            }
+
+            fs.copySync(templateDir, self.output_directory);
+        });
+
+        process.chdir(this.input_directory);
+
+        executableName = JO_DOC_CLI;
+        if (useLocalJoDoc) {
+            executableName = path.join(module.filename, "../../../node_modules/.bin/jodoc");
+        }
+
+        commandLine = executableName + " --output \"" + this.output_directory + "\" --title \"Cordova API Documentation\" --template \"" + templateFile + "\" ./";
+        if (self.options.verbose > 0) {
+            console.log("Running joDoc-js with command line:");
+            console.log(commandLine);
+        }
+
+        if (this.options.verbose < 2) {
+            commandLine = commandLine + " > " + nullDevice + " 2> " + nullDevice;
+        }
+
+        if (this.options.verbose > 1) {
+            console.info("Running jodoc from " + this.input_directory + " directory");
+            console.info(commandLine);
+        }
+
+        child = exec(commandLine);
+        if (child.code !== 0) {
+            console.error("Error during execution of jodoc. Error code is: " + child.code);
+            process.exit(child.code);
+        }
+
+        process.chdir(currentDirectory);
+    };
+
+    return JoDoc;
+}());
+module.exports = JoDoc;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/cordova/post/addtitle.js
----------------------------------------------------------------------
diff --git a/lib/cordova/post/addtitle.js b/lib/cordova/post/addtitle.js
new file mode 100644
index 0000000..774b58f
--- /dev/null
+++ b/lib/cordova/post/addtitle.js
@@ -0,0 +1,72 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var fs = require("fs-extra");
+var path = require("path");
+var cheerio = require('cheerio');
+
+/**
+* Preprocessor which updates top stripe with header or the page.
+*/
+var AddTitle = (function () {
+    'use strict';
+
+    /**
+    * Creates a new instance of FileMerger
+    * @param options Options for the generation process.
+    */
+    function AddTitle(options) {
+        this.options = options || { verbose: 0 };
+        this.stage = "Adding title";
+    }
+
+    AddTitle.prototype.run = function (file) {
+        if (this.options.verbose > 1) {
+            console.log("Add title to file " + file);
+        }
+
+        var $ = cheerio.load(fs.readFileSync(file)),
+            title_source,
+            title_target,
+            title;
+        title_source = $('#content > h1');
+        if (title_source.length === 0) {
+            return null;
+        }
+
+        title_source = $(title_source[0]);
+        title_target = $('#subheader > h1');
+        if (title_target.length === 0) {
+            return null;
+        }
+
+        title_target = $(title_target[0]);
+        if (this.options.verbose > 1) {
+            console.log("Change title from " + title_target.text() + " to " + title_source.text());
+        }
+
+        title = title_source.text();
+        title_target.text(title);
+        fs.writeFileSync(file, $.html());
+        return title;
+    };
+
+    return AddTitle;
+}());
+module.exports = AddTitle;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/cordova/post/index.js
----------------------------------------------------------------------
diff --git a/lib/cordova/post/index.js b/lib/cordova/post/index.js
new file mode 100644
index 0000000..a2950df
--- /dev/null
+++ b/lib/cordova/post/index.js
@@ -0,0 +1,28 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var AddTitle = require("./addtitle"),
+    UpdateIndex = require("./updateindex"),
+    UpdateKeywordIndex = require("./updatekeywordindex"),
+    TableOfContents = require("./tableofcontents"),
+    VersionMenu = require("./versionmenu"),
+    NavigationMenu = require("./navigationmenu"),
+    Prettify = require("./prettify"),
+    NoIndex = require("./noindex");
+module.exports = [AddTitle, UpdateIndex, UpdateKeywordIndex, TableOfContents, VersionMenu, NavigationMenu, Prettify, NoIndex];

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/cordova/post/navigationmenu.js
----------------------------------------------------------------------
diff --git a/lib/cordova/post/navigationmenu.js b/lib/cordova/post/navigationmenu.js
new file mode 100644
index 0000000..14a7ff0
--- /dev/null
+++ b/lib/cordova/post/navigationmenu.js
@@ -0,0 +1,116 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var fs = require("fs-extra");
+var path = require("path");
+var cheerio = require('cheerio'),
+    FileHelpers = require("../../file_helpers");
+
+/**
+* Preprocessor which updates top stripe with header or the page.
+*/
+var NavigationMenu = (function () {
+    'use strict';
+
+    /**
+    * Creates a new instance of FileMerger
+    * @param options Options for the generation process.
+    */
+    function NavigationMenu(options) {
+        this.options = options || { verbose: 0 };
+        this.stage = "Building navigation menu";
+        this.sections = [];
+
+        var filename = path.join(FileHelpers.getTmpDirectory(), 'jodoc', 'index.md.html');
+        if (!fs.existsSync(filename)) {
+            throw new Error("index.md.html was not generated in " + FileHelpers.getTmpDirectory() + "/jodoc");
+        }
+        var $ = cheerio.load(fs.readFileSync(filename)),
+            h1_set,
+            ul_set,
+            count;
+
+        h1_set   = $('#home > h1');
+        ul_set   = $('#home > ul');
+        count    = h1_set.length;
+
+        function getAppender(links) {
+            function appendLink(index, element) {
+                links.push(element);
+            }
+
+            return appendLink;
+        }
+        for (var i = 0; i < count; i++) {
+            var links = [],
+                appendLink = getAppender(links);
+
+            $('li > h2 > a', ul_set[i]).each(appendLink);
+
+            this.sections.push({
+                'title': $(h1_set[i]).text(),
+                'links': links
+            });
+        }
+    }
+
+    NavigationMenu.prototype.run = function (file) {
+        if (path.extname(file) !== ".html") {
+            return;
+        }
+
+        if (this.options.verbose > 1) {
+            console.log("Appending file to nav menu " + file);
+        }
+
+        var $ = cheerio.load(fs.readFileSync(file));
+        for (var i = 0; i < this.sections.length; i++) {
+            var section = this.sections[i];
+            this.insertTitle(section.title, $);
+            this.insertLinks(section.links, $);
+        }
+
+        fs.writeFileSync(file, $.html());
+        return $.html();
+    };
+
+    NavigationMenu.prototype.insertTitle = function (title, $) {
+        var element = cheerio("<h1></h1>");
+        element.text(title);
+        $('#sidebar').first().append(element).append("\n");
+    };
+
+    NavigationMenu.prototype.insertLinks = function (links, $) {
+        var ul = cheerio("<ul></ul>"),
+            li;
+
+        ul.append("\n");
+        for (var i = 0; i < links.length; i++) {
+            var link = links[i];
+            li = cheerio("<li></li>");
+            li.append(link) ;
+            ul.append(li).append("\n");
+        }
+
+        $('#sidebar').first().append(ul).append("\n");
+    };
+
+    return NavigationMenu;
+}());
+module.exports = NavigationMenu;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/cordova/post/noindex.js
----------------------------------------------------------------------
diff --git a/lib/cordova/post/noindex.js b/lib/cordova/post/noindex.js
new file mode 100644
index 0000000..44b9409
--- /dev/null
+++ b/lib/cordova/post/noindex.js
@@ -0,0 +1,110 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var fs = require("fs-extra");
+var path = require("path");
+var cheerio = require('cheerio'),
+    FileHelpers = require("../../file_helpers");
+
+/**
+* Preprocessor which adds meta tag robot=noindex, to all not latest versions of the docs.
+*/
+var NoIndex = (function () {
+    'use strict';
+    var latestVersion = null;
+
+    /**
+    * Creates a new instance of FileMerger
+    * @param options Options for the generation process.
+    */
+    function NoIndex(options) {
+        latestVersion = getLatestIndex();
+        this.options = options || { verbose: 0 };
+        this.stage = "Insert noindex";
+    }
+
+    NoIndex.prototype.run = function (file) {
+        if (!file.match(/.html$/)) {
+            return null;
+        }
+
+        var version = this.options.version,
+            language = this.options.lang,
+            $,
+            meta_tags;
+        if (latestVersion == version && language == 'en') {
+            if (this.options.verbose > 1) {
+                console.log("File belongs to language " + language + " and version " + version + " which is assumed to be latest");
+            }
+
+            return;
+        }
+
+        $ = cheerio.load(fs.readFileSync(file));
+        meta_tags = $('head meta');
+        meta_tags.append(createNoIndexMeta());
+
+        var hmtl = fs.writeFileSync(file, $.html());
+        return hmtl;
+    };
+
+    function getLatestIndex() {
+        // skip if we have the latest version
+        if (latestVersion !== null) {
+          return latestVersion;
+        }
+
+        // collect all english versions because they are the most up-to-date
+        var docs_path = FileHelpers.getDefaultInputDirectory(),
+            versions  = [],
+            lang_dir = path.join(docs_path, 'en'),
+            version_dirs;
+
+        version_dirs = fs.readdirSync(lang_dir);
+            version_dirs.forEach(function (version) {
+                var configFile = path.join(lang_dir, version, "config.json"),
+                    configData = JSON.parse(fs.readFileSync(configFile));
+                versions.push(version);
+            });
+
+        // sort the version list because Dir does not guarantee an order
+        versions.sort().reverse();
+
+        // we want the latest stable release
+        // if edge is the most recent, remove it
+        var last = versions.shift();
+        if (last == 'edge') {
+            last = versions.shift();
+        }
+
+        // return the latest version
+        latestVersion = last;
+        return last;
+    }
+
+    function createNoIndexMeta() {
+        var element = cheerio("<meta></meta>");
+        element.attr('name', 'robots');
+        element.attr('label', 'noindex');
+        return element;
+    }
+
+    return NoIndex;
+}());
+module.exports = NoIndex;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/cordova/post/prettify.js
----------------------------------------------------------------------
diff --git a/lib/cordova/post/prettify.js b/lib/cordova/post/prettify.js
new file mode 100644
index 0000000..7d21c18
--- /dev/null
+++ b/lib/cordova/post/prettify.js
@@ -0,0 +1,58 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var fs = require("fs-extra");
+var path = require("path");
+var cheerio = require('cheerio');
+
+/**
+* Preprocessor which updates top stripe with header or the page.
+*/
+var Prettify = (function () {
+    'use strict';
+
+    /**
+    * Creates a new instance of FileMerger
+    * @param options Options for the generation process.
+    */
+    function Prettify(options) {
+        this.options = options || { verbose: 0 };
+        this.stage = "Prettify";
+    }
+
+    Prettify.prototype.run = function (file) {
+        if (path.extname(file) !== ".html") {
+            return;
+        }
+
+        if (this.options.verbose > 1) {
+            console.log("Prettify file " + file);
+        }
+
+        var $ = cheerio.load(fs.readFileSync(file)),
+            element;
+        element = $('#content pre');
+        element.attr('class', 'prettyprint');
+        fs.writeFileSync(file, $.html());
+        return element;
+    };
+
+    return Prettify;
+}());
+module.exports = Prettify;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/cordova/post/tableofcontents.js
----------------------------------------------------------------------
diff --git a/lib/cordova/post/tableofcontents.js b/lib/cordova/post/tableofcontents.js
new file mode 100644
index 0000000..24403f3
--- /dev/null
+++ b/lib/cordova/post/tableofcontents.js
@@ -0,0 +1,114 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var fs = require("fs-extra");
+var path = require("path");
+var cheerio = require('cheerio');
+
+/**
+* Preprocessor which updates top stripe with header or the page.
+*/
+var TableOfContents = (function () {
+    'use strict';
+
+    /**
+    * Creates a new instance of TableOfContents
+    * @param options Options for the generation process.
+    */
+    function TableOfContents(options) {
+        this.options = options || { verbose: 0 };
+        this.stage = "Building TOC";
+    }
+
+    TableOfContents.prototype.run = function (file) {
+        var filenamePart = path.basename(file);
+        if (filenamePart === "_index.html" || filenamePart === "index.html") {
+            return;
+        }
+
+        var doc = cheerio.load(fs.readFileSync(file)),
+            option_set = [],
+            current_h1 = "",
+            indentation = "\xa0\xa0\xa0\xa0\xa0\xa0",
+            select,
+            subheader;
+        doc("#content h1, #content h2").each(function (index, elementDom) {
+            var element = cheerio(elementDom),
+                child = element.children().first(),
+                option,
+                s,
+                anchorName,
+                anchor;
+            if (elementDom.name === 'h1') {
+                current_h1 = element.text();
+                option = cheerio("<option></option");
+                anchorName =  child.attr('name');
+                if (anchorName !== null && anchorName !== undefined) {
+                    anchorName = encodeURIComponent(anchorName);
+                    option.attr('value', anchorName.replace(/\s/g, '%20'));
+                }
+
+                option.text(element.text());
+                option_set.push(option);
+            } else {
+                // Remove all leading and trailing non-word characters
+                // Replace all inner non-word characters with an underscore
+                // Replace all spaces since encodeURIComponent not produce correct URI
+                s = element.text()
+                    .replace(/^\W+|\W+$/g, '')
+                    .replace(/\W+/g, '_').toLowerCase();
+                option = cheerio("<option></option>");
+                anchorName = current_h1 + "_" + s;
+                anchorName = encodeURIComponent(anchorName);
+                anchorName = anchorName.replace(/%2520/g, '%20');
+                option.attr('value', anchorName);
+                option.text(indentation + "- " + element.text());
+                option_set.push(option);
+
+                anchor = cheerio("<a></a>");
+                anchor.attr('name', anchorName);
+                anchor.text(element.text());
+                element.text('');
+                element.append(anchor);
+            }
+        });
+
+        // Return if one or less elements found (useless selection box)
+        if (option_set.length <= 1) {
+            return null;
+        }
+
+        // Add select menu to the subheader
+        select = cheerio("<select></select>");
+        option_set.forEach(function (optionGroup) {
+            select.append(optionGroup.clone());
+        });
+        subheader = doc("#subheader > small").first();
+        if (subheader.length === 0) {
+            return null;
+        }
+
+        subheader.append(select);
+        fs.writeFileSync(file, doc.html().replace('&amp;nbsp;', '&nbsp;'));
+        return option_set;
+    };
+
+    return TableOfContents;
+}());
+module.exports = TableOfContents;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/cordova/post/updateindex.js
----------------------------------------------------------------------
diff --git a/lib/cordova/post/updateindex.js b/lib/cordova/post/updateindex.js
new file mode 100644
index 0000000..a8f3a79
--- /dev/null
+++ b/lib/cordova/post/updateindex.js
@@ -0,0 +1,65 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var fs = require("fs-extra");
+var path = require("path");
+var cheerio = require('cheerio');
+
+/**
+* Preprocessor which updates top stripe with header or the page.
+*/
+var UpdateIndex = (function () {
+    'use strict';
+    var header_title  = 'Home';
+
+    /**
+    * Creates a new instance of FileMerger
+    * @param options Options for the generation process.
+    */
+    function UpdateIndex(options) {
+        this.options = options || { verbose: 0 };
+        this.stage = "Update index";
+        this.header_title = header_title;
+    }
+
+    UpdateIndex.prototype.run = function (file) {
+        if (path.basename(file) !== "index.md.html") {
+            return false;
+        }
+
+        if (this.options.verbose > 1) {
+            console.info("Update index");
+        }
+
+        var $ = cheerio.load(fs.readFileSync(file)),
+            title_target;
+        title_target = $('#subheader > h1');
+        if (title_target.length !== 0) {
+            title_target = $(title_target[0]);
+            title_target.text(header_title);
+        }
+
+        fs.writeFileSync(file, $.html());
+        fs.renameSync(file, path.join(path.dirname(file), "index.html"));
+        return true;
+    };
+
+    return UpdateIndex;
+}());
+module.exports = UpdateIndex;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/cordova/post/updatekeywordindex.js
----------------------------------------------------------------------
diff --git a/lib/cordova/post/updatekeywordindex.js b/lib/cordova/post/updatekeywordindex.js
new file mode 100644
index 0000000..e5a48f9
--- /dev/null
+++ b/lib/cordova/post/updatekeywordindex.js
@@ -0,0 +1,80 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var fs = require("fs-extra");
+var path = require("path");
+var cheerio = require('cheerio');
+
+/**
+* Preprocessor which updates top stripe with header or the page.
+*/
+var UpdateKeywordIndex = (function () {
+    'use strict';
+    var header_title  = 'Keyword Index',
+        content_title = 'Keyword Index';
+
+    /**
+    * Creates a new instance of FileMerger
+    * @param options Options for the generation process.
+    */
+    function UpdateKeywordIndex(options) {
+        this.options = options || { verbose: 0 };
+        this.stage = "Update keywork index";
+        this.header_title = header_title;
+        this.content_title = content_title;
+    }
+
+    UpdateKeywordIndex.prototype.run = function (file) {
+        if (path.basename(file) !== "_index.html") {
+            return false;
+        }
+
+        if (this.options.verbose > 1) {
+            console.info("Update keyword index");
+        }
+
+        var $ = cheerio.load(fs.readFileSync(file)),
+            element,
+            content;
+        element = $('#subheader > h1');
+        if (element.length !== 0) {
+            element = $(element[0]);
+            element.text(header_title);
+        }
+
+        element = $('#content > h1');
+        if (element.length !== 0) {
+            element = $(element[0]);
+            element.text(content_title);
+        }
+
+        element = $('#content > hr');
+        if (element.length !== 0) {
+            element = $(element[0]);
+            element.remove();
+        }
+
+        content = $.html();
+        content = content.replace(/"index\.md\.html/g, '"index.html');
+        fs.writeFileSync(file, content);
+    };
+
+    return UpdateKeywordIndex;
+}());
+module.exports = UpdateKeywordIndex;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/cordova/post/versionmenu.js
----------------------------------------------------------------------
diff --git a/lib/cordova/post/versionmenu.js b/lib/cordova/post/versionmenu.js
new file mode 100644
index 0000000..50b9d24
--- /dev/null
+++ b/lib/cordova/post/versionmenu.js
@@ -0,0 +1,142 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var fs = require("fs-extra");
+var path = require("path");
+var cheerio = require('cheerio');
+
+/**
+* Preprocessor which updates top stripe with header or the page.
+*/
+var VersionMenu = (function () {
+    'use strict';
+    var languages = [],
+        versions = [];
+
+
+    /**
+    * Creates a new instance of FileMerger
+    * @param options Options for the generation process.
+    */
+    function VersionMenu(options) {
+        this.options = options || { verbose: 0 };
+        this.stage = "Populate version menu";
+        languages = [];
+        versions = [];
+        this.buildVersionsData();
+    }
+
+    VersionMenu.prototype.run = function (file) {
+        if (path.extname(file) !== ".html") {
+            return;
+        }
+
+        if (this.options.verbose > 1) {
+            console.info("Building version menu for file " + file);
+        }
+
+        var $ = cheerio.load(fs.readFileSync(file)),
+            element;
+
+        element = $('#header small select').first();
+        this.generateMenu().forEach(function (optionGroup) {
+            element.append(optionGroup).append("\n");
+        });
+        fs.writeFileSync(file, $.html());
+    };
+
+    VersionMenu.prototype.buildVersionsData = function () {
+        var docs_path = path.resolve(path.join(module.filename, '..', '..', '..', '..', 'docs')),
+            lang_dirs,
+            lang_labels = [];
+
+        lang_dirs = fs.readdirSync(docs_path);
+        lang_dirs.forEach(function (lang) {
+            versions[lang] = [];
+            var lang_dir = path.join(docs_path, lang),
+                version_dirs;
+            version_dirs = fs.readdirSync(lang_dir);
+            version_dirs.forEach(function (version) {
+                var configFile = path.join(lang_dir, version, "config.json"),
+                    configData = JSON.parse(fs.readFileSync(configFile));
+                versions[lang].push(version);
+                lang_labels[lang] = configData.language;
+            });
+
+            languages.push({ lang: lang, label: lang_labels[lang] });
+        });
+        languages = languages.sort(function (a, b) {
+            if (a.label === b.label) {
+                return 0;
+            }
+
+            if (a.label > b.label) {
+                return 1;
+            }
+
+            return -1;
+        });
+    };
+
+    VersionMenu.prototype.generateMenu = function () {
+        var result = [],
+            langGroup,
+            versionData,
+            versionOption,
+            lang,
+            versionIndex,
+            version,
+            mapper,
+            key;
+
+        mapper = function (item) {
+            return item;
+        };
+
+        for (key in languages) {
+            if (languages.hasOwnProperty(key)) {
+                lang = languages[key].lang;
+                langGroup = cheerio("<optgroup></optgroup>");
+                langGroup.append("\n");
+                langGroup.attr('label', languages[key].label);
+                langGroup.attr('value', lang);
+
+                versionData = versions[lang].map(mapper).reverse();
+                for (versionIndex = 0; versionIndex < versionData.length; versionIndex = versionIndex + 1) {
+                    version = versionData[versionIndex];
+                    versionOption = cheerio("<option></option>");
+                    if (this.options.version === version && this.options.lang === lang) {
+                        versionOption.attr('selected', 'selected');
+                    }
+
+                    versionOption.attr('value', version);
+                    versionOption.text(version);
+                    langGroup.append(versionOption).append("\n");
+                }
+
+                result.push(langGroup);
+            }
+        }
+
+        return result;
+    };
+
+    return VersionMenu;
+}());
+module.exports = VersionMenu;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/cordova/pre/filemerger.js
----------------------------------------------------------------------
diff --git a/lib/cordova/pre/filemerger.js b/lib/cordova/pre/filemerger.js
new file mode 100644
index 0000000..5f8debf
--- /dev/null
+++ b/lib/cordova/pre/filemerger.js
@@ -0,0 +1,105 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var fs = require("fs-extra"),
+    path = require("path"),
+    FileHelpers = require("../../file_helpers");
+
+var FileMerger = (function () {
+    'use strict';
+
+    var config = null;
+
+    /**
+    * Creates a new instance of FileMerger
+    * @param options Options for the generation process.
+    */
+    function FileMerger(options) {
+        this.options = options || { verbose: 0 };
+        this.stage = "Merge files";
+
+        config = null;
+    }
+
+    FileMerger.prototype.run = function (file) {
+        if (this.options.verbose > 1) {
+            console.log("Merge file " + file);
+        }
+
+        if (file.match(/\/guide\//)) {
+            return null;
+        }
+
+        if (!fs.existsSync(file)) {
+            return null;
+        }
+
+        this.filename  = path.basename(file);
+        this.directory = path.dirname(file);
+
+        var filesToAppend,
+            cfg = this.config(),
+            i,
+            filepath;
+        if (!cfg.hasOwnProperty(this.filename)) {
+            return null;
+        }
+
+        filesToAppend = cfg[this.filename];
+        for (i = 0; i < filesToAppend.length; i += 1) {
+            filepath = filesToAppend[i];
+
+            // skip the file that we're merging into because it's listed in config.json
+            if (path.basename(filepath) === this.filename) {
+                if (this.options.verbose > 0) {
+                    console.log("Skipping " + filesToAppend[i] + " from " + this.filename + " section since it has same base name as file to merge");
+                }
+            } else {
+                filepath = path.join(FileHelpers.getTmpDirectory(), 'docs', filepath);
+                fs.appendFileSync(file, "\n\n---\n");
+                fs.appendFileSync(file, fs.readFileSync(filepath, "utf-8").trim());
+                fs.removeSync(filepath);
+            }
+        }
+    };
+
+    FileMerger.prototype.config = function () {
+        if (config !== null) {
+            return config;
+        }
+
+        var directory = this.directory,
+            file,
+            configJSON;
+        while (config === null) {
+            file = path.join(directory, 'config.json');
+            if (fs.existsSync(file)) {
+                configJSON = fs.readFileSync(file);
+                config = JSON.parse(configJSON).merge;
+            } else {
+                directory = fs.dirname(directory);
+            }
+        }
+
+        return config;
+    };
+
+    return FileMerger;
+}());
+module.exports = FileMerger;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/cordova/pre/index.js
----------------------------------------------------------------------
diff --git a/lib/cordova/pre/index.js b/lib/cordova/pre/index.js
new file mode 100644
index 0000000..db3de0b
--- /dev/null
+++ b/lib/cordova/pre/index.js
@@ -0,0 +1,22 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var FileMerger = require("./filemerger"),
+    YamlFrontMatter = require("./yamlfrontmatter");
+module.exports = [YamlFrontMatter, FileMerger];

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/cordova/pre/yamlfrontmatter.js
----------------------------------------------------------------------
diff --git a/lib/cordova/pre/yamlfrontmatter.js b/lib/cordova/pre/yamlfrontmatter.js
new file mode 100644
index 0000000..e7e7fbd
--- /dev/null
+++ b/lib/cordova/pre/yamlfrontmatter.js
@@ -0,0 +1,68 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var fs = require("fs-extra"),
+    path = require("path"),
+    yaml = require("js-yaml");
+
+var YamlFrontMatter = (function () {
+    'use strict';
+
+    /**
+    * Creates a new instance of FileMerger
+    * @param options Options for the generation process.
+    */
+    function YamlFrontMatter(options) {
+        this.options = options || { verbose: 0 };
+        this.stage = "Starting YAML stripping";
+    }
+
+    YamlFrontMatter.prototype.run = function (file) {
+        if (this.options.verbose > 1) {
+            console.log("String YAML from file " + file);
+        }
+
+        var content = fs.readFileSync(file, "utf8"),
+            yamlRegexStripper = /^(---\s*\n[\s\S]*?\n?)^(---\s*$\n?)/m,
+            match = yamlRegexStripper.exec(content),
+            yamlData;
+        if (match === null) {
+            return {};
+        }
+
+        try {
+            yamlData = yaml.safeLoad(match[1]);
+        }
+        catch (yamle) {
+            console.error("File: " + file);
+            if (this.options.verbose > 1) {
+                console.error("YAML Exception during processing following content:\n" + content);
+            }
+
+            throw yamle;
+        }
+
+        content = content.substr(match[0].length);
+        fs.writeFileSync(file, content);
+        return yamlData;
+    };
+
+    return YamlFrontMatter;
+}());
+module.exports = YamlFrontMatter;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/docs_comparer.js
----------------------------------------------------------------------
diff --git a/lib/docs_comparer.js b/lib/docs_comparer.js
new file mode 100644
index 0000000..a6c8c13
--- /dev/null
+++ b/lib/docs_comparer.js
@@ -0,0 +1,243 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var fs = require("fs-extra");
+var path = require("path");
+var JoDoc = require("./cordova/jodoc");
+var FileHelpers = require("./file_helpers");
+var cheerio = require('cheerio');
+var jsdiff = require('diff');
+require('colors');
+
+var DocsComparer = (function () {
+    'use strict';
+
+    function processEachFile(source_path, fileCallback, directoryCallback) {
+        var directoryEntries = fs.readdirSync(source_path);
+        directoryEntries.forEach(function (dirEntry) {
+            var fullPath = path.join(source_path, dirEntry),
+                stat;
+            if (!fs.existsSync(fullPath)) {
+                return;
+            }
+
+            stat = fs.lstatSync(fullPath);
+            if (stat.isFile()) {
+                fileCallback(fullPath);
+                return;
+            }
+
+            if (stat.isDirectory()) {
+                if (directoryCallback(fullPath)) {
+                    processEachFile(fullPath, fileCallback, directoryCallback);
+                }
+
+                return;
+            }
+        });
+    }
+
+    /**
+    * Creates a new instance of DocsComparer
+    * @param inputDirectory Directory which contains files which has to be processed.
+    * @param outputDirectory Directory to which store generated files.
+    */
+    function DocsComparer(originalDirectory, outputDirectory) {
+        this.original_directory = originalDirectory || path.join(FileHelpers.getRootDirectory(), "public");
+        this.output_directory = outputDirectory || path.join(FileHelpers.getRootDirectory(), "public/test");
+    }
+
+    /**
+    * Compares two sets of documentation
+    * @param language Language which has to be compared.
+    * @param version Version which files has to be compared.
+    * @param verbose_mode Verbosity level.
+    */
+    DocsComparer.prototype.compare = function (language, version, verbose_mode) {
+        var self = this,
+            ignore_list = ['.', '..', '.DS_Store', 'test'];
+
+        verbose_mode = verbose_mode || 0;
+        if (verbose_mode > 0) {
+            console.log("Comparing docs for lang " + language + " and version " + version);
+            console.log("Clearing output directory");
+        }
+
+        fs.readdirSync(this.original_directory).forEach(function (language_dir) {
+            if (ignore_list.indexOf(language_dir) !== -1) {
+                return;
+            }
+
+            if (language && language_dir !== language) {
+                return;
+            }
+
+            var language_path = path.join(self.original_directory, language_dir);
+
+            fs.readdirSync(language_path).forEach(function (version_dir) {
+                if (ignore_list.indexOf(version_dir) !== -1) {
+                    return;
+                }
+
+                if (version && version_dir !== version) {
+                    return;
+                }
+
+                var output_path = path.join(self.output_directory, language_dir, version_dir),
+                    input_path = path.join(self.original_directory, language_dir, version_dir),
+                    options = {
+                        lang: language_dir,
+                        version: version_dir,
+                        verbose: verbose_mode
+                    };
+
+                console.log(" => Comparing the Cordova Documentation for " + version_dir + "-" + language_dir + "...");
+                self.process(input_path, output_path, options);
+            });
+        });
+    };
+    DocsComparer.prototype.process = function (original_directory, output_path, options) {
+        var self = this;
+        console.log("Processing " + original_directory + " and " + output_path);
+        var compareFiles = function (fileName) {
+            var relativePath = path.relative(original_directory, fileName);
+            var targetFile = path.join(output_path, relativePath);
+            if (!fs.existsSync(targetFile)) {
+                console.error("Path " + relativePath + " is missing in the new docs");
+                return;
+            }
+
+            if (/.html$/.test(relativePath)) {
+                // Compare HTML content.
+                self.compareHtml(fileName, targetFile, relativePath, options);
+            } else {
+                var originalFileStat = fs.statSync(fileName);
+                var targetFileStat = fs.statSync(targetFile);
+                var originalFileSize = originalFileStat.size;
+                var targetFileSize = targetFileStat.size;
+                self.compareFileSize(fileName, targetFile, relativePath, options);
+            }
+        };
+        processEachFile(original_directory, compareFiles, function (directoryName) {
+            var relativePath = path.relative(original_directory, directoryName);
+            var targetFile = path.join(output_path, relativePath);
+            if (!fs.existsSync(targetFile)) {
+                console.error("Dir " + relativePath + "/ is missing in the new docs");
+                return;
+            }
+
+            // console.log(relativePath + "\\");
+            return true;
+        });
+    };
+
+    DocsComparer.prototype.compareHtml = function (sourceFile, targetFile, relativePath, options) {
+        if (options.verbose > 0) {
+            console.log("Compare " + relativePath);
+        }
+
+        if (relativePath == "_index.html") {
+            if (options.lang == "zh" || options.lang == "ja" || options.lang == "ko" || options.lang == "ru") {
+                console.log("File " + relativePath + " is skipped for the Asian languages and Russian, since this is results in out of memory exception");
+                return;
+            }
+        }
+
+        var cheerioOptions = {
+            normalizeWhitespace: true,
+            xmlMode: true
+        };
+        var sourceDom = cheerio.load(fs.readFileSync(sourceFile), cheerioOptions),
+            targetDom = cheerio.load(fs.readFileSync(targetFile), cheerioOptions);
+
+        // This is identical subsets
+        this.compareDomSubset(sourceDom, targetDom, "head", relativePath, options);
+        this.compareDomSubset(sourceDom, targetDom, "#sidebar", relativePath, options);
+        this.compareDomSubset(sourceDom, targetDom, "#header", relativePath, options);
+        this.compareDomSubset(sourceDom, targetDom, "#content", relativePath, options);
+
+        // Almost identical subsets
+        this.compareDomSubset(sourceDom, targetDom, "#subheader", relativePath, options);
+    };
+
+    DocsComparer.prototype.compareDomSubset = function (sourceDom, targetDom, subset, relativePath, options) {
+        var sourceHtml = sourceDom(subset).html(),
+            targetHtml = targetDom(subset).html(),
+            diff;
+
+        diff = jsdiff.diffChars(sourceHtml, targetHtml);
+        var changed = false;
+        diff.forEach(function (part) {
+            changed = part.added || part.removed;
+        });
+        if (changed) {
+            console.error("Subset of DOM '" + subset + "' for path " + relativePath + " is different.");
+            if (options.verbose > 0) {
+                diff.forEach(function(part){
+                    // green for additions, red for deletions
+                    // grey for common parts
+                    var color = part.added ? 'green' : (part.removed ? 'red' : 'grey');
+                    process.stderr.write(part.value[color]);
+                });
+
+                console.log();
+            }
+        }
+    };
+
+    DocsComparer.prototype.compareDom = function (sourceDom, targetDom, relativePath, options) {
+        var sourceHtml = sourceDom.html();
+        var targetHtml = targetDom.html();
+
+        var diff = jsdiff.diffChars(sourceHtml, targetHtml);
+        var changed = false;
+        diff.forEach(function (part) {
+            changed = part.added || part.removed;
+        });
+        if (changed) {
+            console.error("DOM for path " + relativePath + " is different.");
+            if (options.verbose > 0) {
+                diff.forEach(function(part){
+                    // green for additions, red for deletions
+                    // grey for common parts
+                    var color = part.added ? 'green' : (part.removed ? 'red' : 'grey');
+                    process.stderr.write(part.value[color]);
+                });
+
+                console.log();
+            }
+        }
+    };
+
+    DocsComparer.prototype.compareFileSize = function (sourceFile, targetFile, relativePath) {
+        var originalFileStat = fs.statSync(sourceFile);
+        var targetFileStat = fs.statSync(targetFile);
+        var originalFileSize = originalFileStat.size;
+        var targetFileSize = targetFileStat.size;
+
+        if (originalFileSize != targetFileSize) {
+            console.error("Path " + relativePath + " is different. Old size: " + originalFileSize + ". New size: " + targetFileSize);
+        }
+
+        return originalFileSize != targetFileSize;
+    };
+
+    return DocsComparer;
+}());
+module.exports = DocsComparer;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/docs_generator.js
----------------------------------------------------------------------
diff --git a/lib/docs_generator.js b/lib/docs_generator.js
new file mode 100644
index 0000000..1243d83
--- /dev/null
+++ b/lib/docs_generator.js
@@ -0,0 +1,176 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var fs = require("fs-extra");
+var path = require("path");
+var JoDoc = require("./cordova/jodoc");
+var FileHelpers = require("./file_helpers");
+
+var DocsGenerator = (function () {
+    'use strict';
+
+    function processEachFile(source_path, callback) {
+        var directoryEntries = fs.readdirSync(source_path);
+        directoryEntries.forEach(function (dirEntry) {
+            var fullPath = path.join(source_path, dirEntry),
+                stat;
+            if (!fs.existsSync(fullPath)) {
+                return;
+            }
+
+            stat = fs.lstatSync(fullPath);
+            if (stat.isFile()) {
+                callback(fullPath);
+                return;
+            }
+
+            if (stat.isDirectory()) {
+                processEachFile(fullPath, callback);
+                return;
+            }
+        });
+    }
+
+    /**
+    * Creates a new instance of DocsGenerator
+    * @param inputDirectory Directory which contains files which has to be processed.
+    * @param outputDirectory Directory to which store generated files.
+    */
+    function DocsGenerator(inputDirectory, outputDirectory) {
+        this.input_directory = inputDirectory || FileHelpers.getDefaultInputDirectory();
+        this.output_directory = outputDirectory || FileHelpers.getDefaultOutputDirectory();
+        this.working_directory = path.join(FileHelpers.getTmpDirectory(), 'docs');
+    }
+
+    /* Cordova Build-Time Steps
+    * - For each version of the documentation
+    *   - Create a work space for the docs processing
+    *   - Pre-file processing
+    *   - Run joDoc
+    *   - Pre-file processing
+    *   - Release and cleanup
+    */
+    DocsGenerator.prototype.run = function (language, version, verbose_mode) {
+        var self = this,
+            ignore_list = ['.', '..', '.DS_Store'];
+
+        verbose_mode = verbose_mode || 0;
+        if (verbose_mode > 0) {
+            console.log("Generating docs for lang " + language + " and version " + version);
+            console.log("Clearing output directory");
+        }
+
+        fs.removeSync(this.output_directory);
+
+        fs.readdirSync(this.input_directory).forEach(function (language_dir) {
+            if (ignore_list.indexOf(language_dir) !== -1) {
+                return;
+            }
+
+            if (language && language_dir !== language) {
+                return;
+            }
+
+            var language_path = path.join(self.input_directory, language_dir);
+
+            fs.readdirSync(language_path).forEach(function (version_dir) {
+                if (ignore_list.indexOf(version_dir) !== -1) {
+                    return;
+                }
+
+                if (version && version_dir !== version) {
+                    return;
+                }
+
+                var output_path = path.join(self.output_directory, language_dir, version_dir),
+                    input_path = path.join(self.input_directory, language_dir, version_dir),
+                    options = {
+                        lang: language_dir,
+                        version: version_dir,
+                        verbose: verbose_mode
+                    };
+
+                console.log(" => Generating the Cordova Documentation for " + version_dir + "-" + language_dir + "...");
+                self.process(input_path, output_path, options);
+            });
+        });
+    };
+
+    DocsGenerator.prototype.process = function (input_path, output_path, options) {
+        fs.copySync(input_path, this.working_directory);
+
+        var preprocessPath,
+            processPath,
+            generated_path;
+        preprocessPath = this.before_jodoc(this.working_directory, options);
+        processPath = this.jodocify(preprocessPath, options);
+        generated_path = this.after_jodoc(processPath, options);
+
+        fs.ensureDirSync(path.dirname(output_path));
+        fs.renameSync(generated_path, output_path);
+
+        fs.removeSync(FileHelpers.getTmpDirectory());
+    };
+
+    DocsGenerator.prototype.run_process_sequence = function (sequence_name, source_path, options) {
+        var currentModuleDir = path.dirname(module.filename),
+            directoryEntries,
+            sequenceProcessors,
+            processors;
+        directoryEntries = fs.readdirSync(path.join(currentModuleDir, "cordova", sequence_name));
+        sequenceProcessors = require("./cordova/" + sequence_name + "/index");
+        processors = sequenceProcessors.map(function (ProcessorConstructor) {
+            return new ProcessorConstructor(options);
+        });
+        processors.forEach(function (process_module) {
+            if (options.verbose > 0) {
+                console.log("Stage: " + process_module.stage);
+            }
+
+            processEachFile(source_path, function (filename) {
+                process_module.run(filename);
+            });
+        });
+
+        return source_path;
+    };
+
+    DocsGenerator.prototype.before_jodoc = function (source_path, options) {
+        this.run_process_sequence("pre", source_path, options);
+
+        return source_path;
+    };
+
+    DocsGenerator.prototype.jodocify = function (source_path, options) {
+        var output_directory = path.join(FileHelpers.getTmpDirectory(), 'jodoc');
+
+        new JoDoc(source_path, output_directory, options).run();
+        fs.ensureDirSync(output_directory);
+
+        return output_directory;
+    };
+
+    DocsGenerator.prototype.after_jodoc = function (source_path, options) {
+        this.run_process_sequence("post", source_path, options);
+        return source_path;
+    };
+
+    return DocsGenerator;
+}());
+module.exports = DocsGenerator;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/lib/file_helpers.js
----------------------------------------------------------------------
diff --git a/lib/file_helpers.js b/lib/file_helpers.js
new file mode 100644
index 0000000..ba5a3bc
--- /dev/null
+++ b/lib/file_helpers.js
@@ -0,0 +1,59 @@
+/*
+       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.
+*/
+/*jslint node: true */
+var fs = require("fs-extra");
+var path = require("path");
+
+var FileHelpers = (function () {
+    'use strict';
+
+    var FileHelpers = {};
+
+    /**
+    * Gets default directory for source files.
+    */
+    FileHelpers.getDefaultInputDirectory = function () {
+        return path.join(FileHelpers.getRootDirectory(), "docs");
+    };
+
+    /**
+    * Gets default directory for final output.
+    * @remarks Right now used non default folder, to not mix with Ruby implementation.
+    */
+    FileHelpers.getDefaultOutputDirectory = function () {
+        return path.join(FileHelpers.getRootDirectory(), "public/test");
+    };
+
+    /**
+    * Gets temporary directory, where files will be processed.
+    */
+    FileHelpers.getTmpDirectory = function () {
+        return path.join(FileHelpers.getRootDirectory(), "tmp");
+    };
+
+    /**
+    * Gets absolute path for the Cordova Docs root directory
+    */
+    FileHelpers.getRootDirectory = function () {
+        return path.resolve(path.join(path.dirname(module.filename), ".."));
+    };
+
+    return FileHelpers;
+}());
+module.exports = FileHelpers;

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/package.json
----------------------------------------------------------------------
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..2283eee
--- /dev/null
+++ b/package.json
@@ -0,0 +1,39 @@
+{
+  "name": "cordova-docs",
+  "version": "3.6.1",
+  "description": "Documentation for the Apache Cordova",
+  "main": "index.js",
+  "directories": {
+    "doc": "docs"
+  },
+  "dependencies": {
+    "cheerio": "^0.17.0",
+    "esrever": "^0.1.0",
+    "fs-extra": "^0.11.1",
+    "jodoc": "git://github.com/kant2002/jodoc-js",
+    "js-yaml": "^3.2.2",
+    "shelljs": "^0.3.0",
+    "yargs": "^1.3.1"
+  },
+  "devDependencies": {
+    "colors": "^1.0.3",
+    "diff": "^1.2.0",
+    "jshint": "^2.5.8",
+    "mocha": "^1.21.4"
+  },
+  "scripts": {
+    "jshint": "node node_modules/jshint/bin/jshint lib spec",
+    "test": "npm run jshint && npm run mocha",
+    "mocha": "./node_modules/.bin/mocha --recursive ./spec"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/apache/cordova-docs.git"
+  },
+  "author": "",
+  "license": "ISC",
+  "bugs": {
+    "url": "https://github.com/apache/cordova-docs/issues"
+  },
+  "homepage": "https://github.com/apache/cordova-docs"
+}

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/spec/cordova/add_title_spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova/add_title_spec.js b/spec/cordova/add_title_spec.js
new file mode 100644
index 0000000..ce070d1
--- /dev/null
+++ b/spec/cordova/add_title_spec.js
@@ -0,0 +1,69 @@
+/*
+       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.
+*/
+/*jslint node: true */
+/*global describe, it, beforeEach, afterEach, after, before */
+(function () {
+    'use strict';
+    var assert = require("assert"),
+        path = require('path'),
+        fs = require('fs'),
+        cheerio = require('cheerio'),
+        AddTitle = require("../../lib/cordova/post/addtitle"),
+        SpecHelpers = require("../spec_helpers");
+
+    describe('AddTitle', function () {
+        var sut,
+            files;
+        
+        before(function (done) {
+            var tmp_directory = SpecHelpers.create_tmp_directory_assets(module.filename);
+            sut = new AddTitle();
+            files = {
+                'normal': path.join(tmp_directory, 'example.html'),
+                'no_source': path.join(tmp_directory, 'example_no_source.html'),
+                'no_target': path.join(tmp_directory, 'example_no_target.html')
+            };
+            done();
+        });
+        
+        after(function (done) {
+            SpecHelpers.remove_tmp_directory();
+            done();
+        });
+
+        it('should set the title', function () {
+            var testing_file = files.normal,
+                result = sut.run(testing_file),
+                dom;
+            assert.strictEqual('Accelerometer', result);
+            dom = cheerio.load(fs.readFileSync(testing_file));
+            assert.strictEqual('Accelerometer', dom('#subheader > h1').first().html());
+        });
+
+        it('should skip files with no source title', function () {
+            var result = sut.run(files.no_source);
+            assert.strictEqual(null, result);
+        });
+
+        it('should skip files with no target title', function () {
+            var result = sut.run(files.no_target);
+            assert.strictEqual(null, result);
+        });
+    });
+}());
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/spec/cordova/prettify_spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova/prettify_spec.js b/spec/cordova/prettify_spec.js
new file mode 100644
index 0000000..f699f9b
--- /dev/null
+++ b/spec/cordova/prettify_spec.js
@@ -0,0 +1,63 @@
+/*
+       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.
+*/
+/*jslint node: true */
+/*global describe, it, beforeEach, afterEach, after, before */
+(function () {
+    'use strict';
+    var assert = require("assert"),
+        path = require('path'),
+        fs = require('fs'),
+        cheerio = require('cheerio'),
+        Prettify = require("../../lib/cordova/post/prettify"),
+        SpecHelpers = require("../spec_helpers");
+
+    describe('Prettify', function () {
+        var sut,
+            files;
+        
+        beforeEach(function (done) {
+            var tmp_directory = SpecHelpers.create_tmp_directory_assets(module.filename);
+            sut = new Prettify();
+            files = {
+                'normal': path.join(tmp_directory, 'example.html')
+            };
+            done();
+        });
+        
+        afterEach(function (done) {
+            SpecHelpers.remove_tmp_directory();
+            done();
+        });
+
+        it('should find some code blocks', function () {
+            var code_tags = sut.run(files.normal);
+            assert.ok(code_tags.length > 0);
+        });
+
+        it('should add the prettyprint class to each code block', function () {
+            var testing_file = files.normal,
+                dom,
+                initial_title,
+                new_title;
+            sut.run(files.normal);
+            dom = cheerio.load(fs.readFileSync(files.normal));
+            assert.ok(dom('#content pre.prettyprint').length > 0);
+        });
+    });
+}());
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/spec/cordova/table_of_contents_spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova/table_of_contents_spec.js b/spec/cordova/table_of_contents_spec.js
new file mode 100644
index 0000000..29fe2f7
--- /dev/null
+++ b/spec/cordova/table_of_contents_spec.js
@@ -0,0 +1,118 @@
+/*
+       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.
+*/
+/*jslint node: true */
+/*global describe, it, beforeEach, afterEach, after, before */
+(function () {
+    'use strict';
+    var assert = require("assert"),
+        path = require('path'),
+        fs = require('fs'),
+        esrever = require('esrever'),
+        cheerio = require('cheerio'),
+        TableOfContents = require("../../lib/cordova/post/tableofcontents"),
+        SpecHelpers = require("../spec_helpers");
+
+    describe('TableOfContents', function () {
+        var sut,
+            files;
+        
+        beforeEach(function (done) {
+            var tmp_directory = SpecHelpers.create_tmp_directory_assets(module.filename);
+            sut = new TableOfContents();
+            files = {
+                'normal': path.join(tmp_directory, 'example.html'),
+                'no_source': path.join(tmp_directory, 'example_no_source.html'),
+                'no_target': path.join(tmp_directory, 'example_no_target.html')
+            };
+            done();
+        });
+        
+        afterEach(function (done) {
+            SpecHelpers.remove_tmp_directory();
+            done();
+        });
+
+        it('should find the table of content values', function () {
+            var result = sut.run(files.normal);
+            assert.strictEqual(32, result.length);
+        });
+
+        it('should find all <h1> elements', function () {
+            var result = sut.run(files.normal),
+                headers = [];
+            
+            result.forEach(function (header, index) {
+                var match = header.toString().match(/-/);
+                if (match === null) {
+                    headers.push(header);
+                }
+            });
+            assert.strictEqual(8, headers.length);
+        });
+
+        it('should find all <h2> elements', function () {
+            var result = sut.run(files.normal),
+                headers = [];
+            
+            result.forEach(function (header, index) {
+                var match = header.toString().match(/-/);
+                if (match !== null) {
+                    // if nil != (header =~ /-/) and (header =~ /-/) > 0 }
+                    headers.push(header);
+                }
+            });
+            assert.strictEqual(24, headers.length);
+        });
+
+        it('should ignore whitespace in the target name', function () {
+            var result = sut.run(files.normal),
+                names = [],
+                doc = cheerio.load(fs.readFileSync(files.normal));
+            
+            //result = result.reverse();
+            //console.log(result[0]);
+            assert.ok(doc("#content > h1, #content > h2").length > 0, "Should found H1 and H2");
+            doc("#content > h1, #content > h2").each(function (index, element) {
+                var child = cheerio(element).children().first(),
+                    resultElement = result.shift(),
+                    resultElementHtml = resultElement.toString(),
+                    valueMatch = resultElementHtml.match(/value=\"([^\"]*)\"/);
+                assert.ok(valueMatch !== null, "Could not find value in the resulting HTML '" + resultElementHtml + "' which should match to '" + child.attr('name') + "'");
+                assert.strictEqual(valueMatch[1], child.attr('name'));
+            });
+        });
+
+        it('should create a HTML select element', function () {
+            var result = sut.run(files.normal),
+                doc = cheerio.load(files.normal);
+            
+            assert.ok(('#subheader > small > select').length > 0);
+        });
+
+        it('should skip files with no source title', function () {
+            var result = sut.run(files.no_source);
+            assert.strictEqual(null, result);
+        });
+
+        it('should skip files with no target title', function () {
+            var result = sut.run(files.no_target);
+            assert.ok(null === result, "Find something when should not");
+        });
+    });
+}());
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/spec/cordova/update_index_spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova/update_index_spec.js b/spec/cordova/update_index_spec.js
new file mode 100644
index 0000000..5fee632
--- /dev/null
+++ b/spec/cordova/update_index_spec.js
@@ -0,0 +1,77 @@
+/*
+       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.
+*/
+/*jslint node: true */
+/*global describe, it, beforeEach, afterEach, after, before */
+(function () {
+    'use strict';
+    var assert = require("assert"),
+        path = require('path'),
+        fs = require('fs'),
+        cheerio = require('cheerio'),
+        UpdateIndex = require("../../lib/cordova/post/updateindex"),
+        SpecHelpers = require("../spec_helpers");
+
+    describe('UpdateIndex', function () {
+        var sut,
+            files;
+        
+        beforeEach(function (done) {
+            var tmp_directory = SpecHelpers.create_tmp_directory_assets(module.filename);
+            sut = new UpdateIndex();
+            files = {
+                'input': path.join(tmp_directory, 'index.md.html'),
+                'output': path.join(tmp_directory, 'index.html')
+            };
+            done();
+        });
+        
+        afterEach(function (done) {
+            SpecHelpers.remove_tmp_directory();
+            done();
+        });
+
+        it('should skip all files but index.md.html', function () {
+            assert.strictEqual(false, sut.run('index.md'));
+            assert.strictEqual(false, sut.run('index.html'));
+            assert.strictEqual(false, sut.run('_index.md.html'));
+        });
+
+        it('should rename the title', function () {
+            var testing_file = files.normal,
+                dom,
+                initial_title,
+                new_title;
+            dom = cheerio.load(fs.readFileSync(files.input));
+            initial_title = dom('#subheader > h1').first().html();
+            assert.notStrictEqual(sut.header_title, initial_title);
+            sut.run(files.input);
+            dom = cheerio.load(fs.readFileSync(files.output));
+            new_title = dom('#subheader > h1').first().html();
+            assert.strictEqual(sut.header_title, new_title);
+        });
+
+        it('should rename the file', function () {
+            assert.strictEqual(true, fs.existsSync(files.input));
+            assert.strictEqual(false, fs.existsSync(files.output));
+            var result = sut.run(files.input);
+            assert.strictEqual(false, fs.existsSync(files.input));
+            assert.strictEqual(true, fs.existsSync(files.output));
+        });
+    });
+}());
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-docs/blob/455ed599/spec/cordova/update_keyword_index_spec.js
----------------------------------------------------------------------
diff --git a/spec/cordova/update_keyword_index_spec.js b/spec/cordova/update_keyword_index_spec.js
new file mode 100644
index 0000000..6ff1061
--- /dev/null
+++ b/spec/cordova/update_keyword_index_spec.js
@@ -0,0 +1,96 @@
+/*
+       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.
+*/
+/*jslint node: true */
+/*global describe, it, beforeEach, afterEach, after, before */
+(function () {
+    'use strict';
+    var assert = require("assert"),
+        path = require('path'),
+        fs = require('fs'),
+        cheerio = require('cheerio'),
+        UpdateKeywordIndex = require("../../lib/cordova/post/updatekeywordindex"),
+        SpecHelpers = require("../spec_helpers");
+
+    describe('UpdateKeywordIndex', function () {
+        var sut,
+            file;
+        
+        beforeEach(function (done) {
+            var tmp_directory = SpecHelpers.create_tmp_directory_assets(module.filename);
+            sut = new UpdateKeywordIndex();
+            file = path.join(tmp_directory, '_index.html');
+            done();
+        });
+        
+        afterEach(function (done) {
+            SpecHelpers.remove_tmp_directory();
+            done();
+        });
+
+        it('should skip all files but _index.html', function () {
+            assert.strictEqual(false, sut.run('index.md'));
+            assert.strictEqual(false, sut.run('index.html'));
+            assert.strictEqual(false, sut.run('index.htm'));
+            assert.strictEqual(false, sut.run('_index.htm'));
+            assert.strictEqual(false, sut.run('index.md.html'));
+        });
+
+        it('should rename the title', function () {
+            var dom,
+                initial_title,
+                new_title;
+            dom = cheerio.load(fs.readFileSync(file));
+            initial_title = dom('#subheader > h1').first().html();
+            assert.notStrictEqual(sut.header_title, initial_title);
+            sut.run(file);
+            dom = cheerio.load(fs.readFileSync(file));
+            new_title = dom('#subheader > h1').first().html();
+            assert.strictEqual(sut.header_title, new_title);
+        });
+
+        it('should rename the h1', function () {
+            var dom,
+                initial_title,
+                new_title;
+            dom = cheerio.load(fs.readFileSync(file));
+            initial_title = dom('#content > h1').first().html();
+            assert.notStrictEqual(sut.content_title, initial_title);
+            sut.run(file);
+            dom = cheerio.load(fs.readFileSync(file));
+            new_title = dom('#content > h1').first().html();
+            assert.strictEqual(sut.content_title, new_title);
+        });
+
+        it('should remove the <hr/>', function () {
+            var dom;
+            dom = cheerio.load(fs.readFileSync(file));
+            assert.notStrictEqual(0, dom('#content > hr').length);
+            sut.run(file);
+            dom = cheerio.load(fs.readFileSync(file));
+            assert.strictEqual(0, dom('#content > hr').length);
+        });
+
+        it('should update references from index.md.html to index.html', function () {
+            var fileToSearch = "index.md.html";
+            assert.notStrictEqual(-1, fs.readFileSync(file).toString().indexOf(fileToSearch));
+            sut.run(file);
+            assert.strictEqual(-1, fs.readFileSync(file).toString().indexOf(fileToSearch));
+        });
+    });
+}());
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org