Repository: cordova-windows Updated Branches: refs/heads/master a4c673e30 -> 10594681c
CB-10622 Support any MRT qualifiers for Windows icons This closes #159, closes #162, closes #149 Project: http://git-wip-us.apache.org/repos/asf/cordova-windows/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-windows/commit/10594681 Tree: http://git-wip-us.apache.org/repos/asf/cordova-windows/tree/10594681 Diff: http://git-wip-us.apache.org/repos/asf/cordova-windows/diff/10594681 Branch: refs/heads/master Commit: 10594681c9331f2be9bfd30d54a0c170e36a84f3 Parents: a4c673e Author: Vladimir Kotikov <kotikov.vladi...@gmail.com> Authored: Mon Mar 14 15:24:15 2016 +0300 Committer: Vladimir Kotikov <kotikov.vladi...@gmail.com> Committed: Tue Mar 29 09:54:44 2016 +0300 ---------------------------------------------------------------------- spec/unit/MRTImage.spec.js | 70 ++++++++++++++++++++++++++++++ spec/unit/Prepare.Win10.spec.js | 80 ++++++++++++++++++++++++++++++++++- template/cordova/lib/MRTImage.js | 65 ++++++++++++++++++++++++++++ template/cordova/lib/prepare.js | 37 +++++++--------- 4 files changed, 229 insertions(+), 23 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/10594681/spec/unit/MRTImage.spec.js ---------------------------------------------------------------------- diff --git a/spec/unit/MRTImage.spec.js b/spec/unit/MRTImage.spec.js new file mode 100644 index 0000000..4f27df0 --- /dev/null +++ b/spec/unit/MRTImage.spec.js @@ -0,0 +1,70 @@ +/** + 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 MRTImage = require('../../template/cordova/lib/MRTImage'); + +describe('MRTImage class', function () { + + it('should be constructable', function () { + expect(new MRTImage('some/path/Image.scale-240.png')).toBeDefined(); + }); + + it('should detect base name and qualifiers properly', function () { + expect(new MRTImage('some/path/Image.scale-240.png').basename).toBe('Image'); + expect(new MRTImage('some/path/Basename.with.dots.scale-240.png').basename).toBe('Basename.with.dots'); + expect(new MRTImage('some/path/Basename.with.dots.png').basename).toBe('Basename.with'); + + expect(new MRTImage('some/path/Image.png').qualifiers).toBe('scale-100'); + expect(new MRTImage('some/path/Image.scale-240.png').qualifiers).toBe('scale-240'); + expect(new MRTImage('some/path/Image.targetsize-20_altform-unplated.png').qualifiers).toBe('targetsize-20_altform-unplated'); + }); + + describe('matchesTo method', function () { + it('should compare MRTImage instances properly', function () { + var testImage = new MRTImage('some/path/Basename.scale-240.png'); + + expect(new MRTImage('some/path/Basename.png').matchesTo(testImage)).toBe(true); + expect(new MRTImage('some/path/Basename.scale-240.png').matchesTo(testImage)).toBe(true); + expect(new MRTImage('some/path/Basename.targetsize-20_scale-240.png').matchesTo(testImage)).toBe(true); + + expect(new MRTImage(testImage).matchesTo('')).toBe(false); + expect(new MRTImage(testImage).matchesTo({})).toBe(false); + expect(new MRTImage(testImage).matchesTo(undefined)).toBe(false); + + expect(new MRTImage('some/path/Basename.jpg').matchesTo(testImage)).toBe(false); + expect(new MRTImage('some/path/Basename.with.dots.scale-240.png').matchesTo(testImage)).toBe(false); + }); + }); + + describe('generateFilenameFrom method', function () { + it('should use baseName argument to construct new filename', function () { + var testImage = new MRTImage('some/path/Basename.scale-240.png'); + + expect(testImage.generateFilenameFrom('NewName')).toMatch(/^NewName(.*)\.png/); + expect(testImage.generateFilenameFrom('NewName')).not.toMatch(/Basename/); + }); + + it('should leave qualifiers unchanged', function () { + var testImage = new MRTImage('some/path/Basename.scale-240.png'); + + expect(testImage.generateFilenameFrom('NewName')).toMatch(/\.scale-240\.png$/); + expect(testImage.generateFilenameFrom('NewName.with.dots-and-dashes')).toMatch(/\.scale-240\.png$/); + }); + }); +}); http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/10594681/spec/unit/Prepare.Win10.spec.js ---------------------------------------------------------------------- diff --git a/spec/unit/Prepare.Win10.spec.js b/spec/unit/Prepare.Win10.spec.js index b0d671d..074c3a5 100644 --- a/spec/unit/Prepare.Win10.spec.js +++ b/spec/unit/Prepare.Win10.spec.js @@ -17,6 +17,9 @@ under the License. */ +var path = require('path'); +var shell = require('shelljs'); + var rewire = require('rewire'), prepare = rewire('../../template/cordova/lib/prepare'), AppxManifest = require('../../template/cordova/lib/AppxManifest'), @@ -382,7 +385,6 @@ describe('A Windows 10 project should apply the uap: namespace prefix to certain }); }); - function createMockConfigAndManifestForDescription(description) { var config = { version: function() { return '1.0.0.0'; }, @@ -453,3 +455,79 @@ describe('Package description', function () { expect(desc.attrib.Description).not.toMatch(/\n|\t/); }); }); + +describe('copyIcons method', function () { + var copyImages = prepare.__get__('copyImages'); + + var PROJECT = '/some/path'; + + function createMockConfig(images) { + var result = jasmine.createSpyObj('config', ['getIcons', 'getSplashScreens']); + result.getIcons.andReturn(images); + result.getSplashScreens.andReturn([]); + + return result; + } + + beforeEach(function () { + spyOn(shell, 'cp'); + }); + + it('should guess target filename based on icon size', function () { + var images = [ + {src: 'res/Windows/Square44x44Logo_100.png', width: '44', height: '44' }, + {src: 'res/Windows/Square44x44Logo_240.png', width: '106', height: '106' } + ]; + + var config = createMockConfig(images); + + copyImages(config, PROJECT); + + expect(shell.cp).toHaveBeenCalledWith('-f', path.normalize('res/Windows/Square44x44Logo_100.png'), path.join(PROJECT, 'images/Square44x44Logo.scale-100.png')); + expect(shell.cp).toHaveBeenCalledWith('-f', path.normalize('res/Windows/Square44x44Logo_240.png'), path.join(PROJECT, 'images/Square44x44Logo.scale-240.png')); + }); + + it('should ignore unknown icon sizes and emit a warning', function () { + var config = createMockConfig([ + {src: 'res/Windows/UnknownImage.png', width: '999', height: '999' }, + ]); + + var warnSpy = jasmine.createSpy('warn'); + events.on('warn', warnSpy); + copyImages(config, PROJECT); + expect(shell.cp).not.toHaveBeenCalled(); + expect(warnSpy.calls[0].args[0]).toMatch('image is skipped'); + }); + + describe('when "target" attribute is specified for the image', function () { + it('should copy all images with the same base name and extension to destination dir', function () { + var matchingFiles = [ + 'res/Windows/Square44x44.scale-100.png', + 'res/Windows/Square44x44.targetsize-16.png', + 'res/Windows/Square44x44.scale-150_targetsize-16.png', + 'res/Windows/Square44x44.targetsize-16_scale-200.png', + 'res/Windows/Square44x44.targetsize-16_altform-unplated_scale-200.png' + ]; + + var nonMatchingFiles = [ + 'res/Windows/Square55x55.scale-100.png', + 'res/Windows/Square44x44.targetsize-16.jpg' + ]; + + spyOn(fs, 'readdirSync').andReturn(matchingFiles.concat(nonMatchingFiles)); + + var images = [{src: 'res/Windows/Square44x44.png', target: 'SmallIcon' }]; + var config = createMockConfig(images); + + copyImages(config, PROJECT); + + expect(shell.cp.calls.length).toBe(5); + matchingFiles.forEach(function (filename) { + expect(shell.cp).toHaveBeenCalledWith('-f', path.normalize(filename), jasmine.any(String)); + }); + shell.cp.calls.forEach(function (call) { + expect(path.basename(call.args[2])).toMatch(/^SmallIcon.*\.png$/); + }); + }); + }); +}); http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/10594681/template/cordova/lib/MRTImage.js ---------------------------------------------------------------------- diff --git a/template/cordova/lib/MRTImage.js b/template/cordova/lib/MRTImage.js new file mode 100644 index 0000000..822ece9 --- /dev/null +++ b/template/cordova/lib/MRTImage.js @@ -0,0 +1,65 @@ +/** + 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 path = require('path'); + +function MRTImage(filePath) { + this.path = filePath; + this.location = path.dirname(filePath); + this.extension = path.extname(filePath); + this.basename = path.basename(filePath, this.extension); + // 'scale-100' is the default qualifier + this.qualifiers = 'scale-100'; + + var nameParts = this.basename.split('.'); + if (nameParts.length > 1) { + // Qualifiers is the dotted segment in the file just before the file extension + // If no such segment in filename, then qualifiers is empty string + this.qualifiers = nameParts[nameParts.length - 1]; + // Basename it everything before that segment + this.basename = nameParts.slice(0, -1).join('.'); + } +} + +/** + * Indicates whether the current instance is matches to another one + * (base names and extensions are equal) + * + * @param {MRTImage} anotherImage Another instance of MRTImage class. + * @returns {Boolean} True if the current instance is matches to another one + */ +MRTImage.prototype.matchesTo = function (anotherImage) { + return anotherImage instanceof MRTImage && + anotherImage.basename === this.basename && + anotherImage.extension === this.extension; +}; + +/** + * Generates a new filename based on new base name for the file. for example + * new MRTImage('myFileName.scale-400.png').replaceBaseName('otherFileName') + * -> 'otherFileName.scale-400.png' + * + * @param {String} baseName A new base name to use + * @returns {String} A new filename + */ +MRTImage.prototype.generateFilenameFrom = function (baseName) { + return [baseName, this.qualifiers].join('.') + this.extension; +}; + +module.exports = MRTImage; http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/10594681/template/cordova/lib/prepare.js ---------------------------------------------------------------------- diff --git a/template/cordova/lib/prepare.js b/template/cordova/lib/prepare.js index e8e04fc..f2d560c 100644 --- a/template/cordova/lib/prepare.js +++ b/template/cordova/lib/prepare.js @@ -23,6 +23,7 @@ var path = require('path'); var shell = require('shelljs'); var et = require('elementtree'); var Version = require('./Version'); +var MRTImage = require('./MRTImage'); var AppxManifest = require('./AppxManifest'); var MSBuildTools = require('./MSBuildTools'); var ConfigParser = require('./ConfigParser'); @@ -303,30 +304,22 @@ function copyImages(config, platformRoot) { } function copyMrtImage(src, dest) { - var srcDir = path.dirname(src), - srcExt = path.extname(src), - srcFileName = path.basename(src, srcExt); + // Parse source path into new MRTImage + var imageToCopy = new MRTImage(src); - var destExt = path.extname(dest), - destFileName = path.basename(dest, destExt); + // then get all matching MRT images in source directory + var candidates = fs.readdirSync(imageToCopy.location) + .map(function (file) { return new MRTImage(file); }) + .filter(imageToCopy.matchesTo, imageToCopy); - // all MRT images: logo.png, logo.scale-100.png, logo.scale-200.png, etc - var images = fs.readdirSync(srcDir).filter(function(e) { - return e.match('^'+srcFileName + '(.scale-[0-9]+)?' + srcExt); - }); - // warn if no images found - if (images.length === 0) { - events.emit('warn', 'No images found for target: ' + destFileName); - return; - } - // copy images with new name but keeping scale suffix - images.forEach(function(img) { - var scale = path.extname(path.basename(img, srcExt)); - if (scale === '') { - scale = '.scale-100'; - } - copyImage(path.join(srcDir, img), destFileName+scale+destExt); + candidates.forEach(function(mrtImage) { + // copy images with new base name but keeping qualifier + copyImage(mrtImage.path, mrtImage.generateFilenameFrom(dest)); }); + + // Warn user if no images were copied + if (candidates.length === 0) + events.emit('warn', 'No images found for target: ' + dest); } // Platform default images @@ -371,7 +364,7 @@ function copyImages(config, platformRoot) { images.forEach(function (img) { if (img.target) { - copyMrtImage(img.src, img.target + '.png'); + copyMrtImage(img.src, img.target); } else { // find target image by size var targetImg = findPlatformImage (img.width, img.height); --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cordova.apache.org For additional commands, e-mail: commits-h...@cordova.apache.org