@jinntec/jinn-codemirror
Version:
Source code editor component based on codemirror with language support for XML and Leiden+
209 lines (208 loc) • 5.78 kB
JavaScript
function transformElem(elem, output) {
for (let i = 0; i < elem.childNodes.length; i++) {
transform(elem.childNodes[i], output);
}
}
function transform(node, output) {
if (!node) {
return;
}
switch (node.nodeType) {
case Node.DOCUMENT_NODE:
case Node.DOCUMENT_FRAGMENT_NODE:
transform(node.firstElementChild, output);
break;
case Node.ELEMENT_NODE:
const elem = node;
let n;
switch (elem.localName) {
case "ab":
output.push("<=");
transformElem(elem, output);
output.push("=>");
break;
case "abbr":
output.push("(|");
transformElem(elem, output);
output.push("|)");
break;
case "del":
output.push("\u301A");
transformElem(elem, output);
output.push("\u301B");
break;
case "div":
n = elem.getAttribute("n");
const subtype = elem.getAttribute("subtype");
switch (subtype) {
case "column":
output.push(`<D=.${n}.column`);
break;
case "part":
output.push(`<D=.${n}.part`);
break;
default:
output.push(`<D=.${n}`);
break;
}
transformElem(elem, output);
output.push(`=D>
`);
break;
case "expan":
case "ex":
const cert = elem.getAttribute("cert");
output.push("(");
transformElem(elem, output);
if (cert === "low") {
output.push("?");
}
output.push(")");
break;
case "gap":
transformGap(elem, output);
break;
case "lb":
n = elem.getAttribute("n");
if (output.length > 0 && !/\n+$/.test(output[output.length - 1])) {
output.push("\n");
}
const breakAttr = elem.getAttribute("break");
output.push(`${n}.${breakAttr === "no" ? "- " : " "}`);
break;
case "supplied":
transformSupplied(elem, output);
break;
case "unclear":
const content = elem.textContent || "";
let contentOut = "";
for (let i = 0; i < content.length; i++) {
const codepoint = content.codePointAt(i);
if (codepoint) {
contentOut += String.fromCodePoint(codepoint);
contentOut += String.fromCodePoint(803);
}
}
output.push(contentOut);
break;
case "foreign":
output.push("~|");
transformElem(elem, output);
output.push(`|~${elem.getAttribute("xml:lang")}`);
break;
default:
throw new Error(`Cannot transform element ${elem.localName} to Leiden`);
break;
}
break;
case Node.TEXT_NODE:
output.push(node.nodeValue || "");
break;
}
}
function transformGap(elem, output) {
const unit = elem.getAttribute("unit");
const quantity = elem.getAttribute("quantity");
const reason = elem.getAttribute("reason");
if (reason) {
switch (reason) {
case "lost":
switch (unit) {
case "character":
if (quantity) {
output.push(`[.${quantity}]`);
} else {
output.push("[.?]");
}
break;
case "line":
if (quantity) {
output.push(`lost.${quantity}lin`);
} else {
output.push("lost.?lin");
}
break;
}
break;
case "illegible":
switch (unit) {
case "character":
if (quantity) {
output.push(`.${quantity}`);
} else {
output.push(".?");
}
break;
case "line":
if (quantity) {
output.push(`.${quantity}lin`);
}
break;
}
break;
}
}
}
function transformSupplied(elem, output) {
const reason = elem.getAttribute("reason");
if (reason) {
const cert = elem.getAttribute("cert");
switch (reason) {
case "omitted":
output.push("<");
transformElem(elem, output);
if (cert && cert === "low") {
output.push("(?)");
}
output.push(">");
break;
case "lost":
default:
output.push("[");
transformElem(elem, output);
if (cert && cert === "low") {
output.push("(?)");
}
output.push("]");
break;
}
}
}
function xml2leidenPlus(root) {
if (!(root instanceof Element)) {
return "";
}
const output = [];
let columnBreaks = root.querySelectorAll("cb");
if (columnBreaks.length > 0) {
root = root.cloneNode(true);
columnBreaks = root.querySelectorAll("cb");
for (let i = 0; i <= columnBreaks.length; i++) {
const range = document.createRange();
if (i === 0) {
range.setStart(root, 0);
} else {
range.setStartAfter(columnBreaks[i - 1]);
}
if (i === columnBreaks.length) {
root.lastChild && range.setEndAfter(root.lastChild);
} else {
range.setEndBefore(columnBreaks[i]);
}
const columnDiv = document.createElement("div");
columnDiv.setAttribute("type", "textpart");
columnDiv.setAttribute("subtype", "column");
columnDiv.setAttribute("n", (i + 1).toString());
const ab = document.createElement("ab");
columnDiv.appendChild(ab);
ab.appendChild(range.extractContents());
transform(columnDiv, output);
}
} else {
transform(root, output);
}
return output.join("");
}
export {
xml2leidenPlus
};