abapmerge
Version:
Merge ABAP INCLUDEs into single file
276 lines • 12.7 kB
JavaScript
;
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable @typescript-eslint/no-unused-vars */
var file_list_1 = __importDefault(require("./file_list"));
var file_1 = __importDefault(require("./file"));
var fast_xml_parser_1 = require("fast-xml-parser");
var PragmaProcessor = /** @class */ (function () {
function PragmaProcessor(files, opts) {
this.files = files;
this.opts = opts || {};
}
PragmaProcessor.process = function (files, opts) {
var instance = new PragmaProcessor(files, opts);
return instance.processFiles();
};
PragmaProcessor.prototype.processFiles = function () {
var e_1, _a, e_2, _b;
var newFiles = new file_list_1.default();
try {
for (var _c = __values(this.files), _d = _c.next(); !_d.done; _d = _c.next()) {
var file = _d.value;
if (file.isBinary() || !file.isABAP()) {
newFiles.push(file);
continue;
}
var lines = file.getContents().split("\n");
var hasPragma = false;
var output = [];
try {
for (var lines_1 = (e_2 = void 0, __values(lines)), lines_1_1 = lines_1.next(); !lines_1_1.done; lines_1_1 = lines_1.next()) {
var line = lines_1_1.value;
var pragma = line.match(/^(\*|(\s*)")\s*@@abapmerge\s+(.+)/i);
if (pragma) {
var pragmaCmd = pragma[3];
var indent = (pragma[1] === "*") ? "" : pragma[2];
var processed = this.processPragma(indent, pragmaCmd);
if (processed && processed.length > 0) {
hasPragma = true;
output.push.apply(output, __spreadArray([], __read(processed), false));
}
else {
output.push(line);
}
}
else {
output.push(line);
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (lines_1_1 && !lines_1_1.done && (_b = lines_1.return)) _b.call(lines_1);
}
finally { if (e_2) throw e_2.error; }
}
newFiles.push(hasPragma
? new file_1.default(file.getFilename(), output.join("\n"))
: file);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_1) throw e_1.error; }
}
return newFiles;
};
PragmaProcessor.prototype.comment = function (name) {
return this.opts.noComments
? []
: [
"****************************************************",
"* abapmerge Pragma [".concat(this.currentPragmaName, "] - ").concat(name.toUpperCase()),
"****************************************************",
];
};
PragmaProcessor.prototype.processPragma = function (indent, pragma) {
/* pragmas has the following format
* @@abapmerge command params
* if written as " comment, then indentation before " is also used for output
* Currently supported pragmas:
* - include {filename} > {string wrapper}
* {filename} - path to the file relative to script execution dir (argv[0])
* {string wrapper} is a pattern where $$ is replaced by the include line
* $$ is escaped - ' replaced to '' (to fit in abap string), use $$$ to avoid escaping
* e.g. include somestyle.css > APPEND '$$' TO styletab.
* - include-cua { filaname.xml } > { variable }
* parse xml file, find CUA node and convert it to `variable`
* zcl_abapgit_objects_program=>ty_cua type is expected for the var
*/
var result = [];
var cmdMatch = pragma.match(/(\S+)\s+(.*)/);
if (!cmdMatch)
return null;
var command = cmdMatch[1].toLowerCase();
var commandParams = cmdMatch[2];
this.currentPragmaName = command; // hack for `comment()`
switch (command) {
case "include":
result.push.apply(result, __spreadArray([], __read(this.pragmaInclude(indent, commandParams)), false));
break;
case "include-base64":
result.push.apply(result, __spreadArray([], __read(this.pragmaIncludeBase64(indent, commandParams)), false));
break;
case "include-cua":
result.push.apply(result, __spreadArray([], __read(this.pragmaIncludeCua(indent, commandParams)), false));
break;
default: break;
}
return result;
};
PragmaProcessor.prototype.pragmaInclude = function (indent, includeParams) {
var params = includeParams.match(/(\S+)\s*>\s*(.*)/i);
if (!params)
return [];
var filename = params[1];
var template = params[2];
var lines = this.files.otherByName(filename).getContents().split("\n");
if (lines.length > 0 && !lines[lines.length - 1]) {
lines.pop(); // remove empty string
}
var result = [];
result.push.apply(result, __spreadArray([], __read(this.comment(filename)), false));
result.push.apply(result, __spreadArray([], __read(lines.map(function (line) {
var render = template.replace("$$$", line); // unescaped
render = render.replace("$$", line.replace(/'/g, "''")); // escape ' -> ''
return indent + render;
})), false));
return result;
};
PragmaProcessor.prototype.pragmaIncludeBase64 = function (indent, includeParams) {
var params = includeParams.match(/(\S+)\s*>\s*(.*)/i);
if (!params)
return [];
var filename = params[1];
var template = params[2];
var lines = this.files.otherByName(filename)
.getBlob()
.toString("base64")
.match(/.{1,60}/g);
if (!lines || lines.length === 0)
return [];
return __spreadArray(__spreadArray([], __read(this.comment(filename)), false), __read(lines.map(function (line) { return indent + template.replace(/\${2,3}/, line); })), false);
};
PragmaProcessor.prototype.pragmaIncludeCua = function (indent, includeParams) {
var params = includeParams.trim().match(/(\S+)\s*>\s*(\S+)/i);
if (!params)
return [];
var filename = params[1];
var varName = params[2];
if (!/\.xml$/i.test(filename))
return [];
var xml = this.files.otherByName(filename).getContents();
var lines = new CuaConverter().convert(xml, varName);
if (!lines || lines.length === 0)
return [];
return __spreadArray(__spreadArray([], __read(this.comment(filename)), false), __read(lines.map(function (i) { return indent + i; })), false);
};
return PragmaProcessor;
}());
exports.default = PragmaProcessor;
var CuaConverter = /** @class */ (function () {
function CuaConverter() {
}
CuaConverter.prototype.convert = function (xml, varName) {
var e_3, _a;
var _b, _c, _d;
var parser = new fast_xml_parser_1.XMLParser({
ignoreAttributes: true,
numberParseOptions: { leadingZeros: false, hex: true }, // to keep leading zeros
isArray: function (_name, jpath, _isLeafNode, _isAttribute) {
// single item tables are still arrays (all but ADM branch)
if (!jpath.startsWith("abapGit.asx:abap.asx:values.CUA."))
return false;
var path = jpath.split(".");
if (path.length !== 6)
return false;
if (path[4] === "ADM")
return false; // flat structure
return true;
},
});
var parsed = parser.parse(xml);
if (!parsed)
throw Error("CuaConverter: XML parsing error");
var cua = (_d = (_c = (_b = parsed === null || parsed === void 0 ? void 0 : parsed.abapGit) === null || _b === void 0 ? void 0 : _b["asx:abap"]) === null || _c === void 0 ? void 0 : _c["asx:values"]) === null || _d === void 0 ? void 0 : _d.CUA;
if (!cua)
return null; // cua is not found - nothing to convert but not an exception
var defs = [];
var code = [];
// eslint-disable-next-line guard-for-in
for (var key in cua) {
var node = cua[key];
key = key.toLowerCase();
if (key === "adm") {
code.push.apply(code, __spreadArray([], __read(this.fillStruc("".concat(varName, "-adm"), node)), false));
}
else {
var itemName = "ls_".concat(key);
defs.push("DATA ".concat(itemName, " LIKE LINE OF ").concat(varName, "-").concat(key, "."));
var attrs = Object.keys(node);
if (attrs.length !== 1)
throw Error("CuaConverter: unexpected structure of [".concat(key, "] node"));
node = node[attrs[0]];
if (!Array.isArray(node))
throw Error("CuaConverter: unexpected structure of [".concat(key, "/").concat(attrs[0], "] node"));
try {
for (var node_1 = (e_3 = void 0, __values(node)), node_1_1 = node_1.next(); !node_1_1.done; node_1_1 = node_1.next()) {
var itemData = node_1_1.value;
code.push("CLEAR ".concat(itemName, "."));
code.push.apply(code, __spreadArray([], __read(this.fillStruc(itemName, itemData)), false));
code.push("APPEND ".concat(itemName, " TO ").concat(varName, "-").concat(key, "."));
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (node_1_1 && !node_1_1.done && (_a = node_1.return)) _a.call(node_1);
}
finally { if (e_3) throw e_3.error; }
}
}
}
return __spreadArray(__spreadArray([], __read(defs), false), __read(code), false);
};
CuaConverter.prototype.fillStruc = function (varName, obj) {
return __spreadArray([], __read(Object.entries(obj)), false).map(function (_a) {
var _b = __read(_a, 2), key = _b[0], val = _b[1];
return "".concat(varName, "-").concat(key.toLowerCase(), " = '").concat(val, "'.");
});
};
return CuaConverter;
}());
//# sourceMappingURL=pragma.js.map