Skip to content

Commit 2b93ce2

Browse files
committed
refactor(cordova): use elementtree for cleaner config.xml edits
This refactor should make `config.xml` manipulation much cleaner. Although it may not solve all issues (XML editing in Node is not solid or pleasant at all), it's a huge step forward. Now we use the same library as Cordova, with the same whitespace configuration. fixes ionic-team#645 (somewhat) fixes ionic-team#2332 fixes ionic-team#2193 fixes ionic-team#2230
1 parent 8eafd90 commit 2b93ce2

28 files changed

Lines changed: 482 additions & 592 deletions

packages/cli-plugin-cordova/package.json

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"lint": "tslint --config ../../tslint.js --project tsconfig.json --type-check",
1212
"build": "npm run clean && npm run build-ts && npm run build-js",
1313
"build-ts": "tsc",
14-
"build-js": "npm run script-prepublish && cp ./resources.json ./dist/resources.json",
14+
"build-js": "npm run script-prepublish",
1515
"watch": "concurrently -p \"{name} \" -n \"TS,JS\" -c \"cyan.bold,yellow.dim\" \"npm run watch-ts\" \"npm run watch-js\"",
1616
"watch-ts": "tsc -w",
1717
"watch-js": "cross-env-shell IONIC_PREPUBLISH_PLUGIN_VERSION=${npm_package_version}-local \"npm run watch-js-chokidar\"",
@@ -44,8 +44,7 @@
4444
"files": [
4545
"bin/",
4646
"default-resources",
47-
"dist/",
48-
"resources.json"
47+
"dist/"
4948
],
5049
"license": "MIT",
5150
"jest": {
@@ -61,12 +60,11 @@
6160
"dependencies": {
6261
"@ionic/cli-utils": "1.6.0",
6362
"chalk": "^2.0.0",
64-
"tslib": "^1.7.1",
65-
"xml2js": "^0.4.17"
63+
"elementtree": "^0.1.7",
64+
"tslib": "^1.7.1"
6665
},
6766
"devDependencies": {
6867
"@ionic/cli-scripts": "0.3.0",
69-
"@types/chalk": "^0.4.31",
70-
"@types/xml2js": "0.0.33"
68+
"@types/chalk": "^0.4.31"
7169
}
7270
}

packages/cli-plugin-cordova/resources.json

Lines changed: 0 additions & 97 deletions
This file was deleted.

packages/cli-plugin-cordova/src/commands/base.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
} from '@ionic/cli-utils';
1616

1717
import { CORDOVA_INTENT, filterArgumentsForCordova, generateBuildOptions } from '../lib/utils/cordova';
18-
import { resetConfigXmlContentSrc, writeConfigXmlContentSrc } from '../lib/utils/configXmlUtils';
18+
import { ConfigXml } from '../lib/utils/configXml';
1919
import { getProjectPlatforms, installPlatform } from '../lib/utils/setup';
2020

2121
export const CORDOVA_RUN_COMMAND_OPTIONS = [
@@ -200,31 +200,34 @@ export class CordovaRunCommand extends CordovaCommand implements CommandPreRun {
200200
async run(inputs: CommandLineInputs, options: CommandLineOptions): Promise<void> {
201201
const isLiveReload = options['livereload'];
202202

203-
// If it is not livereload then just run build.
204-
if (!isLiveReload) {
205-
await this.env.hooks.fire('build:before', { env: this.env });
203+
const conf = await ConfigXml.load(this.env.project.directory);
206204

207-
// ensure the content node was set back to its original
208-
await resetConfigXmlContentSrc(this.env.project.directory);
209-
await this.env.hooks.fire('command:build', {
205+
if (isLiveReload) {
206+
await this.env.hooks.fire('watch:before', { env: this.env });
207+
208+
const [ serverSettings ] = await this.env.hooks.fire('command:serve', {
210209
cmd: this,
211210
env: this.env,
212211
inputs,
213212
options: generateBuildOptions(this.metadata, options),
214213
});
215214

216-
await this.env.hooks.fire('build:after', { env: this.env });
215+
await conf.writeContentSrc(`${serverSettings.protocol || 'http'}://${serverSettings.externalAddress || serverSettings.publicIp}:${serverSettings.port || serverSettings.httpPort}`);
216+
await conf.save();
217217
} else {
218-
await this.env.hooks.fire('watch:before', { env: this.env });
218+
await this.env.hooks.fire('build:before', { env: this.env });
219219

220-
const [ serverSettings ] = await this.env.hooks.fire('command:serve', {
220+
await conf.resetContentSrc();
221+
await conf.save();
222+
223+
await this.env.hooks.fire('command:build', {
221224
cmd: this,
222225
env: this.env,
223226
inputs,
224227
options: generateBuildOptions(this.metadata, options),
225228
});
226229

227-
await writeConfigXmlContentSrc(this.env.project.directory, `${serverSettings.protocol || 'http'}://${serverSettings.externalAddress || serverSettings.publicIp}:${serverSettings.port || serverSettings.httpPort}`);
230+
await this.env.hooks.fire('build:after', { env: this.env });
228231
}
229232

230233
await this.runCordova(filterArgumentsForCordova(this.metadata, inputs, options), { showExecution: true });

packages/cli-plugin-cordova/src/commands/build.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
} from '@ionic/cli-utils';
99

1010
import { CORDOVA_INTENT, filterArgumentsForCordova, generateBuildOptions } from '../lib/utils/cordova';
11-
import { resetConfigXmlContentSrc } from '../lib/utils/configXmlUtils';
11+
import { ConfigXml } from '../lib/utils/configXml';
1212
import { CordovaCommand } from './base';
1313

1414
@CommandMetadata({
@@ -118,8 +118,9 @@ export class BuildCommand extends CordovaCommand implements CommandPreRun {
118118
async run(inputs: CommandLineInputs, options: CommandLineOptions): Promise<void> {
119119
const { build } = options;
120120

121-
// ensure the content node was set back to its original src
122-
await resetConfigXmlContentSrc(this.env.project.directory);
121+
const conf = await ConfigXml.load(this.env.project.directory);
122+
await conf.resetContentSrc();
123+
await conf.save();
123124

124125
if (build) {
125126
await this.env.hooks.fire('build:before', { env: this.env });

packages/cli-plugin-cordova/src/commands/compile.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from '@ionic/cli-utils';
88

99
import { filterArgumentsForCordova } from '../lib/utils/cordova';
10-
import { resetConfigXmlContentSrc } from '../lib/utils/configXmlUtils';
10+
import { ConfigXml } from '../lib/utils/configXml';
1111
import { CordovaCommand } from './base';
1212

1313
@CommandMetadata({
@@ -43,8 +43,10 @@ export class CompileCommand extends CordovaCommand implements CommandPreRun {
4343
}
4444

4545
async run(inputs: CommandLineInputs, options: CommandLineOptions): Promise<void> {
46-
// ensure the content node was set back to its original
47-
await resetConfigXmlContentSrc(this.env.project.directory);
46+
const conf = await ConfigXml.load(this.env.project.directory);
47+
await conf.resetContentSrc();
48+
await conf.save();
49+
4850
const response = await this.runCordova(filterArgumentsForCordova(this.metadata, inputs, options));
4951
this.env.log.msg(response);
5052
}

packages/cli-plugin-cordova/src/commands/platform.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import {
1212

1313
import { KnownPlatform } from '../definitions';
1414
import { filterArgumentsForCordova } from '../lib/utils/cordova';
15-
import { resetConfigXmlContentSrc } from '../lib/utils/configXmlUtils';
16-
import { addDefaultImagesToProjectResources } from '../lib/resources';
15+
import { ConfigXml } from '../lib/utils/configXml';
16+
import { RESOURCES, addDefaultImagesToProjectResources } from '../lib/resources';
1717
import { getProjectPlatforms } from '../lib/utils/setup';
1818
import { CordovaCommand } from './base';
1919

@@ -78,8 +78,9 @@ export class PlatformCommand extends CordovaCommand implements CommandPreRun {
7878
async run(inputs: CommandLineInputs, options: CommandLineOptions): Promise<void> {
7979
let [ action, platformName ] = inputs;
8080

81-
// ensure the content node was set back to its original src
82-
await resetConfigXmlContentSrc(this.env.project.directory);
81+
const conf = await ConfigXml.load(this.env.project.directory);
82+
await conf.resetContentSrc();
83+
await conf.save();
8384

8485
const platforms = await getProjectPlatforms(this.env.project.directory);
8586

@@ -100,6 +101,9 @@ export class PlatformCommand extends CordovaCommand implements CommandPreRun {
100101
if (action === 'add' && !(options['noresources']) && ['ios', 'android', 'wp8'].includes(platformName)) {
101102
this.env.tasks.next(`Copying default image resources into ${chalk.bold('./resources/' + platformName)}`);
102103
await addDefaultImagesToProjectResources(this.env.project.directory, <KnownPlatform>platformName);
104+
const conf = await ConfigXml.load(this.env.project.directory);
105+
await conf.ensurePlatformImages(platformName, RESOURCES[platformName]);
106+
await conf.save();
103107
}
104108

105109
this.env.tasks.end();

packages/cli-plugin-cordova/src/commands/plugin.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from '@ionic/cli-utils';
1212

1313
import { CORDOVA_INTENT, filterArgumentsForCordova } from '../lib/utils/cordova';
14-
import { resetConfigXmlContentSrc } from '../lib/utils/configXmlUtils';
14+
import { ConfigXml } from '../lib/utils/configXml';
1515
import { CordovaCommand } from './base';
1616

1717
@CommandMetadata({
@@ -77,8 +77,9 @@ export class PluginCommand extends CordovaCommand implements CommandPreRun {
7777
}
7878

7979
async run(inputs: CommandLineInputs, options: CommandLineOptions): Promise<void> {
80-
// ensure the content node was set back to its original
81-
await resetConfigXmlContentSrc(this.env.project.directory);
80+
const conf = await ConfigXml.load(this.env.project.directory);
81+
await conf.resetContentSrc();
82+
await conf.save();
8283

8384
const optionList = filterArgumentsForCordova(this.metadata, inputs.splice(0, 2), options);
8485

packages/cli-plugin-cordova/src/commands/prepare.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99

1010
import { filterArgumentsForCordova } from '../lib/utils/cordova';
1111
import { installPlatform } from '../lib/utils/setup';
12-
import { getPlatformEngine, parseConfigXmlToJson, resetConfigXmlContentSrc } from '../lib/utils/configXmlUtils';
12+
import { ConfigXml } from '../lib/utils/configXml';
1313
import { CordovaCommand } from './base';
1414

1515
@CommandMetadata({
@@ -43,8 +43,8 @@ export class PrepareCommand extends CordovaCommand implements CommandPreRun {
4343
const [ platform ] = inputs;
4444

4545
if (platform) {
46-
const configJson = await parseConfigXmlToJson(this.env.project.directory);
47-
const platformEngine = getPlatformEngine(configJson, platform);
46+
const conf = await ConfigXml.load(this.env.project.directory);
47+
const platformEngine = conf.getPlatformEngine(platform);
4848

4949
if (!platformEngine) {
5050
const confirm = await this.env.prompt({
@@ -61,8 +61,9 @@ export class PrepareCommand extends CordovaCommand implements CommandPreRun {
6161
}
6262
}
6363

64-
// ensure the content node was set back to its original src
65-
await resetConfigXmlContentSrc(this.env.project.directory);
64+
const conf = await ConfigXml.load(this.env.project.directory);
65+
await conf.resetContentSrc();
66+
await conf.save();
6667

6768
const response = await this.runCordova(filterArgumentsForCordova(this.metadata, inputs, options), {});
6869
this.env.log.msg(response);

0 commit comments

Comments
 (0)