UNPKG

@jinntec/jinn-codemirror

Version:

Source code editor component based on codemirror with language support for XML and Leiden+

210 lines (204 loc) 7.49 kB
function transformElem(elem: Element, output: string[]) { for (let i = 0; i < elem.childNodes.length; i++) { transform(elem.childNodes[i], output); } } function transform(node: Node|null, output: string[]) { if (!node) { return; } switch (node.nodeType) { case Node.DOCUMENT_NODE: case Node.DOCUMENT_FRAGMENT_NODE: transform((<DocumentFragment>node).firstElementChild, output); break; case Node.ELEMENT_NODE: const elem = <Element>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('〚'); transformElem(elem, output); output.push('〛'); 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>\n`); 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(0x0323); } } 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: Element, output: string[]) { 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: Element, output: string[]) { 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; } } } export function xml2leidenPlus(root: Node): string { if (!(root instanceof Element)) { return ''; } const output:string[] = []; let columnBreaks = root.querySelectorAll('cb'); if (columnBreaks.length > 0) { root = root.cloneNode(true); columnBreaks = (<Element>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(''); }