UNPKG

nodekit-cli

Version:

A command-line tool for creating {NK} NodeKit applications

165 lines (135 loc) 5.35 kB
/* * 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://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 util = require('util'); var path = require('path'); var CommonMunger = require('nodekit-cli')['nodekit-cli-common'].ConfigChanges.PlatformMunger; var CapsNeedUapPrefix = require(path.join(__dirname, 'AppxManifest')).CapsNeedUapPrefix; var CAPS_SELECTOR = '/Package/Capabilities'; var WINDOWS10_MANIFEST = 'package.windows10.appxmanifest'; function PlatformMunger(platform, project_dir, platformJson, pluginInfoProvider) { CommonMunger.apply(this, arguments); } util.inherits(PlatformMunger, CommonMunger); /** * This is an override of apply_file_munge method from nodekit-common's PlatformMunger class. * In addition to parent's method logic also removes capabilities with 'uap:' prefix that were * added by AppxManifest class * * @param {String} file A file name to apply munge to * @param {Object} munge Serialized changes that need to be applied to the file * @param {Boolean} [remove=false] Flag that specifies whether the changes * need to be removed or added to the file */ PlatformMunger.prototype.apply_file_munge = function (file, munge, remove) { // Create a copy to avoid modification of original munge var mungeCopy = cloneObject(munge); var capabilities = mungeCopy.parents[CAPS_SELECTOR]; if (capabilities) { // Add 'uap' prefixes for windows 10 manifest if (file === WINDOWS10_MANIFEST) { capabilities = generateUapCapabilities(capabilities); } // Remove duplicates and sort capabilities when installing plugin if (!remove) { capabilities = getUniqueCapabilities(capabilities).sort(compareCapabilities); } // Put back capabilities into munge's copy mungeCopy.parents[CAPS_SELECTOR] = capabilities; } PlatformMunger.super_.prototype.apply_file_munge.call(this, file, mungeCopy, remove); }; // Recursive function to clone an object function cloneObject(obj) { if (obj === null || typeof obj !== 'object') { return obj; } var copy = obj.constructor(); Object.keys(obj).forEach(function(key) { copy[key] = cloneObject(obj[key]); }); return copy; } /** * Retrieve capabality name from xml field * @param {Object} capability with xml field like <Capability Name="CapabilityName"> * @return {String} name of capability */ function getCapabilityName(capability) { var reg = /Name\s*=\s*"(.*?)"/; return capability.xml.match(reg)[1]; } /** * Remove capabilities with same names * @param {Object} an array of capabilities * @return {Object} an unique array of capabilities */ function getUniqueCapabilities(capabilities) { return capabilities.reduce(function(uniqueCaps, currCap) { var isRepeated = uniqueCaps.some(function(cap) { return getCapabilityName(cap) === getCapabilityName(currCap); }); return isRepeated ? uniqueCaps : uniqueCaps.concat([currCap]); }, []); } /** * Comparator function to pass to Array.sort * @param {Object} firstCap first capability * @param {Object} secondCap second capability * @return {Number} either -1, 0 or 1 */ function compareCapabilities(firstCap, secondCap) { var firstCapName = getCapabilityName(firstCap); var secondCapName = getCapabilityName(secondCap); if (firstCapName < secondCapName) { return -1; } if (firstCapName > secondCapName) { return 1; } return 0; } /** * Generates a new munge that contains <uap:Capability> elements created based on * corresponding <Capability> elements from base munge. If there are no such elements * found in base munge, the empty munge is returned (selectors might be present under * the 'parents' key, but they will contain no changes). * * @param {Object} capabilities A list of capabilities * @return {Object} A list with 'uap'-prefixed capabilities */ function generateUapCapabilities(capabilities) { function hasCapabilityChange(change) { return /^\s*<(\w+:)?(Device)?Capability\s/.test(change.xml); } function createPrefixedCapabilityChange(change) { if (CapsNeedUapPrefix.indexOf(getCapabilityName(change)) < 0) { return change; } // If capability is already prefixed, avoid adding another prefix var replaceXML = change.xml.indexOf('uap:') > 0 ? change.xml : change.xml.replace(/Capability/, 'uap:Capability'); return { xml: replaceXML, count: change.count, before: change.before }; } return capabilities // For every xml change check if it adds a <Capability> element ... .filter(hasCapabilityChange) // ... and create a duplicate with 'uap:' prefix .map(createPrefixedCapabilityChange); } exports.PlatformMunger = PlatformMunger;