You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by be...@apache.org on 2013/08/21 03:12:59 UTC
git commit: [CB-4618] fix for xml parsing on windows,
use xml-helpers from now on to parse xml
Updated Branches:
refs/heads/master 4b77decee -> 0f56fbcda
[CB-4618] fix for xml parsing on windows, use xml-helpers from now on to parse xml
Project: http://git-wip-us.apache.org/repos/asf/cordova-cli/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-cli/commit/0f56fbcd
Tree: http://git-wip-us.apache.org/repos/asf/cordova-cli/tree/0f56fbcd
Diff: http://git-wip-us.apache.org/repos/asf/cordova-cli/diff/0f56fbcd
Branch: refs/heads/master
Commit: 0f56fbcdaacc7c851ee4fd26ca63bea15b10daea
Parents: 4b77dec
Author: Benn Mapes <be...@gmail.com>
Authored: Tue Aug 20 14:39:33 2013 -0700
Committer: Benn Mapes <be...@gmail.com>
Committed: Tue Aug 20 16:01:35 2013 -0700
----------------------------------------------------------------------
spec/fixtures/plugins/ChildBrowser/plugin.xml | 142 ++++++++++++++++
.../ChildBrowser/src/android/ChildBrowser.java | 19 +++
.../plugins/ChildBrowser/www/childbrowser.js | 19 +++
.../ChildBrowser/www/childbrowser/image.jpg | 1 +
.../ChildBrowser/www/childbrowser_file.html | 1 +
.../projects/android/AndroidManifest.xml | 69 ++++++++
.../projects/android/assets/www/.gitkeep | 0
.../projects/android/res/xml/config.xml | 54 ++++++
spec/fixtures/projects/android/src/.gitkeep | 0
spec/fixtures/projects/windows/bom_test.xml | 24 +++
spec/xml-helpers.spec.js | 136 +++++++++++++++
src/cli.js | 19 +++
src/config_parser.js | 3 +-
src/metadata/android_parser.js | 5 +-
src/metadata/wp7_parser.js | 22 +--
src/metadata/wp8_parser.js | 22 +--
src/plugin_parser.js | 6 +-
src/xml-helpers.js | 167 +++++++++++++++++++
18 files changed, 671 insertions(+), 38 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/spec/fixtures/plugins/ChildBrowser/plugin.xml
----------------------------------------------------------------------
diff --git a/spec/fixtures/plugins/ChildBrowser/plugin.xml b/spec/fixtures/plugins/ChildBrowser/plugin.xml
new file mode 100644
index 0000000..512c02f
--- /dev/null
+++ b/spec/fixtures/plugins/ChildBrowser/plugin.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ Licensed 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.
+
+-->
+
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ id="com.phonegap.plugins.childbrowser"
+ version="0.6.0">
+
+ <name>Child Browser</name>
+
+ <asset src="www/childbrowser" target="childbrowser" />
+ <asset src="www/childbrowser_file.html" target="childbrowser_file.html" />
+
+ <js-module src="www/childbrowser.js" name="ChildBrowser">
+ <clobbers target="childbrowser" />
+ </js-module>
+
+ <config-file target="config.xml" parent="/*">
+ <access origin="build.phonegap.com" />
+ <access origin="s3.amazonaws.com" />
+ </config-file>
+
+ <info>No matter what platform you are installing to, this notice is very important.</info>
+
+ <!-- android -->
+ <platform name="android">
+ <config-file target="AndroidManifest.xml" parent="/manifest/application">
+ <activity android:name="com.phonegap.plugins.childBrowser.ChildBrowser"
+ android:label="@string/app_name">
+ <intent-filter>
+ </intent-filter>
+ </activity>
+ </config-file>
+
+ <!-- CDV < 2.0 -->
+ <config-file target="res/xml/plugins.xml" parent="/plugins">
+ <plugin name="ChildBrowser"
+ value="com.phonegap.plugins.childBrowser.ChildBrowser"/>
+ </config-file>
+
+ <!-- CDV 2.0+ (for now) -->
+ <config-file target="res/xml/config.xml" parent="/cordova/plugins">
+ <plugin name="ChildBrowser"
+ value="com.phonegap.plugins.childBrowser.ChildBrowser"/>
+ </config-file>
+
+ <source-file src="src/android/ChildBrowser.java"
+ target-dir="src/com/phonegap/plugins/childBrowser" />
+ <info>Please make sure you read this because it is very important to complete the installation of your plugin.</info>
+ </platform>
+
+ <!-- ios -->
+ <platform name="ios">
+ <plugins-plist key="com.phonegap.plugins.childbrowser"
+ string="ChildBrowserCommand" />
+
+ <config-file target="config.xml" parent="/widget/plugins">
+ <plugin name="ChildBrowser"
+ value="ChildBrowserCommand" />
+ </config-file>
+
+ <resource-file src="src/ios/ChildBrowser.bundle" />
+ <resource-file src="src/ios/ChildBrowserViewController.xib" />
+
+ <config-file target="*-Info.plist" parent="AppId">
+ <string>$APP_ID</string>
+ </config-file>
+
+ <config-file target="*-Info.plist" parent="CFBundleURLTypes">
+ <array>
+ <dict>
+ <key>PackageName</key>
+ <string>$PACKAGE_NAME</string>
+ </dict>
+ </array>
+ </config-file>
+
+ <header-file src="src/ios/ChildBrowserCommand.h" />
+ <header-file src="src/ios/ChildBrowserViewController.h" />
+ <header-file src="src/ios/TargetDirTest.h" target-dir="targetDir"/>
+
+ <source-file src="src/ios/ChildBrowserCommand.m" />
+ <source-file src="src/ios/ChildBrowserViewController.m" />
+ <source-file src="src/ios/preserveDirs/PreserveDirsTest.m" preserve-dirs="true" />
+ <header-file src="src/ios/TargetDirTest.m" target-dir="targetDir"/>
+
+ <!-- framework for testing (not actual dependency of ChildBrowser -->
+ <framework src="libsqlite3.dylib" />
+ <framework src="social.framework" weak="true" />
+ <framework src="music.framework" weak="rabbit" />
+ </platform>
+ <!-- wp7 -->
+ <platform name="wp7">
+ <resource-file src="src\wp7\Images\appbar.back.rest.png" />
+ <config-file target="config.xml" parent="/widget/plugins">
+ <plugin name="ChildBrowser"
+ value="ChildBrowser"/>
+ </config-file>
+
+ <source-file src="src\wp7\ChildBrowserCommand.cs"
+ target-dir="Plugins\" />
+
+ <!-- modify the project file to include the added files -->
+ <config-file target=".csproj" parent=".">
+ </config-file>
+
+ </platform>
+
+ <!-- wp8 -->
+ <platform name="wp8">
+ <resource-file src="src\wp7\Images\appbar.back.rest.png" />
+ <config-file target="config.xml" parent="/widget/plugins">
+ <plugin name="ChildBrowser"
+ value="ChildBrowser"/>
+ </config-file>
+
+ <source-file src="src\wp7\ChildBrowserCommand.cs"
+ target-dir="Plugins\" />
+
+ <!-- modify the project file to include the added files -->
+ <config-file target=".csproj" parent=".">
+ </config-file>
+
+ </platform>
+</plugin>
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/spec/fixtures/plugins/ChildBrowser/src/android/ChildBrowser.java
----------------------------------------------------------------------
diff --git a/spec/fixtures/plugins/ChildBrowser/src/android/ChildBrowser.java b/spec/fixtures/plugins/ChildBrowser/src/android/ChildBrowser.java
new file mode 100644
index 0000000..5263b0c
--- /dev/null
+++ b/spec/fixtures/plugins/ChildBrowser/src/android/ChildBrowser.java
@@ -0,0 +1,19 @@
+/*
+ *
+ * Copyright 2013 Anis Kadri
+ *
+ * Licensed 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.
+ *
+*/
+
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/spec/fixtures/plugins/ChildBrowser/www/childbrowser.js
----------------------------------------------------------------------
diff --git a/spec/fixtures/plugins/ChildBrowser/www/childbrowser.js b/spec/fixtures/plugins/ChildBrowser/www/childbrowser.js
new file mode 100644
index 0000000..5263b0c
--- /dev/null
+++ b/spec/fixtures/plugins/ChildBrowser/www/childbrowser.js
@@ -0,0 +1,19 @@
+/*
+ *
+ * Copyright 2013 Anis Kadri
+ *
+ * Licensed 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.
+ *
+*/
+
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/spec/fixtures/plugins/ChildBrowser/www/childbrowser/image.jpg
----------------------------------------------------------------------
diff --git a/spec/fixtures/plugins/ChildBrowser/www/childbrowser/image.jpg b/spec/fixtures/plugins/ChildBrowser/www/childbrowser/image.jpg
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/spec/fixtures/plugins/ChildBrowser/www/childbrowser/image.jpg
@@ -0,0 +1 @@
+foo
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/spec/fixtures/plugins/ChildBrowser/www/childbrowser_file.html
----------------------------------------------------------------------
diff --git a/spec/fixtures/plugins/ChildBrowser/www/childbrowser_file.html b/spec/fixtures/plugins/ChildBrowser/www/childbrowser_file.html
new file mode 100644
index 0000000..6de7b8c
--- /dev/null
+++ b/spec/fixtures/plugins/ChildBrowser/www/childbrowser_file.html
@@ -0,0 +1 @@
+This is a test file.
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/spec/fixtures/projects/android/AndroidManifest.xml
----------------------------------------------------------------------
diff --git a/spec/fixtures/projects/android/AndroidManifest.xml b/spec/fixtures/projects/android/AndroidManifest.xml
new file mode 100644
index 0000000..0c52803
--- /dev/null
+++ b/spec/fixtures/projects/android/AndroidManifest.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright 2013 Anis Kadri
+
+ Licensed 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.
+
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
+ package="com.alunny.childapp" android:versionName="1.1" android:versionCode="5">
+ <supports-screens
+ android:largeScreens="true"
+ android:normalScreens="true"
+ android:smallScreens="true"
+ android:xlargeScreens="true"
+ android:resizeable="true"
+ android:anyDensity="true"
+ />
+
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.VIBRATE" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+ <uses-permission android:name="android.permission.RECORD_VIDEO"/>
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+ <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+
+ <uses-feature android:name="android.hardware.camera" />
+ <uses-feature android:name="android.hardware.camera.autofocus" />
+
+ <application android:icon="@drawable/icon" android:label="@string/app_name"
+ android:debuggable="true">
+ <activity android:name="ChildApp" android:label="@string/app_name"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name="com.phonegap.DroidGap" android:label="@string/app_name"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ </intent-filter>
+ </activity>
+ </application>
+
+ <uses-sdk android:minSdkVersion="5" />
+</manifest>
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/spec/fixtures/projects/android/assets/www/.gitkeep
----------------------------------------------------------------------
diff --git a/spec/fixtures/projects/android/assets/www/.gitkeep b/spec/fixtures/projects/android/assets/www/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/spec/fixtures/projects/android/res/xml/config.xml
----------------------------------------------------------------------
diff --git a/spec/fixtures/projects/android/res/xml/config.xml b/spec/fixtures/projects/android/res/xml/config.xml
new file mode 100644
index 0000000..d37aba5
--- /dev/null
+++ b/spec/fixtures/projects/android/res/xml/config.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<cordova>
+ <!--
+ access elements control the Android whitelist.
+ Domains are assumed blocked unless set otherwise
+ -->
+
+ <access origin="http://127.0.0.1*"/> <!-- allow local pages -->
+
+ <!-- <access origin="https://example.com" /> allow any secure requests to example.com -->
+ <!-- <access origin="https://example.com" subdomains="true" /> such as above, but including subdomains, such as www -->
+ <!-- <access origin=".*"/> Allow all domains, suggested development use only -->
+
+ <log level="DEBUG"/>
+ <preference name="useBrowserHistory" value="false" />
+<plugins>
+ <plugin name="App" value="org.apache.cordova.App"/>
+ <plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
+ <plugin name="Device" value="org.apache.cordova.Device"/>
+ <plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
+ <plugin name="Compass" value="org.apache.cordova.CompassListener"/>
+ <plugin name="Media" value="org.apache.cordova.AudioHandler"/>
+ <plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
+ <plugin name="Contacts" value="org.apache.cordova.ContactManager"/>
+ <plugin name="File" value="org.apache.cordova.FileUtils"/>
+ <plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
+ <plugin name="Notification" value="org.apache.cordova.Notification"/>
+ <plugin name="Storage" value="org.apache.cordova.Storage"/>
+ <plugin name="Temperature" value="org.apache.cordova.TempListener"/>
+ <plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
+ <plugin name="Capture" value="org.apache.cordova.Capture"/>
+ <plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
+ <plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
+</plugins>
+</cordova>
+
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/spec/fixtures/projects/android/src/.gitkeep
----------------------------------------------------------------------
diff --git a/spec/fixtures/projects/android/src/.gitkeep b/spec/fixtures/projects/android/src/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/spec/fixtures/projects/windows/bom_test.xml
----------------------------------------------------------------------
diff --git a/spec/fixtures/projects/windows/bom_test.xml b/spec/fixtures/projects/windows/bom_test.xml
new file mode 100644
index 0000000..57cadf6
--- /dev/null
+++ b/spec/fixtures/projects/windows/bom_test.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+-->
+<widget>
+ <access origin="*"/>
+</widget>
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/spec/xml-helpers.spec.js
----------------------------------------------------------------------
diff --git a/spec/xml-helpers.spec.js b/spec/xml-helpers.spec.js
new file mode 100644
index 0000000..140347a
--- /dev/null
+++ b/spec/xml-helpers.spec.js
@@ -0,0 +1,136 @@
+/*
+ *
+ *
+ * Licensed 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.
+ *
+*/
+
+var path = require('path')
+ , xml_helpers = require('../src/xml-helpers')
+ , et = require('elementtree')
+
+ , title = et.XML('<title>HELLO</title>')
+ , usesNetworkOne = et.XML('<uses-permission ' +
+ 'android:name="PACKAGE_NAME.permission.C2D_MESSAGE"/>')
+ , usesNetworkTwo = et.XML("<uses-permission android:name=\
+ \"PACKAGE_NAME.permission.C2D_MESSAGE\" />")
+ , usesReceive = et.XML("<uses-permission android:name=\
+ \"com.google.android.c2dm.permission.RECEIVE\"/>")
+ , helloTagOne = et.XML("<h1>HELLO</h1>")
+ , goodbyeTag = et.XML("<h1>GOODBYE</h1>")
+ , helloTagTwo = et.XML("<h1> HELLO </h1>");
+
+
+describe('xml-helpers', function(){
+ describe('parseElementtreeSync', function() {
+ it('should parse xml with a byte order mark', function() {
+ var xml_path = path.join(__dirname, 'fixtures', 'projects', 'windows', 'bom_test.xml');
+ expect(function() {
+ xml_helpers.parseElementtreeSync(xml_path);
+ }).not.toThrow();
+ })
+ });
+ describe('equalNodes', function() {
+ it('should return false for different tags', function(){
+ expect(xml_helpers.equalNodes(usesNetworkOne, title)).toBe(false);
+ });
+
+ it('should return true for identical tags', function(){
+ expect(xml_helpers.equalNodes(usesNetworkOne, usesNetworkTwo)).toBe(true);
+ });
+
+ it('should return false for different attributes', function(){
+ expect(xml_helpers.equalNodes(usesNetworkOne, usesReceive)).toBe(false);
+ });
+
+ it('should distinguish between text', function(){
+ expect(xml_helpers.equalNodes(helloTagOne, goodbyeTag)).toBe(false);
+ });
+
+ it('should ignore whitespace in text', function(){
+ expect(xml_helpers.equalNodes(helloTagOne, helloTagTwo)).toBe(true);
+ });
+
+ describe('should compare children', function(){
+ it('by child quantity', function(){
+ var one = et.XML('<i><b>o</b></i>'),
+ two = et.XML('<i><b>o</b><u></u></i>');
+
+ expect(xml_helpers.equalNodes(one, two)).toBe(false);
+ });
+
+ it('by child equality', function(){
+ var one = et.XML('<i><b>o</b></i>'),
+ two = et.XML('<i><u></u></i>'),
+ uno = et.XML('<i>\n<b>o</b>\n</i>');
+
+ expect(xml_helpers.equalNodes(one, uno)).toBe(true);
+ expect(xml_helpers.equalNodes(one, two)).toBe(false);
+ });
+ });
+ });
+ describe('pruneXML', function() {
+ var config_xml;
+
+ beforeEach(function() {
+ config_xml = xml_helpers.parseElementtreeSync(path.join(__dirname, 'fixtures', 'projects', 'android', 'res', 'xml', 'config.xml'));
+ });
+
+ it('should remove any children that match the specified selector', function() {
+ var children = config_xml.findall('plugins/plugin');
+ xml_helpers.pruneXML(config_xml, children, 'plugins');
+ expect(config_xml.find('plugins').getchildren().length).toEqual(0);
+ });
+ it('should do nothing if the children cannot be found', function() {
+ var children = [title];
+ xml_helpers.pruneXML(config_xml, children, 'plugins');
+ expect(config_xml.find('plugins').getchildren().length).toEqual(17);
+ });
+ it('should be able to handle absolute selectors', function() {
+ var children = config_xml.findall('plugins/plugin');
+ xml_helpers.pruneXML(config_xml, children, '/cordova/plugins');
+ expect(config_xml.find('plugins').getchildren().length).toEqual(0);
+ });
+ it('should be able to handle absolute selectors with wildcards', function() {
+ var children = config_xml.findall('plugins/plugin');
+ xml_helpers.pruneXML(config_xml, children, '/*/plugins');
+ expect(config_xml.find('plugins').getchildren().length).toEqual(0);
+ });
+ });
+
+ describe('graftXML', function() {
+ var config_xml, plugin_xml;
+
+ beforeEach(function() {
+ config_xml = xml_helpers.parseElementtreeSync(path.join(__dirname, 'fixtures', 'projects', 'android', 'res', 'xml', 'config.xml'));
+ plugin_xml = xml_helpers.parseElementtreeSync(path.join(__dirname, 'fixtures', 'plugins', 'ChildBrowser', 'plugin.xml'));
+ });
+
+ it('should add children to the specified selector', function() {
+ var children = plugin_xml.find('config-file').getchildren();
+ xml_helpers.graftXML(config_xml, children, 'plugins');
+ expect(config_xml.find('plugins').getchildren().length).toEqual(19);
+ });
+ it('should be able to handle absolute selectors', function() {
+ var children = plugin_xml.find('config-file').getchildren();
+ xml_helpers.graftXML(config_xml, children, '/cordova');
+ expect(config_xml.findall('access').length).toEqual(3);
+ });
+ it('should be able to handle absolute selectors with wildcards', function() {
+ var children = plugin_xml.find('config-file').getchildren();
+ xml_helpers.graftXML(config_xml, children, '/*');
+ expect(config_xml.findall('access').length).toEqual(3);
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/src/cli.js
----------------------------------------------------------------------
diff --git a/src/cli.js b/src/cli.js
index 296ccda..24c9d7d 100755
--- a/src/cli.js
+++ b/src/cli.js
@@ -1,3 +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.
+*/
+
var optimist = require('optimist'),
cordova = require('../cordova'),
plugman = require('plugman'),
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/src/config_parser.js
----------------------------------------------------------------------
diff --git a/src/config_parser.js b/src/config_parser.js
index 5c5e0dc..6e40054 100644
--- a/src/config_parser.js
+++ b/src/config_parser.js
@@ -17,11 +17,12 @@
under the License.
*/
var et = require('elementtree'),
+ xml= require('./xml-helpers'),
fs = require('fs');
function config_parser(path) {
this.path = path;
- this.doc = new et.ElementTree(et.XML(fs.readFileSync(path, 'utf-8')));
+ this.doc = xml.parseElementtreeSync(path);
this.access = new access(this);
this.preference = new preference(this);
}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/src/metadata/android_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/android_parser.js b/src/metadata/android_parser.js
index 722bd45..6da778a 100644
--- a/src/metadata/android_parser.js
+++ b/src/metadata/android_parser.js
@@ -19,6 +19,7 @@
var fs = require('fs'),
path = require('path'),
et = require('elementtree'),
+ xml = require('../xml-helpers'),
util = require('../util'),
events = require('../events'),
shell = require('shelljs'),
@@ -81,12 +82,12 @@ module.exports.prototype = {
// Update app name by editing res/values/strings.xml
var name = config.name();
- var strings = new et.ElementTree(et.XML(fs.readFileSync(this.strings, 'utf-8')));
+ var strings = xml.parseElementtreeSync(this.strings);
strings.find('string[@name="app_name"]').text = name;
fs.writeFileSync(this.strings, strings.write({indent: 4}), 'utf-8');
events.emit('log', 'Wrote out Android application name to "' + name + '"');
- var manifest = new et.ElementTree(et.XML(fs.readFileSync(this.manifest, 'utf-8')));
+ var manifest = xml.parseElementtreeSync(this.manifest);
// Update the version by changing the AndroidManifest android:versionName
var version = config.version();
manifest.getroot().attrib["android:versionName"] = version;
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/src/metadata/wp7_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/wp7_parser.js b/src/metadata/wp7_parser.js
index 6c81668..bde8770 100644
--- a/src/metadata/wp7_parser.js
+++ b/src/metadata/wp7_parser.js
@@ -19,6 +19,7 @@
var fs = require('fs'),
path = require('path'),
et = require('elementtree'),
+ xml = require('../xml-helpers'),
util = require('../util'),
events = require('../events'),
shell = require('shelljs'),
@@ -66,9 +67,7 @@ module.exports.prototype = {
} else throw new Error('update_from_config requires a config_parser object');
//Get manifest file
- var man = fs.readFileSync(this.manifest_path, 'utf-8');
- var cleanedMan = man.replace('\ufeff', ''); //Windows is the BOM
- var manifest = new et.ElementTree(et.XML(cleanedMan));
+ var manifest = xml.parseElementtreeSync(this.manifest_path);
//Update app version
var version = config.version();
@@ -105,9 +104,7 @@ module.exports.prototype = {
* - App.xaml.cs
*/
var pkg = config.packageName();
- var raw = fs.readFileSync(this.csproj_path, 'utf-8');
- var cleanedPage = raw.replace(/^\uFEFF/i, '');
- var csproj = new et.ElementTree(et.XML(cleanedPage));
+ var csproj = xml.parseElementtreeSync(this.csproj_path);
prev_name = csproj.find('.//RootNamespace').text;
if(prev_name != pkg) {
events.emit('log', "Updating package name from " + prev_name + " to " + pkg);
@@ -118,10 +115,7 @@ module.exports.prototype = {
csproj.find('.//SilverlightAppEntry').text = pkg + '.App';
fs.writeFileSync(this.csproj_path, csproj.write({indent: 4}), 'utf-8');
//MainPage.xaml
- raw = fs.readFileSync(path.join(this.wp7_proj_dir, 'MainPage.xaml'), 'utf-8');
- // Remove potential UTF Byte Order Mark
- cleanedPage = raw.replace(/^\uFEFF/i, '');
- var mainPageXAML = new et.ElementTree(et.XML(cleanedPage));
+ var mainPageXAML = xml.parseElementtreeSync(path.join(this.wp7_proj_dir, 'MainPage.xaml'));
mainPageXAML.getroot().attrib['x:Class'] = pkg + '.MainPage';
fs.writeFileSync(path.join(this.wp7_proj_dir, 'MainPage.xaml'), mainPageXAML.write({indent: 4}), 'utf-8');
//MainPage.xaml.cs
@@ -129,9 +123,7 @@ module.exports.prototype = {
var namespaceRegEx = new RegExp('namespace ' + prev_name);
fs.writeFileSync(path.join(this.wp7_proj_dir, 'MainPage.xaml.cs'), mainPageCS.replace(namespaceRegEx, 'namespace ' + pkg), 'utf-8');
//App.xaml
- raw = fs.readFileSync(path.join(this.wp7_proj_dir, 'App.xaml'), 'utf-8');
- cleanedPage = raw.replace(/^\uFEFF/i, '');
- var appXAML = new et.ElementTree(et.XML(cleanedPage));
+ var appXAML = xml.parseElementtreeSync(path.join(this.wp7_proj_dir, 'App.xaml'));
appXAML.getroot().attrib['x:Class'] = pkg + '.App';
fs.writeFileSync(path.join(this.wp7_proj_dir, 'App.xaml'), appXAML.write({indent: 4}), 'utf-8');
//App.xaml.cs
@@ -168,9 +160,7 @@ module.exports.prototype = {
},
// updates the csproj file to explicitly list all www content.
update_csproj:function() {
- var raw = fs.readFileSync(this.csproj_path, 'utf-8');
- var cleaned = raw.replace(/^\uFEFF/i, '');
- var csproj_xml = new et.ElementTree(et.XML(cleaned));
+ var csproj_xml = xml.parseElementtreeSync(this.csproj_path);
// remove any previous references to the www files
var item_groups = csproj_xml.findall('ItemGroup');
for (var i = 0, l = item_groups.length; i < l; i++) {
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/src/metadata/wp8_parser.js
----------------------------------------------------------------------
diff --git a/src/metadata/wp8_parser.js b/src/metadata/wp8_parser.js
index 00797b7..4a4633f 100644
--- a/src/metadata/wp8_parser.js
+++ b/src/metadata/wp8_parser.js
@@ -24,6 +24,7 @@ var fs = require('fs'),
shell = require('shelljs'),
events = require('../events'),
config_parser = require('../config_parser'),
+ xml = require('../xml-helpers'),
config = require('../config');
module.exports = function wp8_parser(project) {
@@ -66,9 +67,7 @@ module.exports.prototype = {
} else throw new Error('update_from_config requires a config_parser object');
//Get manifest file
- var man = fs.readFileSync(this.manifest_path, 'utf-8');
- var cleanedMan = man.replace('\ufeff', ''); //Windows is the BOM
- var manifest = new et.ElementTree(et.XML(cleanedMan));
+ var manifest = xml.parseElementtreeSync(this.manifest_path);
//Update app version
var version = config.version();
@@ -106,9 +105,7 @@ module.exports.prototype = {
* - App.xaml.cs
*/
var pkg = config.packageName();
- var raw = fs.readFileSync(this.csproj_path, 'utf-8');
- var cleanedPage = raw.replace(/^\uFEFF/i, '');
- var csproj = new et.ElementTree(et.XML(cleanedPage));
+ var csproj = xml.parseElementtreeSync(this.csproj_path);
prev_name = csproj.find('.//RootNamespace').text;
if(prev_name != pkg) {
//console.log("Updating package name from " + prev_name + " to " + pkg);
@@ -119,10 +116,7 @@ module.exports.prototype = {
csproj.find('.//SilverlightAppEntry').text = pkg + '.App';
fs.writeFileSync(this.csproj_path, csproj.write({indent: 4}), 'utf-8');
//MainPage.xaml
- raw = fs.readFileSync(path.join(this.wp8_proj_dir, 'MainPage.xaml'), 'utf-8');
- // Remove potential UTF Byte Order Mark
- cleanedPage = raw.replace(/^\uFEFF/i, '');
- var mainPageXAML = new et.ElementTree(et.XML(cleanedPage));
+ var mainPageXAML = xml.parseElementtreeSync(path.join(this.wp8_proj_dir, 'MainPage.xaml'));
mainPageXAML.getroot().attrib['x:Class'] = pkg + '.MainPage';
fs.writeFileSync(path.join(this.wp8_proj_dir, 'MainPage.xaml'), mainPageXAML.write({indent: 4}), 'utf-8');
//MainPage.xaml.cs
@@ -130,9 +124,7 @@ module.exports.prototype = {
var namespaceRegEx = new RegExp('namespace ' + prev_name);
fs.writeFileSync(path.join(this.wp8_proj_dir, 'MainPage.xaml.cs'), mainPageCS.replace(namespaceRegEx, 'namespace ' + pkg), 'utf-8');
//App.xaml
- raw = fs.readFileSync(path.join(this.wp8_proj_dir, 'App.xaml'), 'utf-8');
- cleanedPage = raw.replace(/^\uFEFF/i, '');
- var appXAML = new et.ElementTree(et.XML(cleanedPage));
+ var appXAML = xml.parseElementtreeSync(path.join(this.wp8_proj_dir, 'App.xaml'));
appXAML.getroot().attrib['x:Class'] = pkg + '.App';
fs.writeFileSync(path.join(this.wp8_proj_dir, 'App.xaml'), appXAML.write({indent: 4}), 'utf-8');
//App.xaml.cs
@@ -178,9 +170,7 @@ module.exports.prototype = {
},
// updates the csproj file to explicitly list all www content.
update_csproj:function() {
- var raw = fs.readFileSync(this.csproj_path, 'utf-8');
- var cleaned = raw.replace(/^\uFEFF/i, '');
- var csproj_xml = new et.ElementTree(et.XML(cleaned));
+ var csproj_xml = xml.parseElementtreeSync(this.csproj_path);
// remove any previous references to the www files
var item_groups = csproj_xml.findall('ItemGroup');
for (var i = 0, l = item_groups.length; i < l; i++) {
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/src/plugin_parser.js
----------------------------------------------------------------------
diff --git a/src/plugin_parser.js b/src/plugin_parser.js
index 8b4582b..d3099c0 100644
--- a/src/plugin_parser.js
+++ b/src/plugin_parser.js
@@ -16,12 +16,12 @@
specific language governing permissions and limitations
under the License.
*/
-var et = require('elementtree'),
- fs = require('fs');
+var xml = require('./xml-helpers'),
+ fs = require('fs');
function plugin_parser(xmlPath) {
this.path = xmlPath;
- this.doc = new et.ElementTree(et.XML(fs.readFileSync(xmlPath, 'utf-8')));
+ this.doc = xml.parseElementtreeSync(xmlPath);
this.platforms = this.doc.findall('platform').map(function(p) {
return p.attrib.name;
});
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/0f56fbcd/src/xml-helpers.js
----------------------------------------------------------------------
diff --git a/src/xml-helpers.js b/src/xml-helpers.js
new file mode 100644
index 0000000..1d2a36a
--- /dev/null
+++ b/src/xml-helpers.js
@@ -0,0 +1,167 @@
+/*
+ *
+ * Copyright 2013 Anis Kadri
+ *
+ * Licensed 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.
+ *
+*/
+
+/**
+ * contains XML utility functions, some of which are specific to elementtree
+ */
+
+var fs = require('fs')
+ , path = require('path')
+ , et = require('elementtree');
+
+module.exports = {
+ moveProjFile: function(origFile, projPath, callback) {
+ var src = path.resolve(projPath, origFile)
+ , dest = src.replace('.orig', '');
+
+ fs.createReadStream(src)
+ .pipe(fs.createWriteStream(dest))
+ .on('close', callback);
+ },
+
+ // compare two et.XML nodes, see if they match
+ // compares tagName, text, attributes and children (recursively)
+ equalNodes: function(one, two) {
+ if (one.tag != two.tag) {
+ return false;
+ } else if (one.text.trim() != two.text.trim()) {
+ return false;
+ } else if (one._children.length != two._children.length) {
+ return false;
+ }
+
+ var oneAttribKeys = Object.keys(one.attrib),
+ twoAttribKeys = Object.keys(two.attrib),
+ i = 0, attribName;
+
+ if (oneAttribKeys.length != twoAttribKeys.length) {
+ return false;
+ }
+
+ for (i; i < oneAttribKeys.length; i++) {
+ attribName = oneAttribKeys[i];
+
+ if (one.attrib[attribName] != two.attrib[attribName]) {
+ return false;
+ }
+ }
+
+ for (i; i < one._children.length; i++) {
+ if (!module.exports.equalNodes(one._children[i], two._children[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ },
+
+ // adds node to doc at selector
+ graftXML: function(doc, nodes, selector) {
+ var parent = resolveParent(doc, selector);
+ if (!parent) return false;
+
+ nodes.forEach(function (node) {
+ // check if child is unique first
+ if (uniqueChild(node, parent)) {
+ parent.append(node);
+ }
+ });
+
+ return true;
+ },
+
+ // removes node from doc at selector
+ pruneXML: function(doc, nodes, selector) {
+ var parent = resolveParent(doc, selector);
+ if (!parent) return false;
+
+ nodes.forEach(function (node) {
+ var matchingKid = null;
+ if ((matchingKid = findChild(node, parent)) != null) {
+ // stupid elementtree takes an index argument it doesn't use
+ // and does not conform to the python lib
+ parent.remove(0, matchingKid);
+ }
+ });
+
+ return true;
+ },
+
+ parseElementtreeSync: function (filename) {
+ var contents = fs.readFileSync(filename, 'utf-8');
+ if(contents) {
+ contents = contents.replace(/^\uFEFF/, ''); //Windows is the BOM
+ }
+ return new et.ElementTree(et.XML(contents));
+ }
+};
+
+function findChild(node, parent) {
+ var matchingKids = parent.findall(node.tag)
+ , i, j;
+
+ for (i = 0, j = matchingKids.length ; i < j ; i++) {
+ if (module.exports.equalNodes(node, matchingKids[i])) {
+ return matchingKids[i];
+ }
+ }
+ return null;
+}
+
+function uniqueChild(node, parent) {
+ var matchingKids = parent.findall(node.tag)
+ , i = 0;
+
+ if (matchingKids.length == 0) {
+ return true;
+ } else {
+ for (i; i < matchingKids.length; i++) {
+ if (module.exports.equalNodes(node, matchingKids[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
+var ROOT = /^\/([^\/]*)/,
+ ABSOLUTE = /^\/([^\/]*)\/(.*)/;
+function resolveParent(doc, selector) {
+ var parent, tagName, subSelector;
+
+ // handle absolute selector (which elementtree doesn't like)
+ if (ROOT.test(selector)) {
+ tagName = selector.match(ROOT)[1];
+ // test for wildcard "any-tag" root selector
+ if (tagName == '*' || tagName === doc._root.tag) {
+ parent = doc._root;
+
+ // could be an absolute path, but not selecting the root
+ if (ABSOLUTE.test(selector)) {
+ subSelector = selector.match(ABSOLUTE)[2];
+ parent = parent.find(subSelector)
+ }
+ } else {
+ return false;
+ }
+ } else {
+ parent = doc.find(selector)
+ }
+ return parent;
+}