{"version":3,"sources":["../../../packages/tools/gulp-resjson/resjson-convert.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IAGpB,UAAU,EAAE,MAAM,CAAC;IAInB,UAAU,EAAE,MAAM,CAAC;IAGnB,IAAI,EAAE,OAAO,CAAC;IAId,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CAC9B;AAOD,qBAAa,gBAAgB;IAkBb,OAAO,CAAC,OAAO;IAjB3B,OAAO,CAAC,MAAM,CAAC,WAAW,CAM5B;IACE,OAAO,CAAC,MAAM,CAAC,YAAY,CAE7B;IACS,UAAU,EAAE,GAAG,CAAC;IACvB,OAAO,CAAC,gBAAgB,CAAW;IACnC,OAAO,CAAC,gBAAgB,CAAW;IACnC,OAAO,CAAC,eAAe,CAAW;IAClC,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,IAAI,CAAM;gBAEE,OAAO,EAAE,OAAO;IAGpC,IAAW,iBAAiB,IAAI,MAAM,CAErC;IAED,IAAW,iBAAiB,IAAI,MAAM,CAErC;IAED,IAAW,gBAAgB,IAAI,MAAM,CAEpC;IAEM,YAAY,IAAI,IAAI;IAQpB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO;IAUjD,OAAO,CAAC,WAAW;IA2CnB,OAAO,CAAC,WAAW;IAsBnB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,IAAI;IAqBZ,OAAO,CAAC,QAAQ;CAyCnB","file":"resjson-convert.d.ts","sourcesContent":["export interface Options {\r\n    // enable to produce xxxx.d.ts file.\r\n    // { null, 'module' }\r\n    definition: string;\r\n\r\n    // enable to produce xxxx.ts file.\r\n    //  { null, 'module', 'interface' }\r\n    typescript: string;\r\n\r\n    // enable to produce xxxx.json file.\r\n    json: boolean;\r\n\r\n    // if set a space characters, it adds formating of JSON.\r\n    // it set null, space will be eliminated.\r\n    jsonSpace: string | number;\r\n}\r\n\r\ninterface NameValuePair {\r\n    name: string;\r\n    value: any;\r\n}\r\n\r\nexport class ResJsonConverter {\r\n    private static openContent =\r\n`/* eslint:disable */\r\n/**\r\n * @file Source code generated by gulp-resjson.\r\n * @version 1.0\r\n */\r\n`;\r\n    private static closeContent =\r\n`}\r\n`;\r\n    public outputJson: any;\r\n    private outputDefinition: string[];\r\n    private outputTypescript: string[];\r\n    private outputInterface: string[];\r\n    private jsonCurrent: any;\r\n    private root: any;\r\n\r\n    constructor(private options: Options) {\r\n    }\r\n\r\n    public get contentDefinition(): string {\r\n        return this.outputDefinition.join('');\r\n    }\r\n\r\n    public get contentTypescript(): string {\r\n        return this.outputTypescript.join('');\r\n    }\r\n\r\n    public get contentInterface(): string {\r\n        return this.outputInterface.join('');\r\n    }\r\n\r\n    public contentReset(): void {\r\n        this.outputDefinition = [];\r\n        this.outputTypescript = [];\r\n        this.outputInterface = [];\r\n        this.outputJson = {};\r\n        this.jsonCurrent = this.outputJson;\r\n    }\r\n\r\n    public convert(content: string, validate: boolean) {\r\n        // Remove comments, /* multiline comment */ and // one line comment and \"//\": \"JSON element comment\"\r\n        content = content.replace(/(\\/\\*([^*]|[\\n]|(\\*+([^*/]|[\\n])))*\\*\\/+)|( +\\/\\/.*)|(  +\\\"\\/\\/\\\".*)/g, '');\r\n        const data: any = JSON.parse(content);\r\n        this.root = {};\r\n        this.buildObject(data, validate);\r\n        this.contentReset();\r\n        this.traverse([{ name: 'Strings', value: this.root }], 0);\r\n    }\r\n\r\n    private buildObject(data: any, validate: boolean, indexes?: string[]): void {\r\n        const itemKeys = Object.keys(data);\r\n        for (const itemKey of itemKeys) {\r\n            if (this.skipComment(itemKey, validate, itemKeys)) {\r\n                continue;\r\n            }\r\n\r\n            if (!data.hasOwnProperty(itemKey)) {\r\n                continue;\r\n            }\r\n\r\n            const itemValue = data[itemKey];\r\n            if (typeof itemValue !== 'string') {\r\n                // nested object, so scan inside to add to current.\r\n                const newIndexes = indexes ? indexes.slice(0) : [];\r\n                newIndexes.push(itemKey);\r\n                this.buildObject(itemValue, validate, newIndexes);\r\n                continue;\r\n            }\r\n\r\n            let current = this.root;\r\n            const keys = indexes ? indexes.slice(0) : [];\r\n            keys.push(...itemKey.split('_'));\r\n            let count = keys.length;\r\n            for (const key of keys) {\r\n                count--;\r\n                if (count > 0) {\r\n                    if (!current.hasOwnProperty(key)) {\r\n                        current[key] = {};\r\n                    }\r\n\r\n                    current = current[key];\r\n\r\n                    if (typeof current !== 'object') {\r\n                        throw new Error('Resource key already exists: ' + itemKey);\r\n                    }\r\n                } else {\r\n                    current[key] = itemValue;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    private skipComment(itemKey: string, validate: boolean, itemKeys: string[]): boolean {\r\n        // remove localization comments\r\n        if (itemKey.startsWith('//')) {\r\n            return true;\r\n        } else if (itemKey.startsWith('_')) {\r\n            if (validate) {\r\n                if (!itemKey.endsWith('.comment')) {\r\n                    throw new Error('Resource cannot start with underscore: ' + itemKey);\r\n                }\r\n\r\n                const found = itemKeys.find(item => itemKey === `_${item}.comment`);\r\n                if (!found) {\r\n                    throw new Error('Resource comment doesn\\'t match: ' + itemKey);\r\n                }\r\n            }\r\n\r\n            return true;\r\n        }\r\n\r\n        return false;\r\n    }\r\n\r\n    private jsonNewValue(name: string): any {\r\n        const old = this.jsonCurrent;\r\n        const json = {};\r\n        this.jsonCurrent[name] = json;\r\n        this.jsonCurrent = json;\r\n\r\n        return old;\r\n    }\r\n\r\n    private jsonAddValue(name: string, value: any): void {\r\n        this.jsonCurrent[name] = value;\r\n    }\r\n\r\n    private scan(node: any): { keyItems: NameValuePair[], dataItems: NameValuePair[] } {\r\n        const current = node;\r\n        const keyItems: NameValuePair[] = [];\r\n        const dataItems: NameValuePair[] = [];\r\n        for (const itemKey in current) {\r\n            if (current.hasOwnProperty(itemKey)) {\r\n                const itemValue: any = current[itemKey];\r\n                if (typeof itemValue === 'object') {\r\n                    keyItems.push({ name: itemKey, value: itemValue });\r\n                } else if (typeof itemValue === 'string') {\r\n                    dataItems.push({ name: itemKey, value: itemValue });\r\n                }\r\n            }\r\n        }\r\n\r\n        return {\r\n            keyItems: keyItems,\r\n            dataItems: dataItems\r\n        };\r\n    }\r\n\r\n    private traverse(keyItems: NameValuePair[], indent: number): void {\r\n        const indentSpace = '    ';\r\n        let indentName = '';\r\n        for (let i = 0; i < indent; i++) {\r\n            indentName += indentSpace;\r\n        }\r\n\r\n        const indentValue: string = indentName + indentSpace;\r\n        if (keyItems.length > 0) {\r\n            for (const item of keyItems) {\r\n                if (indent === 0) {\r\n                    this.outputDefinition.push(ResJsonConverter.openContent);\r\n                    this.outputTypescript.push(ResJsonConverter.openContent);\r\n                    this.outputInterface.push(ResJsonConverter.openContent);\r\n                    this.outputDefinition.push('export declare module ' + item.name + ' {\\r\\n');\r\n                    this.outputTypescript.push('export module ' + item.name + ' {\\r\\n    \\'use strict\\';\\r\\n');\r\n                    this.outputInterface.push('export interface ' + item.name + ' {\\r\\n');\r\n                } else {\r\n                    this.outputDefinition.push(indentName + 'module ' + item.name + ' {\\r\\n');\r\n                    this.outputTypescript.push(indentName + 'export module ' + item.name + ' {\\r\\n');\r\n                    this.outputInterface.push(indentName + item.name + ': {\\r\\n');\r\n                }\r\n\r\n                const jsonOld = this.jsonNewValue(item.name);\r\n                const results = this.scan(item.value);\r\n                for (const item2 of results.dataItems) {\r\n                    this.outputDefinition.push(indentValue + 'const ' + item2.name + ': string;\\r\\n');\r\n                    this.outputTypescript.push(indentValue + 'export const ' + item2.name + ' = \\'' + item2.value + '\\';\\r\\n');\r\n                    this.outputInterface.push(indentValue + item2.name + ': string;\\r\\n');\r\n                    this.jsonAddValue(item2.name, item2.value);\r\n                }\r\n\r\n                this.traverse(results.keyItems, ++indent);\r\n                this.jsonCurrent = jsonOld;\r\n\r\n                this.outputDefinition.push(indentName + '}\\r\\n');\r\n                this.outputTypescript.push(indentName + '}\\r\\n');\r\n                this.outputInterface.push(indentName + '};\\r\\n');\r\n            }\r\n        }\r\n    }\r\n}\r\n"]}