1{"version":3,"file":"XML.js","names":["writeXMLAsync","options","xml","format","fs","promises","mkdir","path","dirname","recursive","writeFile","readXMLAsync","contents","readFile","encoding","flag","parser","Parser","manifest","parseStringPromise","fallback","Array","isArray","resources","string","$","translatable","_","unescapeAndroidString","parseXMLAsync","stringTimesN","n","char","join","indentLevel","newline","EOL","xmlInput","toString","builder","Builder","headless","escapeAndroidString","buildObject","Error","indentString","formatted","regex","replace","pad","split","map","line","trim","forEach","indent","match","padding","value","m"],"sources":["../../src/utils/XML.ts"],"sourcesContent":["import fs from 'fs';\nimport { EOL } from 'os';\nimport path from 'path';\nimport { Builder, Parser } from 'xml2js';\n\nexport type XMLValue = boolean | number | string | null | XMLArray | XMLObject;\n\nexport interface XMLArray extends Array<XMLValue> {}\n\nexport interface XMLObject {\n [key: string]: XMLValue | undefined;\n}\n\nexport async function writeXMLAsync(options: { path: string; xml: any }): Promise<void> {\n const xml = format(options.xml);\n await fs.promises.mkdir(path.dirname(options.path), { recursive: true });\n await fs.promises.writeFile(options.path, xml);\n}\n\nexport async function readXMLAsync(options: {\n path: string;\n fallback?: string | null;\n}): Promise<XMLObject> {\n let contents: string = '';\n try {\n contents = await fs.promises.readFile(options.path, { encoding: 'utf8', flag: 'r' });\n } catch {\n // catch and use fallback\n }\n const parser = new Parser();\n const manifest = await parser.parseStringPromise(contents || options.fallback || '');\n\n // For strings.xml\n if (Array.isArray(manifest?.resources?.string)) {\n for (const string of manifest?.resources?.string) {\n if (string.$.translatable === 'false' || string.$.translatable === false) {\n continue;\n }\n string._ = unescapeAndroidString(string._);\n }\n }\n\n return manifest;\n}\n\nexport async function parseXMLAsync(contents: string): Promise<XMLObject> {\n const xml = await new Parser().parseStringPromise(contents);\n return xml;\n}\n\nconst stringTimesN = (n: number, char: string) => Array(n + 1).join(char);\n\nexport function format(manifest: any, { indentLevel = 2, newline = EOL } = {}): string {\n let xmlInput: string;\n if (typeof manifest === 'string') {\n xmlInput = manifest;\n } else if (manifest.toString) {\n const builder = new Builder({\n headless: true,\n });\n\n // For strings.xml\n if (Array.isArray(manifest?.resources?.string)) {\n for (const string of manifest?.resources?.string) {\n if (string.$.translatable === 'false' || string.$.translatable === false) {\n continue;\n }\n string._ = escapeAndroidString(string._);\n }\n }\n\n xmlInput = builder.buildObject(manifest);\n\n return xmlInput;\n } else {\n throw new Error(`Invalid XML value passed in: ${manifest}`);\n }\n const indentString = stringTimesN(indentLevel, ' ');\n\n let formatted = '';\n const regex = /(>)(<)(\\/*)/g;\n const xml = xmlInput.replace(regex, `$1${newline}$2$3`);\n let pad = 0;\n xml\n .split(/\\r?\\n/)\n .map((line: string) => line.trim())\n .forEach((line: string) => {\n let indent = 0;\n if (line.match(/.+<\\/\\w[^>]*>$/)) {\n indent = 0;\n } else if (line.match(/^<\\/\\w/)) {\n if (pad !== 0) {\n pad -= 1;\n }\n } else if (line.match(/^<\\w([^>]*[^/])?>.*$/)) {\n indent = 1;\n } else {\n indent = 0;\n }\n\n const padding = stringTimesN(pad, indentString);\n formatted += padding + line + newline;\n pad += indent;\n });\n\n return formatted.trim();\n}\n\n/**\n * Escapes Android string literals, specifically characters `\"`, `'`, `\\`, `\\n`, `\\r`, `\\t`\n *\n * @param value unescaped Android XML string literal.\n */\nexport function escapeAndroidString(value: string): string {\n value = value.replace(/[\\n\\r\\t'\"@]/g, (m) => {\n switch (m) {\n case '\"':\n case \"'\":\n case '@':\n return '\\\\' + m;\n case '\\n':\n return '\\\\n';\n case '\\r':\n return '\\\\r';\n case '\\t':\n return '\\\\t';\n default:\n throw new Error(`Cannot escape unhandled XML character: ${m}`);\n }\n });\n if (value.match(/(^\\s|\\s$)/)) {\n value = '\"' + value + '\"';\n }\n return value;\n}\n\nexport function unescapeAndroidString(value: string): string {\n return value.replace(/\\\\(.)/g, '$1');\n}\n"],"mappings":"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"}