{"version":3,"sources":["../../../packages/tools/gulp-manifest-resource/index.ts"],"names":[],"mappings":"","file":"index.d.ts","sourcesContent":["'use strict';\r\n\r\nimport { Buffer } from 'buffer';\r\nimport fs from 'fs';\r\nimport log from 'fancy-log';\r\nimport pluginError from 'plugin-error';\r\nimport through2 from 'through2';\r\nimport Vinyl from 'vinyl';\r\nimport * as util from '../utilities';\r\n\r\nconst PLUGIN_NAME = 'gulp-manifest-resource';\r\n\r\ninterface Options {\r\n    /**\r\n     * resource name.\r\n     */\r\n    resourceName: string;\r\n\r\n    /**\r\n     * path of manifest file.\r\n     */\r\n    manifest: string;\r\n\r\n    /**\r\n     * depth of folder structure from the locale folder. (default is 1)\r\n     */\r\n    localeOffset: number;\r\n}\r\n\r\nfunction gulpManifestResources(options: Options) {\r\n    function findResourceKey(node: any, results: string[]): void {\r\n        const match = 'resources:strings:';\r\n        const keys = Object.keys(node);\r\n        if (keys && keys.length > 0) {\r\n            keys.forEach(key => {\r\n                const target = node[key];\r\n                if (target) {\r\n                    if (typeof target === 'string') {\r\n                        if (target.indexOf(match) === 0) {\r\n                            const value = target.substring(match.length);\r\n                            if (results.indexOf(value) < 0) {\r\n                                results.push(value);\r\n                            }\r\n                        }\r\n                    } else {\r\n                        findResourceKey(target, results);\r\n                    }\r\n                }\r\n            });\r\n        }\r\n    }\r\n\r\n    // override options settings if not specified.\r\n    options = <Options>Object.assign(\r\n        {\r\n            manifest: 'src/manifest.json',\r\n            localeOffset: 1\r\n        },\r\n        options || {});\r\n\r\n    const resources: any = {};\r\n\r\n    return through2.obj(\r\n        /**\r\n         * Transform\r\n         */\r\n        function (file, encoding, callback) {\r\n            let locale = 'default';\r\n            if (resources.default) {\r\n                // if default is set already, find current locale from the file path.\r\n                const pathSegments = file.history[0].split('\\\\');\r\n                locale = pathSegments[pathSegments.length - (2 + options.localeOffset)];\r\n            }\r\n\r\n            resources[locale] = {};\r\n            if (resources.default) {\r\n                // if default is set already, pre-fill all resource items from default.\r\n                for (const resourceId in resources.default) {\r\n                    if (resources.default.hasOwnProperty(resourceId)) {\r\n                        resources[locale][resourceId] = resources.default[resourceId];\r\n                    }\r\n                }\r\n            }\r\n\r\n            // remove comments, /* multiline comment */ and // one line comment and \"//\": \"JSON element comment\"\r\n            const content = file.contents.toString('utf8')\r\n                                .replace(/(\\/\\*([^*]|[\\n]|(\\*+([^*/]|[\\n])))*\\*\\/+)|( +\\/\\/.*)|(  +\\\"\\/\\/\\\".*)/g, '');\r\n            const object = JSON.parse(content);\r\n            if (object[options.resourceName] && object[options.resourceName]['Manifest']) {\r\n                // supports <ResourceName>.Manifest.<KeyName> format.\r\n                const items = object[options.resourceName]['Manifest'];\r\n                for (const key in items) {\r\n                    if (items.hasOwnProperty(key)) {\r\n                        resources[locale][key] = items[key];\r\n                    }\r\n                }\r\n            } else {\r\n                // supports <ResourceName>_Manifest_KeyName format.\r\n                const resourceManifest = options.resourceName + '_Manifest_';\r\n                for (const name in object) {\r\n                    if (object.hasOwnProperty(name)) {\r\n                        const index = name.indexOf(resourceManifest);\r\n                        if (index === 0) {\r\n                            const value = object[name];\r\n                            const resourceId2 = name.substring(resourceManifest.length);\r\n                            resources[locale][resourceId2] = value;\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n\r\n            return callback();\r\n        },\r\n\r\n        /**\r\n         * Flush\r\n         */\r\n        function (callback) {\r\n            let result = null;\r\n            try {\r\n                const manifestObject = JSON.parse(fs.readFileSync(options.manifest, 'utf8'));\r\n\r\n                const keys: string[] = [];\r\n                findResourceKey(manifestObject, keys);\r\n                const missing: string[] = [];\r\n                const unused: string[] = Object.keys(resources.default);\r\n\r\n                keys.forEach(function (key) {\r\n                    const index = unused.indexOf(key);\r\n                    if (index >= 0) {\r\n                        unused.splice(index, 1);\r\n                    } else {\r\n                        missing.push(key);\r\n                    }\r\n                });\r\n\r\n                if (missing.length > 0) {\r\n                    missing.forEach(item => {\r\n                        log.error('Missing resource: ' + item);\r\n                    });\r\n                    throw new Error('Missing resource found in manifest.json!');\r\n                }\r\n\r\n                if (unused.length > 0) {\r\n                    unused.forEach(item => {\r\n                        log.error('Unused resource: ' + item);\r\n                    });\r\n                    throw new Error('Unused resource found in strings.resjson!');\r\n                }\r\n\r\n                const locales = [];\r\n                for (const locale in resources) {\r\n                    if (resources.hasOwnProperty(locale) && locale !== 'default') {\r\n                        locales.push(locale);\r\n                    }\r\n                }\r\n\r\n                locales.sort();\r\n                locales.unshift('default');\r\n                const formattedResources = [];\r\n                for (const locale of locales) {\r\n                    formattedResources.push({\r\n                        locale: locale,\r\n                        strings: resources[locale]\r\n                    });\r\n                }\r\n\r\n                manifestObject.resources = formattedResources;\r\n                const manifestFile = new Vinyl({\r\n                    cwd: './',\r\n                    path: options.manifest,\r\n                    contents: Buffer.from(JSON.stringify(manifestObject, null, 2), 'utf8')\r\n                });\r\n\r\n                this.push(manifestFile);\r\n            } catch (e) {\r\n                const error = (!e.plugin || (e.plugin !== PLUGIN_NAME)) ?\r\n                    util.extendError(new pluginError({ plugin: PLUGIN_NAME, message: e.message }), e) : e;\r\n                log.error(error);\r\n                result = e;\r\n            }\r\n\r\n            callback(result);\r\n        });\r\n}\r\n\r\nmodule.exports = gulpManifestResources;\r\n"]}