You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
4.8 KiB
199 lines
4.8 KiB
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.escapeAndroidString = escapeAndroidString;
|
|
exports.format = format;
|
|
exports.parseXMLAsync = parseXMLAsync;
|
|
exports.readXMLAsync = readXMLAsync;
|
|
exports.unescapeAndroidString = unescapeAndroidString;
|
|
exports.writeXMLAsync = writeXMLAsync;
|
|
|
|
function _fs() {
|
|
const data = _interopRequireDefault(require("fs"));
|
|
|
|
_fs = function () {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _os() {
|
|
const data = require("os");
|
|
|
|
_os = function () {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _path() {
|
|
const data = _interopRequireDefault(require("path"));
|
|
|
|
_path = function () {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _xml2js() {
|
|
const data = require("xml2js");
|
|
|
|
_xml2js = function () {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
async function writeXMLAsync(options) {
|
|
const xml = format(options.xml);
|
|
await _fs().default.promises.mkdir(_path().default.dirname(options.path), {
|
|
recursive: true
|
|
});
|
|
await _fs().default.promises.writeFile(options.path, xml);
|
|
}
|
|
|
|
async function readXMLAsync(options) {
|
|
var _manifest$resources;
|
|
|
|
let contents = '';
|
|
|
|
try {
|
|
contents = await _fs().default.promises.readFile(options.path, {
|
|
encoding: 'utf8',
|
|
flag: 'r'
|
|
});
|
|
} catch {// catch and use fallback
|
|
}
|
|
|
|
const parser = new (_xml2js().Parser)();
|
|
const manifest = await parser.parseStringPromise(contents || options.fallback || ''); // For strings.xml
|
|
|
|
if (Array.isArray(manifest === null || manifest === void 0 ? void 0 : (_manifest$resources = manifest.resources) === null || _manifest$resources === void 0 ? void 0 : _manifest$resources.string)) {
|
|
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) {
|
|
var _manifest$resources2;
|
|
|
|
if (string.$.translatable === 'false' || string.$.translatable === false) {
|
|
continue;
|
|
}
|
|
|
|
string._ = unescapeAndroidString(string._);
|
|
}
|
|
}
|
|
|
|
return manifest;
|
|
}
|
|
|
|
async function parseXMLAsync(contents) {
|
|
const xml = await new (_xml2js().Parser)().parseStringPromise(contents);
|
|
return xml;
|
|
}
|
|
|
|
const stringTimesN = (n, char) => Array(n + 1).join(char);
|
|
|
|
function format(manifest, {
|
|
indentLevel = 2,
|
|
newline = _os().EOL
|
|
} = {}) {
|
|
let xmlInput;
|
|
|
|
if (typeof manifest === 'string') {
|
|
xmlInput = manifest;
|
|
} else if (manifest.toString) {
|
|
var _manifest$resources3;
|
|
|
|
const builder = new (_xml2js().Builder)({
|
|
headless: true
|
|
}); // For strings.xml
|
|
|
|
if (Array.isArray(manifest === null || manifest === void 0 ? void 0 : (_manifest$resources3 = manifest.resources) === null || _manifest$resources3 === void 0 ? void 0 : _manifest$resources3.string)) {
|
|
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) {
|
|
var _manifest$resources4;
|
|
|
|
if (string.$.translatable === 'false' || string.$.translatable === false) {
|
|
continue;
|
|
}
|
|
|
|
string._ = escapeAndroidString(string._);
|
|
}
|
|
}
|
|
|
|
xmlInput = builder.buildObject(manifest);
|
|
return xmlInput;
|
|
} else {
|
|
throw new Error(`Invalid XML value passed in: ${manifest}`);
|
|
}
|
|
|
|
const indentString = stringTimesN(indentLevel, ' ');
|
|
let formatted = '';
|
|
const regex = /(>)(<)(\/*)/g;
|
|
const xml = xmlInput.replace(regex, `$1${newline}$2$3`);
|
|
let pad = 0;
|
|
xml.split(/\r?\n/).map(line => line.trim()).forEach(line => {
|
|
let indent = 0;
|
|
|
|
if (line.match(/.+<\/\w[^>]*>$/)) {
|
|
indent = 0;
|
|
} else if (line.match(/^<\/\w/)) {
|
|
if (pad !== 0) {
|
|
pad -= 1;
|
|
}
|
|
} else if (line.match(/^<\w([^>]*[^/])?>.*$/)) {
|
|
indent = 1;
|
|
} else {
|
|
indent = 0;
|
|
}
|
|
|
|
const padding = stringTimesN(pad, indentString);
|
|
formatted += padding + line + newline;
|
|
pad += indent;
|
|
});
|
|
return formatted.trim();
|
|
}
|
|
/**
|
|
* Escapes Android string literals, specifically characters `"`, `'`, `\`, `\n`, `\r`, `\t`
|
|
*
|
|
* @param value unescaped Android XML string literal.
|
|
*/
|
|
|
|
|
|
function escapeAndroidString(value) {
|
|
value = value.replace(/[\n\r\t'"@]/g, m => {
|
|
switch (m) {
|
|
case '"':
|
|
case "'":
|
|
case '@':
|
|
return '\\' + m;
|
|
|
|
case '\n':
|
|
return '\\n';
|
|
|
|
case '\r':
|
|
return '\\r';
|
|
|
|
case '\t':
|
|
return '\\t';
|
|
|
|
default:
|
|
throw new Error(`Cannot escape unhandled XML character: ${m}`);
|
|
}
|
|
});
|
|
|
|
if (value.match(/(^\s|\s$)/)) {
|
|
value = '"' + value + '"';
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
function unescapeAndroidString(value) {
|
|
return value.replace(/\\(.)/g, '$1');
|
|
}
|
|
//# sourceMappingURL=XML.js.map
|