function mapLaunchStoryboardContents (splashScreens, launchStoryboardImagesDir) {
    const platformLaunchStoryboardImages = [];
    const idioms = ['universal', 'ipad', 'iphone'];
    const scalesForIdiom = {
        universal: ['1x', '2x', '3x'],
        ipad: ['1x', '2x'],
        iphone: ['1x', '2x', '3x']
    };
    const sizes = ['com', 'any'];
    const appearences = ['', 'dark', 'light'];

    idioms.forEach(idiom => {
        scalesForIdiom[idiom].forEach(scale => {
            sizes.forEach(width => {
                sizes.forEach(height => {
                    appearences.forEach(appearence => {
                        const item = { idiom, scale, width, height };

                        if (appearence !== '') {
                            item.appearence = appearence;
                        }

                        /* examples of the search pattern:
                         *    scale   ~  idiom    ~   width    height ~ appearence
                         *     @2x    ~ universal ~    any      any
                         *     @3x    ~  iphone   ~    com      any   ~   dark
                         *     @2x    ~   ipad    ~    com      any   ~   light
                         */
                        const searchPattern = '@' + scale + '~' + idiom + '~' + width + height + (appearence ? '~' + appearence : '');

                        /* because old node versions don't have Array.find, the below is
                         * functionally equivalent to this:
                         *     var launchStoryboardImage = splashScreens.find(function(item) {
                         *         return (item.src.indexOf(searchPattern) >= 0) ? (appearence !== '' ? true : ((item.src.indexOf(searchPattern + '~light') >= 0 || (item.src.indexOf(searchPattern + '~dark') >= 0)) ? false : true)) : false;
                         *     });
                         */
                        const launchStoryboardImage = splashScreens.reduce(
                            (p, c) => (c.src.indexOf(searchPattern) >= 0) ? (appearence !== '' ? c : ((c.src.indexOf(searchPattern + '~light') >= 0 || (c.src.indexOf(searchPattern + '~dark') >= 0)) ? p : c)) : p,
                            undefined
                        );

                        if (launchStoryboardImage) {
                            item.filename = `Default${searchPattern}.png`;
                            item.src = launchStoryboardImage.src;
                            item.target = path.join(launchStoryboardImagesDir, item.filename);
                        }

                        platformLaunchStoryboardImages.push(item);
                    });
                });
            });
        });
    });
    return platformLaunchStoryboardImages;
}
Returns an array of images for each possible idiom, scale, and size class. The images themselves are
located in the platform's splash images by their pattern (@scale~idiom~sizesize). All possible
combinations are returned, but not all will have a `filename` property. If the latter isn't present,
the device won't attempt to load an image matching the same traits. If the filename is present,
the device will try to load the image if it corresponds to the traits.

The resulting return looks like this:

    [
        {
            idiom: 'universal|ipad|iphone',
            scale: '1x|2x|3x',
            width: 'any|com',
            height: 'any|com',
            filename: undefined|'Default@scale~idiom~widthheight.png',
            src: undefined|'path/to/original/matched/image/from/splash/screens.png',
            target: undefined|'path/to/asset/library/Default@scale~idiom~widthheight.png',
            appearence: undefined|'dark'|'light'
        }, ...
    ]

@param  {Array<Object>} splashScreens         splash screens as defined in config.xml for this platform
@param  {string} launchStoryboardImagesDir    project-root/Assets.xcassets/LaunchStoryboard.imageset/
@return {Array<Object>}