Skip to content

Commit

Permalink
Cocoapods support improvement, using podspec tag in plugin.xml (apach…
Browse files Browse the repository at this point in the history
  • Loading branch information
knight9999 authored and erisu committed Jan 16, 2019
1 parent f62845d commit ece3b87
Show file tree
Hide file tree
Showing 8 changed files with 1,173 additions and 215 deletions.
387 changes: 289 additions & 98 deletions bin/templates/scripts/cordova/Api.js

Large diffs are not rendered by default.

212 changes: 196 additions & 16 deletions bin/templates/scripts/cordova/lib/Podfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,22 @@ var superspawn = require('cordova-common').superspawn;
var CordovaError = require('cordova-common').CordovaError;

Podfile.FILENAME = 'Podfile';
Podfile.declarationRegexpMap = {
'use_frameworks!': 'use[-_]frameworks!?',
'inhibit_all_warnings!': 'inhibit[-_]all[-_]warnings!?'
};

function Podfile (podFilePath, projectName, minDeploymentTarget) {
this.declarationToken = '##INSERT_DECLARATION##';
this.sourceToken = '##INSERT_SOURCE##';
this.podToken = '##INSERT_POD##';

this.path = podFilePath;
this.projectName = projectName;
this.minDeploymentTarget = minDeploymentTarget || '9.0';
this.contents = null;
this.sources = null;
this.declarations = null;
this.pods = null;
this.__dirty = false;

Expand All @@ -56,10 +64,72 @@ function Podfile (podFilePath, projectName, minDeploymentTarget) {
} else {
events.emit('verbose', 'Podfile found in platforms/ios');
// parse for pods
this.pods = this.__parseForPods(fs.readFileSync(this.path, 'utf8'));
var fileText = fs.readFileSync(this.path, 'utf8');
this.declarations = this.__parseForDeclarations(fileText);
this.sources = this.__parseForSources(fileText);
this.pods = this.__parseForPods(fileText);
}
}

Podfile.prototype.__parseForDeclarations = function (text) {
// split by \n
var arr = text.split('\n');

// getting lines between "platform :ios, '9.0'"" and "target 'HelloCordova'" do
var declarationsPreRE = new RegExp('platform :ios,\\s+\'[^\']+\'');
var declarationsPostRE = new RegExp('target\\s+\'[^\']+\'\\s+do');
var declarationRE = new RegExp('^\\s*[^#]');

return arr.reduce(function (acc, line) {
switch (acc.state) {
case 0:
if (declarationsPreRE.exec(line)) {
acc.state = 1; // Start to read
}
break;
case 1:
if (declarationsPostRE.exec(line)) {
acc.state = 2; // Finish to read
} else {
acc.lines.push(line);
}
break;
case 2:
default:
// do nothing;
}
return acc;
}, {state: 0, lines: []})
.lines
.filter(function (line) {
return declarationRE.exec(line);
})
.reduce(function (obj, line) {
obj[line] = line;
return obj;
}, {});
};

Podfile.prototype.__parseForSources = function (text) {
// split by \n
var arr = text.split('\n');

var sourceRE = new RegExp('source \'(.*)\'');
return arr.filter(function (line) {
var m = sourceRE.exec(line);

return (m !== null);
})
.reduce(function (obj, line) {
var m = sourceRE.exec(line);
if (m !== null) {
var source = m[1];
obj[source] = source;
}
return obj;
}, {});
};

Podfile.prototype.__parseForPods = function (text) {
// split by \n
var arr = text.split('\n');
Expand All @@ -68,7 +138,8 @@ Podfile.prototype.__parseForPods = function (text) {
// pod 'Foobar', '1.2'
// pod 'Foobar', 'abc 123 1.2'
// pod 'PonyDebugger', :configurations => ['Debug', 'Beta']
var podRE = new RegExp('pod \'([^\']*)\'\\s*,?\\s*(.*)');
// var podRE = new RegExp('pod \'([^\']*)\'\\s*,?\\s*(.*)');
var podRE = new RegExp('pod \'([^\']*)\'\\s*(?:,\\s*\'([^\']*)\'\\s*)?,?\\s*(.*)');

// only grab lines that don't have the pod spec'
return arr.filter(function (line) {
Expand All @@ -80,9 +151,16 @@ Podfile.prototype.__parseForPods = function (text) {
var m = podRE.exec(line);

if (m !== null) {
// strip out any single quotes around the value m[2]
var podSpec = m[2].replace(/^\'|\'$/g, ''); /* eslint no-useless-escape : 0 */
obj[m[1]] = podSpec; // i.e pod 'Foo', '1.2' ==> { 'Foo' : '1.2'}
var podspec = {
name: m[1]
};
if (m[2]) {
podspec.spec = m[2];
}
if (m[3]) {
podspec.options = m[3];
}
obj[m[1]] = podspec; // i.e pod 'Foo', '1.2' ==> { 'Foo' : '1.2'}
}

return obj;
Expand All @@ -98,12 +176,14 @@ Podfile.prototype.getTemplate = function () {
var projectName = this.escapeSingleQuotes(this.projectName);
return util.format(
'# DO NOT MODIFY -- auto-generated by Apache Cordova\n' +
'%s\n' +
'platform :ios, \'%s\'\n' +
'%s\n' +
'target \'%s\' do\n' +
'\tproject \'%s.xcodeproj\'\n' +
'%s\n' +
'end\n',
this.minDeploymentTarget, projectName, projectName, this.podToken);
this.sourceToken, this.minDeploymentTarget, this.declarationToken, projectName, projectName, this.podToken);
};

Podfile.prototype.addSpec = function (name, spec) {
Expand All @@ -115,6 +195,14 @@ Podfile.prototype.addSpec = function (name, spec) {
throw new CordovaError('Podfile addSpec: name is not specified.');
}

if (typeof spec === 'string') {
if (spec.startsWith(':')) {
spec = {name: name, options: spec};
} else {
spec = {name: name, spec: spec};
}
}

this.pods[name] = spec;
this.__dirty = true;

Expand All @@ -138,7 +226,60 @@ Podfile.prototype.existsSpec = function (name) {
return (name in this.pods);
};

Podfile.prototype.addSource = function (src) {
this.sources[src] = src;
this.__dirty = true;

events.emit('verbose', util.format('Added source line for `%s`', src));
};

Podfile.prototype.removeSource = function (src) {
if (this.existsSource(src)) {
delete this.sources[src];
this.__dirty = true;
}

events.emit('verbose', util.format('Removed source line for `%s`', src));
};

Podfile.prototype.existsSource = function (src) {
return (src in this.sources);
};

Podfile.prototype.addDeclaration = function (declaration) {
this.declarations[declaration] = declaration;
this.__dirty = true;

events.emit('verbose', util.format('Added declaration line for `%s`', declaration));
};

Podfile.prototype.removeDeclaration = function (declaration) {
if (this.existsDeclaration(declaration)) {
delete this.declarations[declaration];
this.__dirty = true;
}

events.emit('verbose', util.format('Removed source line for `%s`', declaration));
};

Podfile.proofDeclaration = function (declaration) {
var list = Object.keys(Podfile.declarationRegexpMap).filter(function (key) {
var regexp = new RegExp(Podfile.declarationRegexpMap[key]);
return regexp.test(declaration);
});
if (list.length > 0) {
return list[0];
}
return declaration;
};

Podfile.prototype.existsDeclaration = function (declaration) {
return (declaration in this.declarations);
};

Podfile.prototype.clear = function () {
this.sources = {};
this.declarations = {};
this.pods = {};
this.__dirty = true;
};
Expand All @@ -155,22 +296,61 @@ Podfile.prototype.write = function () {
var podsString =
Object.keys(this.pods).map(function (key) {
var name = key;
var spec = self.pods[key];

if (spec.length) {
if (spec.indexOf(':') === 0) {
// don't quote it, it's a specification (starts with ':')
return util.format('\tpod \'%s\', %s', name, spec);
var json = self.pods[key];

if (typeof json === 'string') { // compatibility for using framework tag.
var spec = json;
if (spec.length) {
if (spec.indexOf(':') === 0) {
// don't quote it, it's a specification (starts with ':')
return util.format('\tpod \'%s\', %s', name, spec);
} else {
// quote it, it's a version
return util.format('\tpod \'%s\', \'%s\'', name, spec);
}
} else {
// quote it, it's a version
return util.format('\tpod \'%s\', \'%s\'', name, spec);
return util.format('\tpod \'%s\'', name);
}
} else {
return util.format('\tpod \'%s\'', name);
var list = ['\'' + name + '\''];
if ('spec' in json) {
list.push('\'' + json.spec + '\'');
}

var options = ['tag', 'branch', 'commit', 'git', 'podspec'].filter(function (tag) {
return tag in json;
}).map(function (tag) {
return ':' + tag + ' => \'' + json[tag] + '\'';
});
if ('configurations' in json) {
options.push(':configurations => [' + json['configurations'].split(',').map(function (conf) { return '\'' + conf.trim() + '\''; }).join(',') + ']');
}
if ('options' in json) {
options = [json.options];
}
if (options.length > 0) {
list.push(options.join(', '));
}
return util.format('\tpod %s', list.join(', '));
}
}).join('\n');

text = text.replace(this.podToken, podsString);
var sourcesString =
Object.keys(this.sources).map(function (key) {
var source = self.sources[key];
return util.format('source \'%s\'', source);
}).join('\n');

var declarationString =
Object.keys(this.declarations).map(function (key) {
var declaration = self.declarations[key];
return declaration;
}).join('\n');

text = text.replace(this.podToken, podsString)
.replace(this.sourceToken, sourcesString)
.replace(this.declarationToken, declarationString);

fs.writeFileSync(this.path, text, 'utf8');
this.__dirty = false;

Expand Down
Loading

0 comments on commit ece3b87

Please sign in to comment.