gpml2pvjson
Version:
convert GPML (XML) to pvjson (json)
133 lines (132 loc) • 11 kB
JavaScript
import "source-map-support/register";
// TODO should I get rid of source-map-support/register for production build for browser?
// TODO most or all of this should go into the xpath branch of @wikipathways/cxml.
// Decide on an API and then merge most or all this code into there.
//
// TODO why does TS require that we use the Pathway's "constructor.prototype"
// instead of just the Pathway?
// Why does Pathway.Graphics not need that?
// Why do many of the other require using the prototype?
//
//// TODO why do we get an error with this (/Pathway/@* before /Pathway):
//"/Pathway/@*": GPML2013a.document.Pathway.constructor.prototype,
//"/Pathway": GPML2013a.document.Pathway.constructor.prototype,
//// And with this, we don't get an error, but nothing comes out (/Pathway before /Pathway/@*):
//"/Pathway": GPML2013a.document.Pathway.constructor.prototype,
//"/Pathway/@*": GPML2013a.document.Pathway.constructor.prototype,
import { cloneDeep, curry, keys, partition, toPairs } from "lodash/fp";
import * as hl from "highland";
import * as cxml from "@wikipathways/cxml";
// TODO don't use this regex when we are already also using a nice
// xpath expression parser in the xpath branch of cxml
const ATTR_SELECTOR_REGEX = /\/@(\*|([:A-Za-z_][:\w\-\.]*))$/;
function getSelectorLevel(selector) {
return selector.replace(ATTR_SELECTOR_REGEX, "").split("/").length - 1;
}
const nestedElementsToSelector = curry(function (commonLevel, nestedElements) {
return nestedElements.slice(0, commonLevel).join("/");
});
function getSelectorNestedElements(selector) {
return selector.replace(ATTR_SELECTOR_REGEX, "").split("/");
}
export class CXMLXPath {
constructor(inputStream, schema, xpathNamespaceTbl = { "": "" }) {
this._parser = new cxml.Parser(xpathNamespaceTbl);
this._schema = schema;
this._inputStream = inputStream;
}
parse(selectorToCXML) {
const inputStream = this._inputStream;
const parser = this._parser;
const schema = this._schema;
const result = toPairs(selectorToCXML).reduce(function ({ output, runningSelectors }, [selector, schemaElement]) {
const outputStream = hl();
const useBefore = selector.match(ATTR_SELECTOR_REGEX);
parser.attach(class CustomHandler extends schemaElement.constructor {
_before() {
if (useBefore) {
outputStream.write(cloneDeep(this));
}
}
_after() {
if (!useBefore) {
outputStream.write(cloneDeep(this));
}
}
}, selector);
output[selector] = outputStream;
const level = getSelectorLevel(selector);
const selectorNestedElements = getSelectorNestedElements(selector);
const [selectorsToEnd, stillRunningSelectors] = partition(function (runningSelector) {
const runningSelectorNestedElements = getSelectorNestedElements(runningSelector);
const commonNestedElementsToSelector = nestedElementsToSelector(Math.min(selectorNestedElements.length, runningSelectorNestedElements.length));
return (commonNestedElementsToSelector(runningSelectorNestedElements) !==
commonNestedElementsToSelector(selectorNestedElements));
}, runningSelectors);
selectorsToEnd.forEach(function (runningSelector) {
const runningStream = output[runningSelector];
outputStream
.observe()
.head()
.each(function (x) {
runningStream.end();
});
});
// NOTE: redefining this variable
runningSelectors = stillRunningSelectors.concat([selector]);
return { output, runningSelectors };
}, { output: {}, runningSelectors: [] });
const streamMapBySelector = result.output;
const finalRunningSelectors = result.runningSelectors;
const selectors = keys(selectorToCXML);
parser.parse(inputStream, schema.document).then(function (Pathway) {
finalRunningSelectors.forEach(function (finalRunningSelector) {
streamMapBySelector[finalRunningSelector].end();
});
selectors.forEach(function (selector) {
const thisStream = streamMapBySelector[selector];
if (!thisStream["ended"]) {
//console.log(streamMapBySelector[selector]);
//console.log(`Failed to end stream for ${selector}. See above.`);
//throw new Error(`Failed to end stream for ${selector}. See above.`);
thisStream.end();
/*
(thisStream._observers.length === 0
? thisStream
: thisStream.observe())
.debounce(17)
.each(function() {
thisStream.end();
});
//*/
}
});
}, function (err) {
throw err;
});
/*
streamMapBySelector.startCXML = function() {
return hl(parser.parse(inputStream, schema.document)).map(function(
Pathway
) {
console.log("Pathway");
console.log(Pathway);
finalRunningSelectors.forEach(function(finalRunningSelector) {
streamMapBySelector[finalRunningSelector].end();
});
selectors.forEach(function(selector) {
const thisStream = streamMapBySelector[selector];
if (!thisStream["ended"]) {
//console.log(streamMapBySelector[selector]);
console.log(`Failed to end stream for ${selector}. See above.`);
//throw new Error(`Failed to end stream for ${selector}. See above.`);
//thisStream.end();
}
});
});
};
//*/
return streamMapBySelector;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3htbC14cGF0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zcGlub2Zmcy9jeG1sLXhwYXRoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sNkJBQTZCLENBQUM7QUFDckMseUZBQXlGO0FBRXpGLGtGQUFrRjtBQUNsRixvRUFBb0U7QUFDcEUsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSwrQkFBK0I7QUFDL0IsMkNBQTJDO0FBQzNDLHdEQUF3RDtBQUN4RCxFQUFFO0FBQ0YseUVBQXlFO0FBQ3pFLGtFQUFrRTtBQUNsRSwrREFBK0Q7QUFDL0QsK0ZBQStGO0FBQy9GLCtEQUErRDtBQUMvRCxrRUFBa0U7QUFFbEUsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDdkUsT0FBTyxLQUFLLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFL0IsT0FBTyxLQUFLLElBQUksTUFBTSxvQkFBb0IsQ0FBQztBQXVCM0Msa0VBQWtFO0FBQ2xFLHNEQUFzRDtBQUN0RCxNQUFNLG1CQUFtQixHQUFHLGlDQUFpQyxDQUFDO0FBRTlELFNBQVMsZ0JBQWdCLENBQUMsUUFBUTtJQUNoQyxPQUFPLFFBQVEsQ0FBQyxPQUFPLENBQUMsbUJBQW1CLEVBQUUsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7QUFDekUsQ0FBQztBQUVELE1BQU0sd0JBQXdCLEdBQUcsS0FBSyxDQUFDLFVBQVMsV0FBVyxFQUFFLGNBQWM7SUFDekUsT0FBTyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDeEQsQ0FBQyxDQUFDLENBQUM7QUFFSCxTQUFTLHlCQUF5QixDQUFDLFFBQVE7SUFDekMsT0FBTyxRQUFRLENBQUMsT0FBTyxD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