UNPKG

usfm-editor

Version:
234 lines (185 loc) 8.18 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.transformToSlate = transformToSlate; exports.usfmToSlate = usfmToSlate; require("core-js/modules/es.array.flat.js"); require("core-js/modules/es.array.unscopables.flat.js"); var usfmjs = _interopRequireWildcard(require("usfm-js")); var _usfmjsStructureRules = require("./usfmjsStructureRules"); var _jsonTransforms = require("json-transforms"); var _slateHyperscript = require("slate-hyperscript"); var _NodeTypes = _interopRequireDefault(require("../utils/NodeTypes")); var _basicSlateNodeFactory = require("./basicSlateNodeFactory"); var _UsfmMarkers = require("../utils/UsfmMarkers"); var _slate = require("slate"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function isBook(e) { return Array.isArray(e.chapters) && Array.isArray(e.headers) && e.chapters.every(isChapter); } function isChapter(e) { return typeof e.chapterNumber === "string" && Array.isArray(e.verses); } function isVerse(e) { return typeof e.verseNumber === "string" && Array.isArray(e.nodes); } function isTag(e) { return typeof e.tag === "string"; } function isHasText(e) { return typeof e.text === "string"; } function isHasContent(e) { return typeof e.content === "string"; } function isHasAttrib(e) { return typeof e.attrib === "string"; } function isHasChildren(e) { return Array.isArray(e.children); } function usfmToSlate(usfm) { const usfmJsDoc = usfmjs.toJSON(usfm); console.log("parsed from usfm-js", usfmJsDoc); const usfmAsArrays = (0, _jsonTransforms.transform)(usfmJsDoc, _usfmjsStructureRules.objectToArrayRules); const processedAsArrays = (0, _jsonTransforms.transform)(usfmAsArrays, _usfmjsStructureRules.nextCharRules); console.log("processedAsArrays", processedAsArrays); const slateTree = transformToSlate(processedAsArrays); console.log("slateTree", slateTree); return Array.isArray(slateTree) ? slateTree : [slateTree]; } function transformToSlate(el) { if (isBook(el)) { return book(el); } else if (isChapter(el)) { return [chapter(el)]; } else if (isVerse(el)) { return [verse(el)]; } else if (isTag(el)) { if (typeof el.tag === "string" && _UsfmMarkers.UsfmMarkers.isParagraphType(el.tag)) { return paragraphElement(el); } else { // Character or Note marker return getDescendantTextNodes(el); } } else if (isHasText(el)) { return processText(String(el.text)); } else { console.warn("Unrecognized node: ", el); return []; } } function book(book) { const books = book.chapters.map(chapter); const headers = (0, _slateHyperscript.jsx)("element", { type: _NodeTypes.default.HEADERS }, book.headers.map(transformToSlate)); const children = [headers, books].flat(); return (0, _slateHyperscript.jsx)("fragment", {}, children); } function chapterNumber(number) { return (0, _slateHyperscript.jsx)("element", { type: _UsfmMarkers.UsfmMarkers.CHAPTERS_AND_VERSES.c }, [number]); } function chapter(chapter) { const number = [chapterNumber(chapter.chapterNumber)]; const verses = chapter.verses.map(verse); const children = number.concat(verses); return (0, _slateHyperscript.jsx)("element", { type: _NodeTypes.default.CHAPTER }, children); } function verse(verse) { let verseChildren = [(0, _basicSlateNodeFactory.verseNumber)(verse.verseNumber)]; let currentContainer = (0, _basicSlateNodeFactory.emptyInlineContainer)(); verseChildren = verseChildren.concat(currentContainer); for (const node of verse.nodes) { if (isTag(node) && _UsfmMarkers.UsfmMarkers.isParagraphType(node.tag)) { currentContainer = paragraphElement(node); verseChildren = verseChildren.concat(currentContainer); } else { currentContainer.children = currentContainer.children.concat(transformToSlate(node)); } currentContainer = removeFirstEmptyText(currentContainer); } return (0, _basicSlateNodeFactory.verseWithChildren)(verseChildren); } function paragraphElement(tagNode) { return textElement(tagNode); } function textElement(tagNode) { const textNodes = getDescendantTextNodes(tagNode); return (0, _slateHyperscript.jsx)("element", { type: tagNode.tag }, textNodes); } function removeFirstEmptyText(node) { if (node.children.length > 1 && _slate.Text.isText(node.children[0]) && node.children[0].text == "") { node.children = node.children.slice(1); } return node; } /** * Returns a flat list of descendant text nodes and sets the appopriate marks * on the text nodes */ function getDescendantTextNodes(tagNode) { let textNodes = [{ text: "" }]; if (isHasText(tagNode)) { textNodes = textNodes.concat(processText(tagNode.text)); } else if (isHasContent(tagNode)) { textNodes = textNodes.concat(processText(tagNode.content)); } if (isHasAttrib(tagNode)) { textNodes = textNodes.concat(processText(tagNode.attrib)); } // \w marker will not have an 'attrib' field when parsed by usfm-js. if (isTag(tagNode) && tagNode.tag == _UsfmMarkers.UsfmMarkers.SPECIAL_FEATURES.w) { textNodes = textNodes.concat(processText(get_w_AttributeText(tagNode))); } if (isHasChildren(tagNode)) { // The children will either be additional tag nodes or simple texts, which // will all reduce to a list of text nodes const childText = tagNode.children.map(getDescendantTextNodes); textNodes = textNodes.concat(...childText); } //textNodes = textNodes.flat() // don't think this is needed, but leaving a comment in case wrong // If this node is not a paragraph type (thus it is a character, note, or milestone type), // we will apply the marker as a mark to every descendant text node. if (isTag(tagNode) && !_UsfmMarkers.UsfmMarkers.isParagraphType(tagNode.tag)) { textNodes.forEach(text => { const destructured = _UsfmMarkers.UsfmMarkers.destructureMarker(tagNode.tag); const bareMarker = destructured === null || destructured === void 0 ? void 0 : destructured.markerWithoutLeadingPlus; if (bareMarker) text[bareMarker] = true; }); } return textNodes; } /** * Usfm-js parses the \w marker differently than the other markers with attributes. * This function returns a string that starts with a pipe character and contains * the attributes for the \w marker. Unfortunately, the original order of the attributes * may not be preserved since usfm-js does not tell us what the original order was. */ function get_w_AttributeText(tagNode) { let text = ""; const attributes = ["lemma", "strong", "srcloc"]; attributes.forEach(value => { if (tagNode.hasOwnProperty(value)) { text = text === "" ? "|" : text + " "; text += `${value}=\"${tagNode[value]}\"`; } }); return text; } function processText(text) { return { text: text // Slate does not accept the pipe character so we have a workaround for this .replace(/\|/g, "&pipe;") // Remove newlines .replace(/[\r|\n|\r\n]/g, "") }; }