Updated Branches: refs/heads/master 01f3b0d73 -> 58ba1a4ac
tons of ios specs. Project: http://git-wip-us.apache.org/repos/asf/cordova-plugman/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugman/commit/58ba1a4a Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugman/tree/58ba1a4a Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugman/diff/58ba1a4a Branch: refs/heads/master Commit: 58ba1a4accc4eba08837b3e8179fdec136d53c78 Parents: 01f3b0d Author: Fil Maj <[email protected]> Authored: Wed Apr 24 15:35:02 2013 -0700 Committer: Fil Maj <[email protected]> Committed: Wed Apr 24 15:35:02 2013 -0700 ---------------------------------------------------------------------- README.md | 4 +- spec/platforms/ios.spec.js | 207 ++++++++++++++++++++++--- spec/plugins/DummyPlugin/plugin.xml | 17 +-- spec/plugins/PluginsPlistOnly/plugin.xml | 31 ++++ spec/plugins/VariablePlugin/plugin.xml | 9 +- src/platforms/ios.js | 56 +++---- 6 files changed, 259 insertions(+), 65 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/58ba1a4a/README.md ---------------------------------------------------------------------- diff --git a/README.md b/README.md index 622aee1..32188db 100644 --- a/README.md +++ b/README.md @@ -269,7 +269,7 @@ into a project. A couple of examples: <source-file src="src/android/Foo.java" target-dir="src/com/alunny/foo" /> <!-- ios --> - <source-file src="CDVFoo.m" /> + <source-file src="src/ios/CDVFoo.m" /> #### src (required) @@ -288,7 +288,7 @@ the package `com.alunny.foo` has be located under the directory `com/alunny/foo`. For platforms where the source directory is not important, plugin authors should omit this attribute. -As with assets, if a `source-file`'s `target` would overwrite an existing file, plugman will stop/reverse the installation, notify the user rnd exit with a non-zero code. +As with assets, if a `source-file`'s `target` would overwrite an existing file, plugman will stop/reverse the installation, notify the user and exit with a non-zero code. ### <config-file> http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/58ba1a4a/spec/platforms/ios.spec.js ---------------------------------------------------------------------- diff --git a/spec/platforms/ios.spec.js b/spec/platforms/ios.spec.js index 08c2103..2e43bf5 100644 --- a/spec/platforms/ios.spec.js +++ b/spec/platforms/ios.spec.js @@ -1,6 +1,71 @@ -var ios = require('../../src/platforms/ios'); +var ios = require('../../src/platforms/ios'), + install = require('../../src/install'), + path = require('path'), + fs = require('fs'), + et = require('elementtree'), + shell = require('shelljs'), + os = require('osenv'), + xcode = require('xcode'), + plist = require('plist'), + bplist = require('bplist-parser'), + temp = path.join(os.tmpdir(), 'plugman'), + plugins_dir = path.join(temp, 'cordova', 'plugins'), + ios_config_xml_project = path.join(__dirname, '..', 'projects', 'ios-config-xml', '*'), + ios_plist_project = path.join(__dirname, '..', 'projects', 'ios-plist', '*'), + xml_helpers = require('../../src/util/xml-helpers'), + variableplugin = path.join(__dirname, '..', 'plugins', 'VariablePlugin'), + faultyplugin = path.join(__dirname, '..', 'plugins', 'FaultyPlugin'), + plistplugin = path.join(__dirname, '..', 'plugins', 'PluginsPlistOnly'), + dummyplugin = path.join(__dirname, '..', 'plugins', 'DummyPlugin'); + +var xml_path = path.join(dummyplugin, 'plugin.xml'), + xml_test = fs.readFileSync(xml_path, 'utf-8'), + plugin_et = new et.ElementTree(et.XML(xml_test)); + +var platformTag = plugin_et.find('./platform[@name="ios"]'); +var dummy_id = plugin_et._root.attrib['id']; +var valid_source = platformTag.findall('./source-file'), + assets = plugin_et.findall('./asset'), + plist_els = platformTag.findall('./plugins-plist'), + dummy_configs = platformTag.findall('./config-file'); + +xml_path = path.join(variableplugin, 'plugin.xml'); +xml_test = fs.readFileSync(xml_path, 'utf-8'); +plugin_et = new et.ElementTree(et.XML(xml_test)); +platformTag = plugin_et.find('./platform[@name="ios"]'); + +var variable_id = plugin_et._root.attrib['id']; +var variable_configs = platformTag.findall('./config-file'); + +xml_path = path.join(faultyplugin, 'plugin.xml'); +xml_test = fs.readFileSync(xml_path, 'utf-8'); +plugin_et = new et.ElementTree(et.XML(xml_test)); +platformTag = plugin_et.find('./platform[@name="ios"]'); + +var faulty_id = plugin_et._root.attrib['id']; +var invalid_source = platformTag.findall('./source-file'); + +xml_path = path.join(plistplugin, 'plugin.xml'); +xml_test = fs.readFileSync(xml_path, 'utf-8'); +plugin_et = new et.ElementTree(et.XML(xml_test)); +platformTag = plugin_et.find('./platform[@name="ios"]'); + +var plist_id = plugin_et._root.attrib['id']; +var plist_only_els = platformTag.findall('./plugins-plist'); + +function copyArray(arr) { + return Array.prototype.slice.call(arr, 0); +} describe('ios project handler', function() { + beforeEach(function() { + shell.mkdir('-p', temp); + shell.mkdir('-p', plugins_dir); + }); + afterEach(function() { + shell.rm('-rf', temp); + }); + it('should have an install function', function() { expect(typeof ios.install).toEqual('function'); }); @@ -12,25 +77,114 @@ describe('ios project handler', function() { }); describe('installation', function() { - it('should throw if project is not an xcode project'); - it('should throw if project does not contain an appropriate PhoneGap/Cordova.plist file or config.xml file'); - it('should interpolate any variables correctly into pbx, plist and config files'); + it('should throw if project is not an xcode project', function() { + expect(function() { + ios.install([], 'someid', temp, plugins_dir, {}); + }).toThrow('does not appear to be an xcode project (no xcode project file)'); + }); + it('should throw if project does not contain an appropriate PhoneGap/Cordova.plist file or config.xml file', function() { + shell.cp('-rf', ios_config_xml_project, temp); + shell.rm(path.join(temp, 'SampleApp', 'config.xml')); + + expect(function() { + ios.install([], 'someid', temp, plugins_dir, {}); + }).toThrow('could not find PhoneGap/Cordova plist file, or config.xml file.'); + }); + it('should interpolate any variables correctly into pbx, plist and config files', function() { + shell.cp('-rf', ios_config_xml_project, temp); + ios.install(variable_configs, variable_id, temp, plugins_dir, {'API_KEY':'ruthless competency'}); + var config_file = path.join(temp, 'SampleApp', 'config.xml'); + var contents = fs.readFileSync(config_file, 'utf-8'); + expect(contents).toMatch(/awesome value="ruthless competency"/gi); + }); describe('of <source-file> elements', function() { - it('should throw if source-file src cannot be found'); - it('should throw if source-file target already exists'); - it('should use appropriate paths based on preserve-dirs attribute'); - it('should call into xcodeproj\'s addSourceFile'); - it('should cp the file to the right target location'); + beforeEach(function() { + shell.cp('-rf', ios_config_xml_project, temp); + }); + + it('should throw if source-file src cannot be found', function() { + var source = copyArray(invalid_source); + expect(function() { + ios.install(source, faulty_id, temp, faultyplugin, {}); + }).toThrow('cannot find "' + path.resolve(faultyplugin, 'src/ios/FaultyPluginCommand.m') + '" ios <source-file>'); + }); + it('should throw if source-file target already exists', function() { + var source = copyArray(valid_source); + var target = path.join(temp, 'SampleApp', 'Plugins', 'DummyPluginCommand.m'); + fs.writeFileSync(target, 'some bs', 'utf-8'); + expect(function() { + ios.install(source, dummy_id, temp, dummyplugin, {}); + }).toThrow('target destination "' + target + '" already exists'); + }); + it('should call into xcodeproj\'s addSourceFile appropriately when element has no target-dir', function() { + var source = copyArray(valid_source).filter(function(s) { return s.attrib['target-dir'] == undefined}); + var spy = jasmine.createSpy(); + spyOn(xcode, 'project').andReturn({ + parseSync:function(){}, + writeSync:function(){}, + addSourceFile:spy + }); + ios.install(source, dummy_id, temp, dummyplugin, {}); + expect(spy).toHaveBeenCalledWith(path.join('Plugins', 'DummyPluginCommand.m')); + }); + it('should call into xcodeproj\'s addSourceFile appropriately when element has a target-dir', function() { + var source = copyArray(valid_source).filter(function(s) { return s.attrib['target-dir'] != undefined}); + var spy = jasmine.createSpy(); + spyOn(xcode, 'project').andReturn({ + parseSync:function(){}, + writeSync:function(){}, + addSourceFile:spy + }); + ios.install(source, dummy_id, temp, dummyplugin, {}); + expect(spy).toHaveBeenCalledWith(path.join('Plugins', 'targetDir', 'TargetDirTest.m')); + }); + it('should cp the file to the right target location when element has no target-dir', function() { + var source = copyArray(valid_source).filter(function(s) { return s.attrib['target-dir'] == undefined}); + spyOn(xcode, 'project').andReturn({ + parseSync:function(){}, + writeSync:function(){}, + addSourceFile:function() {} + }); + var spy = spyOn(shell, 'cp'); + ios.install(source, dummy_id, temp, dummyplugin, {}); + expect(spy).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'DummyPluginCommand.m'), path.join(temp, 'SampleApp', 'Plugins', 'DummyPluginCommand.m')); + }); + it('should cp the file to the right target location when element has a target-dir', function() { + var source = copyArray(valid_source).filter(function(s) { return s.attrib['target-dir'] != undefined}); + spyOn(xcode, 'project').andReturn({ + parseSync:function(){}, + writeSync:function(){}, + addSourceFile:function() {} + }); + var spy = spyOn(shell, 'cp'); + ios.install(source, dummy_id, temp, dummyplugin, {}); + expect(spy).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'TargetDirTest.m'), path.join(temp, 'SampleApp', 'Plugins', 'targetDir', 'TargetDirTest.m')); + }); }); describe('of <plugins-plist> elements', function() { - it('should only be used in an applicably old cordova-ios projects'); + it('should only be used in an applicably old cordova-ios projects', function() { + shell.cp('-rf', ios_plist_project, temp); + var pls = copyArray(plist_els); + var spy = spyOn(plist, 'parseFileSync').andReturn({Plugins:{}}); + ios.install(pls, dummy_id, temp, dummyplugin, {}); + expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 'PhoneGap.plist')); + }); + it('should not be used in an applicably new cordova-ios projects', function() { + shell.cp('-rf', ios_config_xml_project, temp); + var pls = copyArray(plist_els); + var spy = spyOn(plist, 'parseFileSync').andReturn({Plugins:{}}); + ios.install(pls, dummy_id, temp, dummyplugin, {}); + expect(spy).not.toHaveBeenCalledWith(path.join(temp, 'SampleApp', 'config.xml')); + }); + it('should add a <plugin> element in applicably new cordova-ios projects with old-style plugins using only <plugins-plist> elements', function() { + shell.cp('-rf', ios_config_xml_project, temp); + var pls = copyArray(plist_only_els); + }); }); describe('of <config-file> elements', function() { - it('should only be used in applicably new cordova-ios projects'); - it('should add a <plugin> element in applicably new cordova-ios projects with old-style plugins using only <plugins-plist> elements'); it('should call xml_helpers\' graftXML'); it('should write the new config file out after successfully grafting'); }); @@ -38,8 +192,8 @@ describe('ios project handler', function() { describe('of <header-file> elements', function() { it('should throw if header-file src cannot be found'); it('should throw if header-file target already exists'); - it('should use appropriate paths based on preserve-dirs attribute'); - it('should call into xcodeproj\'s addHeaderFile'); + it('should call into xcodeproj\'s addHeaderFile appropriately when element has no target-dir'); + it('should call into xcodeproj\'s addHeaderFile appropriately when element a no target-dir'); it('should cp the file to the right target location'); }); @@ -58,17 +212,30 @@ describe('ios project handler', function() { }); describe('uninstallation', function() { - it('should throw if project is not an xcode project'); - it('should throw if project does not contain an appropriate PhoneGap/Cordova.plist file or config.xml file'); + it('should throw if project is not an xcode project', function() { + expect(function() { + ios.uninstall([], 'someid', temp, plugins_dir); + }).toThrow('does not appear to be an xcode project (no xcode project file)'); + }); + it('should throw if project does not contain an appropriate PhoneGap/Cordova.plist file or config.xml file', function() { + shell.cp('-rf', ios_config_xml_project, temp); + shell.rm(path.join(temp, 'SampleApp', 'config.xml')); + expect(function() { + ios.uninstall([], 'someid', temp, plugins_dir); + }).toThrow('could not find PhoneGap/Cordova plist file, or config.xml file.'); + }); describe('of <source-file> elements', function() { - it('should use appropriate paths based on preserve-dirs attribute'); - it('should call into xcodeproj\'s removeSourceFile'); + it('should call into xcodeproj\'s removeSourceFile appropriately when element has no target-dir'); + it('should call into xcodeproj\'s removeSourceFile appropriately when element a no target-dir'); it('should rm the file from the right target location'); }); describe('of <plugins-plist> elements', function() { it('should only be used in an applicably old cordova-ios project'); + it('should not be used in an applicably old cordova-ios project'); + it('should remove the <plugin> element in applicably new cordova-ios projects with old-style plugins using only <plugins-plist> elements', function() { + }); }); describe('of <config-file> elements', function() { @@ -84,8 +251,8 @@ describe('ios project handler', function() { }); describe('of <header-file> elements', function() { - it('should use appropriate paths based on preserve-dirs attribute'); - it('should call into xcodeproj\'s removeHeaderFile'); + it('should call into xcodeproj\'s removeHeaderFile appropriately when element has no target-dir'); + it('should call into xcodeproj\'s removeHeaderFile appropriately when element a no target-dir'); it('should rm the file from the right target location'); }); http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/58ba1a4a/spec/plugins/DummyPlugin/plugin.xml ---------------------------------------------------------------------- diff --git a/spec/plugins/DummyPlugin/plugin.xml b/spec/plugins/DummyPlugin/plugin.xml index e21ed40..21845e7 100644 --- a/spec/plugins/DummyPlugin/plugin.xml +++ b/spec/plugins/DummyPlugin/plugin.xml @@ -84,20 +84,15 @@ value="DummyPluginCommand"/> </config-file> - <resource-file src="DummyPlugin.bundle" /> - <resource-file src="DummyPluginViewController.xib" /> + <resource-file src="src/ios/DummyPlugin.bundle" /> - <header-file src="DummyPluginCommand.h" /> - <header-file src="DummyPluginViewController.h" /> - <header-file src="preserveDirs/PreserveDirsTest.h" preserve-dirs="true" /> - <header-file src="TargetDirTest.h" target-dir="targetDir"/> + <header-file src="src/ios/DummyPluginCommand.h" /> + <source-file src="src/ios/DummyPluginCommand.m"/> - <source-file src="DummyPluginCommand.m" /> - <source-file src="DummyPluginViewController.m" /> - <source-file src="preserveDirs/PreserveDirsTest.m" preserve-dirs="true" /> - <header-file src="TargetDirTest.m" target-dir="targetDir"/> + <header-file src="src/ios/TargetDirTest.h" target-dir="targetDir" /> + <source-file src="src/ios/TargetDirTest.m" target-dir="targetDir" /> <!-- framework for testing (not actual dependency of DummyPlugin --> - <framework src="libsqlite3.dylib" /> + <framework src="src/ios/libsqlite3.dylib" /> </platform> </plugin> http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/58ba1a4a/spec/plugins/DummyPlugin/src/ios/DummyPlugin.bundle ---------------------------------------------------------------------- diff --git a/spec/plugins/DummyPlugin/src/ios/DummyPlugin.bundle b/spec/plugins/DummyPlugin/src/ios/DummyPlugin.bundle new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/58ba1a4a/spec/plugins/DummyPlugin/src/ios/DummyPluginCommand.h ---------------------------------------------------------------------- diff --git a/spec/plugins/DummyPlugin/src/ios/DummyPluginCommand.h b/spec/plugins/DummyPlugin/src/ios/DummyPluginCommand.h new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/58ba1a4a/spec/plugins/DummyPlugin/src/ios/DummyPluginCommand.m ---------------------------------------------------------------------- diff --git a/spec/plugins/DummyPlugin/src/ios/DummyPluginCommand.m b/spec/plugins/DummyPlugin/src/ios/DummyPluginCommand.m new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/58ba1a4a/spec/plugins/DummyPlugin/src/ios/TargetDirTest.h ---------------------------------------------------------------------- diff --git a/spec/plugins/DummyPlugin/src/ios/TargetDirTest.h b/spec/plugins/DummyPlugin/src/ios/TargetDirTest.h new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/58ba1a4a/spec/plugins/DummyPlugin/src/ios/TargetDirTest.m ---------------------------------------------------------------------- diff --git a/spec/plugins/DummyPlugin/src/ios/TargetDirTest.m b/spec/plugins/DummyPlugin/src/ios/TargetDirTest.m new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/58ba1a4a/spec/plugins/DummyPlugin/src/ios/libsqlite3.dylib ---------------------------------------------------------------------- diff --git a/spec/plugins/DummyPlugin/src/ios/libsqlite3.dylib b/spec/plugins/DummyPlugin/src/ios/libsqlite3.dylib new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/58ba1a4a/spec/plugins/PluginsPlistOnly/plugin.xml ---------------------------------------------------------------------- diff --git a/spec/plugins/PluginsPlistOnly/plugin.xml b/spec/plugins/PluginsPlistOnly/plugin.xml new file mode 100644 index 0000000..832e06c --- /dev/null +++ b/spec/plugins/PluginsPlistOnly/plugin.xml @@ -0,0 +1,31 @@ +<?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://www.phonegap.com/ns/plugins/1.0" + id="com.phonegap.plugins.oldskewl" + version="0.0.1"> + + <name>Old Skewl Plugin using Plists</name> + + <!-- ios --> + <platform name="ios"> + <plugins-plist key="OldSkewl" string="OldSkewlCommand" /> + </platform> +</plugin> http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/58ba1a4a/spec/plugins/VariablePlugin/plugin.xml ---------------------------------------------------------------------- diff --git a/spec/plugins/VariablePlugin/plugin.xml b/spec/plugins/VariablePlugin/plugin.xml index 580c329..67bddd0 100644 --- a/spec/plugins/VariablePlugin/plugin.xml +++ b/spec/plugins/VariablePlugin/plugin.xml @@ -26,12 +26,19 @@ <name>Use Variables</name> + <preference name="API_KEY" /> <!-- android --> <platform name="android"> - <preference name="API_KEY" /> <config-file target="AndroidManifest.xml" parent="/manifest"> <poop name="GoogleMapsApiKey" value="$API_KEY" /> </config-file> </platform> + + <!-- ios --> + <platform name="ios"> + <config-file target="config.xml" parent="/widget"> + <awesome value="$API_KEY" /> + </config-file> + </platform> </plugin> http://git-wip-us.apache.org/repos/asf/cordova-plugman/blob/58ba1a4a/src/platforms/ios.js ---------------------------------------------------------------------- diff --git a/src/platforms/ios.js b/src/platforms/ios.js index 9de3750..ac326af 100644 --- a/src/platforms/ios.js +++ b/src/platforms/ios.js @@ -77,7 +77,7 @@ function handlePlugin(action, plugin_id, txs, project_dir, plugin_dir, variables } var config_file = config_files[0]; - var base_config_path = path.basename(config_file); + var config_filename = path.basename(config_file); var xcode_dir = path.dirname(config_file); var pluginsDir = path.resolve(xcode_dir, 'Plugins'); var resourcesDir = path.resolve(xcode_dir, 'Resources'); @@ -106,7 +106,6 @@ function handlePlugin(action, plugin_id, txs, project_dir, plugin_dir, variables shell.mkdir('-p', targetDir); shell.cp(srcFile, destFile); } else { - // TODO: doesnt preserve-dirs affect what the originally-added path to xcodeproj (see above) affect how we should call remove too? xcodeproj.removeSourceFile(path.join('Plugins', path.basename(src))); shell.rm('-rf', destFile); // TODO: is this right, should we check if dir is empty? @@ -114,7 +113,9 @@ function handlePlugin(action, plugin_id, txs, project_dir, plugin_dir, variables } break; case 'plugins-plist': - // Only handle this if the config file is cordova/phonegap plist. + var name = mod.attrib.key; + var value = mod.attrib.string; + // Tack on stuff into plist if this is an old-style project if (path.extname(config_file) == '.plist') { // determine if this is a binary or ascii plist and choose the parser // TODO: this is temporary until binary support is added to node-plist @@ -131,39 +132,36 @@ function handlePlugin(action, plugin_id, txs, project_dir, plugin_dir, variables */ // add plugin to plist - plistObj.Plugins[mod.attrib['key']] = mod.attrib['string']; + plistObj.Plugins[name] = value; } else { - delete plistObj.Plugins[mod.attrib['key']]; + delete plistObj.Plugins[name]; } // write out plist fs.writeFileSync(config_file, plist.build(plistObj)); + } else { + // If it's a config.xml-based project, we should still add/remove plugin entry to config.xml + var xmlDoc = xml_helpers.parseElementtreeSync(config_file); + var pluginsEl = xmlDoc.find('plugins'); + if ( action == 'install') { + var new_plugin = new et.Element('plugin'); + new_plugin.attrib.name = name; + new_plugin.attrib.value = value; + pluginsEl.append(new_plugin); + } else { + var culprit = pluginsEl.find("plugin[@name='"+name+"']"); + pluginsEl.remove(0, culprit); + } + var output = xmlDoc.write({indent: 4}); + fs.writeFileSync(config_file, output); } break; case 'config-file': // Only use config file appropriate for the current cordova-ios project - if (mod.attrib['target'] == base_config_path) { + if (mod.attrib['target'] == config_filename) { // edit configuration files - var xmlDoc = xml_helpers.parseElementtreeSync(config_file), - pListOnly = !!plistEle; + var xmlDoc = xml_helpers.parseElementtreeSync(config_file); - if (mod.find("plugin")) pListOnly = false; - - if (pListOnly) { - // if the plugin supports the old plugins-plist element only - var name = plistEle.attrib.key; - var value = plistEle.attrib.string; - var pluginsEl = xmlDoc.find('plugins'); - if ( action == 'install') { - var new_plugin = new et.Element('plugin'); - new_plugin.attrib.name = name; - new_plugin.attrib.value = value; - pluginsEl.append(new_plugin); - } else { - var culprit = pluginsEl.find("plugin[@name='"+name+"']"); - pluginsEl.remove(0, culprit); - } - } var selector = mod.attrib["parent"], children = mod.findall('*'); @@ -263,12 +261,8 @@ function handlePlugin(action, plugin_id, txs, project_dir, plugin_dir, variables } function getRelativeDir(file) { - var targetDir = file.attrib['target-dir'], - preserveDirs = file.attrib['preserve-dirs']; - - if (preserveDirs && preserveDirs.toLowerCase() == 'true') { - return path.dirname(file.attrib['src']); - } else if (targetDir) { + var targetDir = file.attrib['target-dir']; + if (targetDir) { return targetDir; } else { return '';
