1082815dcSEvan Bacon"use strict";
2082815dcSEvan Bacon
3082815dcSEvan BaconObject.defineProperty(exports, "__esModule", {
4082815dcSEvan Bacon  value: true
5082815dcSEvan Bacon});
6*ed3bd27bSEvan Baconexports._processAndroidXML = _processAndroidXML;
7082815dcSEvan Baconexports.escapeAndroidString = escapeAndroidString;
8082815dcSEvan Baconexports.format = format;
9082815dcSEvan Baconexports.parseXMLAsync = parseXMLAsync;
10082815dcSEvan Baconexports.readXMLAsync = readXMLAsync;
11082815dcSEvan Baconexports.unescapeAndroidString = unescapeAndroidString;
12082815dcSEvan Baconexports.writeXMLAsync = writeXMLAsync;
13082815dcSEvan Baconfunction _fs() {
14082815dcSEvan Bacon  const data = _interopRequireDefault(require("fs"));
15082815dcSEvan Bacon  _fs = function () {
16082815dcSEvan Bacon    return data;
17082815dcSEvan Bacon  };
18082815dcSEvan Bacon  return data;
19082815dcSEvan Bacon}
20082815dcSEvan Baconfunction _os() {
21082815dcSEvan Bacon  const data = require("os");
22082815dcSEvan Bacon  _os = function () {
23082815dcSEvan Bacon    return data;
24082815dcSEvan Bacon  };
25082815dcSEvan Bacon  return data;
26082815dcSEvan Bacon}
27082815dcSEvan Baconfunction _path() {
28082815dcSEvan Bacon  const data = _interopRequireDefault(require("path"));
29082815dcSEvan Bacon  _path = function () {
30082815dcSEvan Bacon    return data;
31082815dcSEvan Bacon  };
32082815dcSEvan Bacon  return data;
33082815dcSEvan Bacon}
34082815dcSEvan Baconfunction _xml2js() {
35082815dcSEvan Bacon  const data = require("xml2js");
36082815dcSEvan Bacon  _xml2js = function () {
37082815dcSEvan Bacon    return data;
38082815dcSEvan Bacon  };
39082815dcSEvan Bacon  return data;
40082815dcSEvan Bacon}
41082815dcSEvan Baconfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
42082815dcSEvan Baconasync function writeXMLAsync(options) {
43082815dcSEvan Bacon  const xml = format(options.xml);
44082815dcSEvan Bacon  await _fs().default.promises.mkdir(_path().default.dirname(options.path), {
45082815dcSEvan Bacon    recursive: true
46082815dcSEvan Bacon  });
47082815dcSEvan Bacon  await _fs().default.promises.writeFile(options.path, xml);
48082815dcSEvan Bacon}
49082815dcSEvan Baconasync function readXMLAsync(options) {
50082815dcSEvan Bacon  let contents = '';
51082815dcSEvan Bacon  try {
52082815dcSEvan Bacon    contents = await _fs().default.promises.readFile(options.path, {
53082815dcSEvan Bacon      encoding: 'utf8',
54082815dcSEvan Bacon      flag: 'r'
55082815dcSEvan Bacon    });
56ee216927STomasz Sapeta  } catch {
57ee216927STomasz Sapeta    // catch and use fallback
58082815dcSEvan Bacon  }
59082815dcSEvan Bacon  const parser = new (_xml2js().Parser)();
60ee216927STomasz Sapeta  const manifest = await parser.parseStringPromise(contents || options.fallback || '');
61*ed3bd27bSEvan Bacon  return _processAndroidXML(manifest);
62*ed3bd27bSEvan Bacon}
63*ed3bd27bSEvan Baconfunction _processAndroidXML(manifest) {
64*ed3bd27bSEvan Bacon  var _manifest$resources;
65ee216927STomasz Sapeta  // For strings.xml
66082815dcSEvan Bacon  if (Array.isArray(manifest === null || manifest === void 0 ? void 0 : (_manifest$resources = manifest.resources) === null || _manifest$resources === void 0 ? void 0 : _manifest$resources.string)) {
67082815dcSEvan Bacon    for (const string of manifest === null || manifest === void 0 ? void 0 : (_manifest$resources2 = manifest.resources) === null || _manifest$resources2 === void 0 ? void 0 : _manifest$resources2.string) {
68082815dcSEvan Bacon      var _manifest$resources2;
69082815dcSEvan Bacon      if (string.$.translatable === 'false' || string.$.translatable === false) {
70082815dcSEvan Bacon        continue;
71082815dcSEvan Bacon      }
72082815dcSEvan Bacon      string._ = unescapeAndroidString(string._);
73082815dcSEvan Bacon    }
74082815dcSEvan Bacon  }
75082815dcSEvan Bacon  return manifest;
76082815dcSEvan Bacon}
77082815dcSEvan Baconasync function parseXMLAsync(contents) {
78082815dcSEvan Bacon  const xml = await new (_xml2js().Parser)().parseStringPromise(contents);
79082815dcSEvan Bacon  return xml;
80082815dcSEvan Bacon}
81082815dcSEvan Baconconst stringTimesN = (n, char) => Array(n + 1).join(char);
82082815dcSEvan Baconfunction format(manifest, {
83082815dcSEvan Bacon  indentLevel = 2,
84082815dcSEvan Bacon  newline = _os().EOL
85082815dcSEvan Bacon} = {}) {
86082815dcSEvan Bacon  let xmlInput;
87082815dcSEvan Bacon  if (typeof manifest === 'string') {
88082815dcSEvan Bacon    xmlInput = manifest;
89082815dcSEvan Bacon  } else if (manifest.toString) {
90082815dcSEvan Bacon    var _manifest$resources3;
91082815dcSEvan Bacon    const builder = new (_xml2js().Builder)({
92082815dcSEvan Bacon      headless: true
93ee216927STomasz Sapeta    });
94082815dcSEvan Bacon
95ee216927STomasz Sapeta    // For strings.xml
96082815dcSEvan Bacon    if (Array.isArray(manifest === null || manifest === void 0 ? void 0 : (_manifest$resources3 = manifest.resources) === null || _manifest$resources3 === void 0 ? void 0 : _manifest$resources3.string)) {
97082815dcSEvan Bacon      for (const string of manifest === null || manifest === void 0 ? void 0 : (_manifest$resources4 = manifest.resources) === null || _manifest$resources4 === void 0 ? void 0 : _manifest$resources4.string) {
98082815dcSEvan Bacon        var _manifest$resources4;
99082815dcSEvan Bacon        if (string.$.translatable === 'false' || string.$.translatable === false) {
100082815dcSEvan Bacon          continue;
101082815dcSEvan Bacon        }
102082815dcSEvan Bacon        string._ = escapeAndroidString(string._);
103082815dcSEvan Bacon      }
104082815dcSEvan Bacon    }
105082815dcSEvan Bacon    xmlInput = builder.buildObject(manifest);
106082815dcSEvan Bacon    return xmlInput;
107082815dcSEvan Bacon  } else {
108082815dcSEvan Bacon    throw new Error(`Invalid XML value passed in: ${manifest}`);
109082815dcSEvan Bacon  }
110082815dcSEvan Bacon  const indentString = stringTimesN(indentLevel, ' ');
111082815dcSEvan Bacon  let formatted = '';
112082815dcSEvan Bacon  const regex = /(>)(<)(\/*)/g;
113082815dcSEvan Bacon  const xml = xmlInput.replace(regex, `$1${newline}$2$3`);
114082815dcSEvan Bacon  let pad = 0;
115082815dcSEvan Bacon  xml.split(/\r?\n/).map(line => line.trim()).forEach(line => {
116082815dcSEvan Bacon    let indent = 0;
117082815dcSEvan Bacon    if (line.match(/.+<\/\w[^>]*>$/)) {
118082815dcSEvan Bacon      indent = 0;
119082815dcSEvan Bacon    } else if (line.match(/^<\/\w/)) {
120082815dcSEvan Bacon      if (pad !== 0) {
121082815dcSEvan Bacon        pad -= 1;
122082815dcSEvan Bacon      }
123082815dcSEvan Bacon    } else if (line.match(/^<\w([^>]*[^/])?>.*$/)) {
124082815dcSEvan Bacon      indent = 1;
125082815dcSEvan Bacon    } else {
126082815dcSEvan Bacon      indent = 0;
127082815dcSEvan Bacon    }
128082815dcSEvan Bacon    const padding = stringTimesN(pad, indentString);
129082815dcSEvan Bacon    formatted += padding + line + newline;
130082815dcSEvan Bacon    pad += indent;
131082815dcSEvan Bacon  });
132082815dcSEvan Bacon  return formatted.trim();
133082815dcSEvan Bacon}
134ee216927STomasz Sapeta
135082815dcSEvan Bacon/**
136082815dcSEvan Bacon * Escapes Android string literals, specifically characters `"`, `'`, `\`, `\n`, `\r`, `\t`
137082815dcSEvan Bacon *
138082815dcSEvan Bacon * @param value unescaped Android XML string literal.
139082815dcSEvan Bacon */
140082815dcSEvan Baconfunction escapeAndroidString(value) {
141082815dcSEvan Bacon  value = value.replace(/[\n\r\t'"@]/g, m => {
142082815dcSEvan Bacon    switch (m) {
143082815dcSEvan Bacon      case '"':
144082815dcSEvan Bacon      case "'":
145082815dcSEvan Bacon      case '@':
146082815dcSEvan Bacon        return '\\' + m;
147082815dcSEvan Bacon      case '\n':
148082815dcSEvan Bacon        return '\\n';
149082815dcSEvan Bacon      case '\r':
150082815dcSEvan Bacon        return '\\r';
151082815dcSEvan Bacon      case '\t':
152082815dcSEvan Bacon        return '\\t';
153082815dcSEvan Bacon      default:
154082815dcSEvan Bacon        throw new Error(`Cannot escape unhandled XML character: ${m}`);
155082815dcSEvan Bacon    }
156082815dcSEvan Bacon  });
157082815dcSEvan Bacon  if (value.match(/(^\s|\s$)/)) {
158082815dcSEvan Bacon    value = '"' + value + '"';
159082815dcSEvan Bacon  }
160082815dcSEvan Bacon  return value;
161082815dcSEvan Bacon}
162082815dcSEvan Baconfunction unescapeAndroidString(value) {
163082815dcSEvan Bacon  return value.replace(/\\(.)/g, '$1');
164082815dcSEvan Bacon}
165082815dcSEvan Bacon//# sourceMappingURL=XML.js.map