Skip to content

Instantly share code, notes, and snippets.

@DavidFrahm
Last active December 28, 2020 00:05
Show Gist options
  • Save DavidFrahm/2ce16cb6aec90b2c428f to your computer and use it in GitHub Desktop.
Save DavidFrahm/2ce16cb6aec90b2c428f to your computer and use it in GitHub Desktop.
Cordova build hook, to use build version from config.xml in your hybrid app
#!/usr/bin/env node
// This plugin replaces text in a file with the app version from config.xml.
var wwwFileToReplace = "js/build.js";
var fs = require('fs');
var path = require('path');
var rootdir = process.argv[2];
function loadConfigXMLDoc(filePath) {
var fs = require('fs');
var xml2js = require('xml2js');
var json = "";
try {
var fileData = fs.readFileSync(filePath, 'ascii');
var parser = new xml2js.Parser();
parser.parseString(fileData.substring(0, fileData.length), function (err, result) {
//console.log("config.xml as JSON", JSON.stringify(result, null, 2));
json = result;
});
console.log("File '" + filePath + "' was successfully read.");
return json;
} catch (ex) {
console.log(ex)
}
}
function replace_string_in_file(filename, to_replace, replace_with) {
var data = fs.readFileSync(filename, 'utf8');
var result = data.replace(new RegExp(to_replace, "g"), replace_with);
fs.writeFileSync(filename, result, 'utf8');
}
var configXMLPath = "config.xml";
var rawJSON = loadConfigXMLDoc(configXMLPath);
var version = rawJSON.widget.$.version;
console.log("Version:", version);
var rootdir = process.argv[2];
var currentBuildPlatforms = process.env.CORDOVA_PLATFORMS.split(",");
console.log("Current build platforms: ", currentBuildPlatforms);
if (rootdir) {
currentBuildPlatforms.forEach(function(val, index, array) {
var wwwPath = "";
switch(val) {
case "ios":
wwwPath = "platforms/ios/www/";
break;
case "android":
wwwPath = "platforms/android/assets/www/";
break;
default:
console.log("Unknown build platform: " + val);
}
var fullfilename = path.join(rootdir, wwwPath + wwwFileToReplace);
if (fs.existsSync(fullfilename)) {
replace_string_in_file(fullfilename, "%%VERSION%%", version);
console.log("Replaced version in file: " + fullfilename);
}
});
}
angular.module('equipmentShare').controller('AppController', function ($scope, BUILD) {
$scope.appVersion = BUILD.VERSION;
});
/*
* Cordova build hook will replace this version with the actual version from config.xml.
*/
angular.module('equipmentShare').constant('BUILD', {
VERSION: "%%VERSION%%"
});
<!-- This example is from an Ionic app. Modify as needed for your framework/templating solution. -->
... other content ...
<ion-item>
Version {{appVersion}}
</ion-item>
... other content ...
@sat007
Copy link

sat007 commented Aug 29, 2017

Hi, have added this in my cordova VS solution under hooks folder and changed this line to var wwwFileToReplace = "js/app.js" in my angular module with constant as .constant('BUILD', {
VERSION: "%%VERSION%%" // %%VERSION%% will be replaced with the actual version from config.xml
})
but still its not returning version information from config instead it just display this %%version%% any idea ?

@vaibhav915
Copy link

Hi,
I am facing same issue. Any update on this one ??
I can see %%version%% as a text instead of actual value ? Any help is appreciated

@KeySeeDev
Copy link

@jfoclpf
Copy link

jfoclpf commented Dec 27, 2020

@DavidFrahm just FYI in new versions of cordova an error is triggered here

var currentBuildPlatforms = process.env.CORDOVA_PLATFORMS.split(',')

error:

var currentBuildPlatforms = process.env.CORDOVA_PLATFORMS.split(',')
                                                          ^

TypeError: Cannot read property 'split' of undefined

apparently process.env.CORDOVA_PLATFORMS does not exist anymore

@jfoclpf
Copy link

jfoclpf commented Dec 28, 2020

Hi there, I made a new functional hook script stored at hooks/setVersion.js. I just tested it now and it works (just in Android, for iOS you just need to replicate the wwwDir)

#!/usr/bin/env node

// This plugin replaces text '%%VERSION%%' in a file with the app version from config.xml.

var wwwFileToReplace = 'js/main.js'

var fs = require('fs')
var path = require('path')

module.exports = function (context) {
  var projectRoot = context.opts.projectRoot
  const wwwDir = path.join(projectRoot, 'platforms', 'android', 'app', 'src', 'main', 'assets', 'www')

  var configXMLPath = 'config.xml'
  loadConfigXMLDoc(configXMLPath, (rawJSON) => {
    var version = rawJSON.widget.$.version
    console.log('Version:', version)

    var fullfilename = path.join(wwwDir, wwwFileToReplace)
    if (fs.existsSync(fullfilename)) {
      replaceStringInFile(fullfilename, '%%VERSION%%', version)
      console.log(context.hook + ': Replaced version in file: ' + path.relative(projectRoot, fullfilename))
    } else {
      console.error('File does not exist: ', path.relative(projectRoot, fullfilename))
      process.exit(1)
    }
  })
}

function loadConfigXMLDoc (filePath, callback) {
  var fs = require('fs')
  var xml2js = require('xml2js')
  try {
    var fileData = fs.readFileSync(filePath, 'ascii')
    var parser = new xml2js.Parser()
    parser.parseString(fileData.substring(0, fileData.length), function (err, result) {
      if (err) {
        console.error(err)
        process.exit(1)
      } else {
        // console.log("config.xml as JSON", JSON.stringify(result, null, 2))
        console.log("File '" + filePath + "' was successfully read.")
        callback(result)
      }
    })
  } catch (ex) {
    console.log(ex)
    process.exit(1)
  }
}

function replaceStringInFile (filename, toReplace, replaceWith) {
  var data = fs.readFileSync(filename, 'utf8')

  var result = data.replace(new RegExp(toReplace, 'g'), replaceWith)
  fs.writeFileSync(filename, result, 'utf8')
}

You have also to add in config.xml

  <hook src="hooks/setVersion.js" type="after_prepare"/>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment