@eten-tech-foundation/scripture-utilities 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -54,7 +54,7 @@ Run `nx build utilities` to build the library.
54
54
 
55
55
  ## Running unit tests
56
56
 
57
- Run `nx test utilities` to execute the unit tests via [Jest](https://jestjs.io).
57
+ Run `nx test utilities` to execute the unit tests via [Vitest](https://vitest.dev/).
58
58
 
59
59
  ## Develop in App
60
60
 
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const O=require("@xmldom/xmldom"),p="USJ",N="3.1",J=["type","marker","content","sid","eid","number","code","altnumber","pubnumber","caller","align","category"];function v(e){return m.includes(e)}const m=["GEN","EXO","LEV","NUM","DEU","JOS","JDG","RUT","1SA","2SA","1KI","2KI","1CH","2CH","EZR","NEH","EST","JOB","PSA","PRO","ECC","SNG","ISA","JER","LAM","EZK","DAN","HOS","JOL","AMO","OBA","JON","MIC","NAM","HAB","ZEP","HAG","ZEC","MAL","MAT","MRK","LUK","JHN","ACT","ROM","1CO","2CO","GAL","EPH","PHP","COL","1TH","2TH","1TI","2TI","TIT","PHM","HEB","JAS","1PE","2PE","1JN","2JN","3JN","JUD","REV","TOB","JDT","ESG","WIS","SIR","BAR","LJE","S3Y","SUS","BEL","1MA","2MA","3MA","4MA","1ES","2ES","MAN","PS2","ODA","PSS","EZA","5EZ","6EZ","DAG","PS3","2BA","LBA","JUB","ENO","1MQ","2MQ","3MQ","REP","4BA","LAO","FRT","BAK","OTH","INT","CNC","GLO","TDX","NDX","XXA","XXB","XXC","XXD","XXE","XXF","XXG"],u="usx",y="3.1";function M(e){const n=new O.DOMParser().parseFromString(e,"text/xml");return R(n.documentElement)}function R(e){const[t]=e?P(e):[{content:[]}];return t.type=p,t.version=N,t}function P(e){const t={};let n=e.tagName,o,s,c="append";if(["row","cell"].includes(n)&&(n="table:"+n),e.attributes)for(const r of Array.from(e.attributes))t[r.name]=r.value;t.style&&(o=t.style,delete t.style),t.vid&&delete t.vid,t.status&&delete t.status;let i={type:n};o&&(i.marker=o),i={...i,...t},e.firstChild&&e.firstChild.nodeType===e.firstChild.TEXT_NODE&&e.firstChild.nodeValue&&E(e.firstChild.nodeValue)!==""&&(s=e.firstChild.nodeValue);const l=Array.from(e.childNodes);i.content=[],s&&i.content.push(s);for(const r of l){if(r.tagName===void 0)continue;const[f,S]=P(r);switch(S){case"append":i.content.push(f);break;case"merge":i.content=i.content.concat(f);break}r.nextSibling&&r.nextSibling.nodeType===r.nextSibling.TEXT_NODE&&r.nextSibling.nodeValue&&(E(r.nextSibling.nodeValue)!==""||r.nextSibling.nodeValue===" ")&&i.content.push(r.nextSibling.nodeValue)}return i.content.length===0&&i.type!==u&&delete i.content,"eid"in i&&["verse","chapter"].includes(n)&&(c="ignore"),[i,c]}function E(e){return e.replace(/(^[ \t\n\r\f\v]+)|([ \t\n\r\f\v]+$)/g,"")}let d,a;function X(e){const t=new O.DOMImplementation().createDocument("",u);return t.documentElement&&(t.documentElement.setAttribute("version",y),_(e,t)),t.toString()}function _(e,t){if(t.documentElement){for(const[n,o]of e.content.entries()){const s=n===e.content.length-1;b(o,t.documentElement,t,s)}return t.documentElement??void 0}}function b(e,t,n,o){let s,c,i;if(typeof e=="string")s=n.createTextNode(e);else if(c=e.type.replace("table:",""),s=n.createElement(c),B(s,e),e.content)for(const[r,f]of e.content.entries()){const S=r===e.content.length-1;b(f,s,n,S)}a&&(c==="verse"||t.tagName==="para"&&o)&&(i=T(n,a),a=void 0),c==="verse"&&typeof e!="string"&&e.sid!==void 0&&(a=e.sid),d&&(c==="chapter"||c==="para"&&o)&&(i=h(n,d),d=void 0),c==="chapter"&&typeof e!="string"&&e.sid!==void 0&&(d=e.sid);const l=t.nodeName===u&&(i==null?void 0:i.tagName)==="verse";i&&(!o||l)&&t.appendChild(i),t.appendChild(s),i&&o&&!l&&t.appendChild(i),o&&t.nodeName===u&&(a&&t.appendChild(T(n,a)),d&&t.appendChild(h(n,d)),a=void 0,d=void 0)}function B(e,t){t.type==="unmatched"?e.setAttribute("marker",t.marker):e.setAttribute("style",t.marker);for(const[n,o]of Object.entries(t))o&&!["type","marker","content"].includes(n)&&e.setAttribute(n,o)}function T(e,t){const n=e.createElement("verse");return n.setAttribute("eid",t),n}function h(e,t){const n=e.createElement("chapter");return n.setAttribute("eid",t),n}const A="$",g=".content[";function I(e){const t=e.split(g);if(t.shift()!==A)throw new Error(`indexesFromJsonPath: jsonPath didn't start with '${A}'`);return t.map(o=>parseInt(o,10))}function C(e){return e.reduce((t,n)=>`${t}${g}${n}]`,A)}exports.MARKER_OBJECT_PROPS=J;exports.USJ_TYPE=p;exports.USJ_VERSION=N;exports.indexesFromUsjJsonPath=I;exports.isValidBookCode=v;exports.usjJsonPathFromIndexes=C;exports.usjToUsxString=X;exports.usxStringToUsj=M;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const N=require("@xmldom/xmldom"),T="USJ",A="3.1",v=Object.freeze({type:T,version:A,content:[]}),M=["type","marker","content","sid","eid","number","code","altnumber","pubnumber","caller","align","category"];function m(e){return X.includes(e)}const X=["GEN","EXO","LEV","NUM","DEU","JOS","JDG","RUT","1SA","2SA","1KI","2KI","1CH","2CH","EZR","NEH","EST","JOB","PSA","PRO","ECC","SNG","ISA","JER","LAM","EZK","DAN","HOS","JOL","AMO","OBA","JON","MIC","NAM","HAB","ZEP","HAG","ZEC","MAL","MAT","MRK","LUK","JHN","ACT","ROM","1CO","2CO","GAL","EPH","PHP","COL","1TH","2TH","1TI","2TI","TIT","PHM","HEB","JAS","1PE","2PE","1JN","2JN","3JN","JUD","REV","TOB","JDT","ESG","WIS","SIR","BAR","LJE","S3Y","SUS","BEL","1MA","2MA","3MA","4MA","1ES","2ES","MAN","PS2","ODA","PSS","EZA","5EZ","6EZ","DAG","PS3","2BA","LBA","JUB","ENO","1MQ","2MQ","3MQ","REP","4BA","LAO","FRT","BAK","OTH","INT","CNC","GLO","TDX","NDX","XXA","XXB","XXC","XXD","XXE","XXF","XXG"],l="usx",O="3.1",_=`<${l} version="${O}" />`;function y(e){const n=new N.DOMParser().parseFromString(e,"text/xml");return R(n.documentElement)}function R(e){const[t]=e?J(e):[{content:[]}];return t.type=T,t.version=A,t}function J(e){const t={};let n=e.tagName,o,s,c="append";if(["row","cell"].includes(n)&&(n="table:"+n),e.attributes)for(const r of Array.from(e.attributes))t[r.name]=r.value;t.style&&(o=t.style,delete t.style),t.vid&&delete t.vid,t.status&&delete t.status;let i={type:n};o&&(i.marker=o),i={...i,...t},e.firstChild&&e.firstChild.nodeType===e.firstChild.TEXT_NODE&&e.firstChild.nodeValue&&h(e.firstChild.nodeValue)!==""&&(s=e.firstChild.nodeValue);const f=Array.from(e.childNodes);i.content=[],s&&i.content.push(s);for(const r of f){if(r.tagName===void 0)continue;const[u,S]=J(r);switch(S){case"append":i.content.push(u);break;case"merge":i.content=i.content.concat(u);break}r.nextSibling&&r.nextSibling.nodeType===r.nextSibling.TEXT_NODE&&r.nextSibling.nodeValue&&(h(r.nextSibling.nodeValue)!==""||r.nextSibling.nodeValue===" ")&&i.content.push(r.nextSibling.nodeValue)}return i.content.length===0&&i.type!==l&&delete i.content,"eid"in i&&["verse","chapter"].includes(n)&&(c="ignore"),[i,c]}function h(e){return e.replace(/(^[ \t\n\r\f\v]+)|([ \t\n\r\f\v]+$)/g,"")}let d,a;function U(e){const t=new N.DOMImplementation().createDocument("",l);return t.documentElement&&(t.documentElement.setAttribute("version",O),I(e,t)),t.toString()}function I(e,t){if(t.documentElement){for(const[n,o]of e.content.entries()){const s=n===e.content.length-1;b(o,t.documentElement,t,s)}return t.documentElement??void 0}}function b(e,t,n,o){let s,c,i;if(typeof e=="string")s=n.createTextNode(e);else if(c=e.type.replace("table:",""),s=n.createElement(c),B(s,e),e.content)for(const[r,u]of e.content.entries()){const S=r===e.content.length-1;b(u,s,n,S)}a&&(c==="verse"||t.tagName==="para"&&o)&&(i=p(n,a),a=void 0),c==="verse"&&typeof e!="string"&&e.sid!==void 0&&(a=e.sid),d&&(c==="chapter"||c==="para"&&o)&&(i=P(n,d),d=void 0),c==="chapter"&&typeof e!="string"&&e.sid!==void 0&&(d=e.sid);const f=t.nodeName===l&&(i==null?void 0:i.tagName)==="verse";i&&(!o||f)&&t.appendChild(i),t.appendChild(s),i&&o&&!f&&t.appendChild(i),o&&t.nodeName===l&&(a&&t.appendChild(p(n,a)),d&&t.appendChild(P(n,d)),a=void 0,d=void 0)}function B(e,t){t.type==="unmatched"?e.setAttribute("marker",t.marker):e.setAttribute("style",t.marker);for(const[n,o]of Object.entries(t))o&&!["type","marker","content"].includes(n)&&e.setAttribute(n,o)}function p(e,t){const n=e.createElement("verse");return n.setAttribute("eid",t),n}function P(e,t){const n=e.createElement("chapter");return n.setAttribute("eid",t),n}const E="$",g=".content[";function V(e){const t=e.split(g);if(t.shift()!==E)throw new Error(`indexesFromJsonPath: jsonPath didn't start with '${E}'`);return t.map(o=>parseInt(o,10))}function C(e){return e.reduce((t,n)=>`${t}${g}${n}]`,E)}exports.EMPTY_USJ=v;exports.EMPTY_USX=_;exports.MARKER_OBJECT_PROPS=M;exports.USJ_TYPE=T;exports.USJ_VERSION=A;exports.USX_TYPE=l;exports.USX_VERSION=O;exports.indexesFromUsjJsonPath=V;exports.isValidBookCode=m;exports.usjJsonPathFromIndexes=C;exports.usjToUsxString=U;exports.usxStringToUsj=y;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/converters/usj/usj.model.ts","../src/converters/usj/usx.model.ts","../src/converters/usj/usx-to-usj.ts","../src/converters/usj/usj-to-usx.ts","../src/converters/usj/jsonpath-indexes.ts"],"sourcesContent":["/**\n * Unified Scripture JSON (USJ) - The JSON variant of USFM and USX data models.\n * These types follow this schema:\n * @see https://github.com/usfm-bible/tcdocs/blob/usj/grammar/usj.js\n */\n\n/** The USJ spec type */\nexport const USJ_TYPE = \"USJ\";\n/** The USJ spec version */\nexport const USJ_VERSION = \"3.1\";\n/** List of known properties of `MarkerObject` */\nexport const MARKER_OBJECT_PROPS: (keyof MarkerObject)[] = [\n \"type\",\n \"marker\",\n \"content\",\n \"sid\",\n \"eid\",\n \"number\",\n \"code\",\n \"altnumber\",\n \"pubnumber\",\n \"caller\",\n \"align\",\n \"category\",\n];\n\n/** Single piece of Scripture content */\nexport type MarkerContent = string | MarkerObject;\n\n/** A Scripture Marker and its contents */\nexport type MarkerObject = {\n /**\n * The kind/category of node or element this is, corresponding the USFM marker and USX node\n * @example `para`, `verse`, `char`\n */\n type: string;\n /**\n * The corresponding marker in USFM or style in USX\n * @example `p`, `v`, `nd`\n */\n marker: string;\n /** This marker's contents laid out in order */\n content?: MarkerContent[];\n /** Indicates the Book-chapter-verse value in the paragraph based structure */\n sid?: string;\n /** Milestone end ID, matches start ID (not currently included in USJ spec) */\n eid?: string;\n /** Chapter number or verse number */\n number?: string;\n /** The 3-letter book code in ID element */\n code?: BookCode;\n /** Alternate chapter number or verse number */\n altnumber?: string;\n /** Published character of chapter or verse */\n pubnumber?: string;\n /** Caller character for footnotes and cross-refs */\n caller?: string;\n /** Alignment of table cells */\n align?: string;\n /** Category of extended study bible sections */\n category?: string;\n};\n\n/** Scripture data represented in JSON format. Data compatible transformation from USX/USFM */\nexport type Usj = {\n /** The USJ spec type */\n type: typeof USJ_TYPE;\n /** The USJ spec version */\n version: typeof USJ_VERSION;\n /** The JSON representation of scripture contents from USFM/USX */\n content: MarkerContent[];\n};\n\nexport function isValidBookCode(code: string): boolean {\n return VALID_BOOK_CODES.includes(code as BookCode);\n}\n\n/** 3-letter Scripture book code */\nexport type BookCode = (typeof VALID_BOOK_CODES)[number];\n\nconst VALID_BOOK_CODES = [\n // Old Testament\n \"GEN\",\n \"EXO\",\n \"LEV\",\n \"NUM\",\n \"DEU\",\n \"JOS\",\n \"JDG\",\n \"RUT\",\n \"1SA\",\n \"2SA\",\n \"1KI\",\n \"2KI\",\n \"1CH\",\n \"2CH\",\n \"EZR\",\n \"NEH\",\n \"EST\",\n \"JOB\",\n \"PSA\",\n \"PRO\",\n \"ECC\",\n \"SNG\",\n \"ISA\",\n \"JER\",\n \"LAM\",\n \"EZK\",\n \"DAN\",\n \"HOS\",\n \"JOL\",\n \"AMO\",\n \"OBA\",\n \"JON\",\n \"MIC\",\n \"NAM\",\n \"HAB\",\n \"ZEP\",\n \"HAG\",\n \"ZEC\",\n \"MAL\",\n // New Testament\n \"MAT\",\n \"MRK\",\n \"LUK\",\n \"JHN\",\n \"ACT\",\n \"ROM\",\n \"1CO\",\n \"2CO\",\n \"GAL\",\n \"EPH\",\n \"PHP\",\n \"COL\",\n \"1TH\",\n \"2TH\",\n \"1TI\",\n \"2TI\",\n \"TIT\",\n \"PHM\",\n \"HEB\",\n \"JAS\",\n \"1PE\",\n \"2PE\",\n \"1JN\",\n \"2JN\",\n \"3JN\",\n \"JUD\",\n \"REV\",\n // Deuterocanon\n \"TOB\",\n \"JDT\",\n \"ESG\",\n \"WIS\",\n \"SIR\",\n \"BAR\",\n \"LJE\",\n \"S3Y\",\n \"SUS\",\n \"BEL\",\n \"1MA\",\n \"2MA\",\n \"3MA\",\n \"4MA\",\n \"1ES\",\n \"2ES\",\n \"MAN\",\n \"PS2\",\n \"ODA\",\n \"PSS\",\n \"EZA\",\n \"5EZ\",\n \"6EZ\",\n \"DAG\",\n \"PS3\",\n \"2BA\",\n \"LBA\",\n \"JUB\",\n \"ENO\",\n \"1MQ\",\n \"2MQ\",\n \"3MQ\",\n \"REP\",\n \"4BA\",\n \"LAO\",\n // Non scripture\n \"FRT\",\n \"BAK\",\n \"OTH\",\n \"INT\",\n \"CNC\",\n \"GLO\",\n \"TDX\",\n \"NDX\",\n \"XXA\",\n \"XXB\",\n \"XXC\",\n \"XXD\",\n \"XXE\",\n \"XXF\",\n \"XXG\",\n] as const;\n","/**\n * Unified Scripture XML (USX).\n * These types follow this schema:\n * @see https://github.com/usfm-bible/tcdocs/blob/main/grammar/usx.rng\n */\n\n/** The USX spec type */\nexport const USX_TYPE = \"usx\";\n/** The USX spec version */\nexport const USX_VERSION = \"3.1\";\n","/**\n * Convert Scripture from USX to USJ.\n * Adapted to TypeScript from this file:\n * @see https://github.com/usfm-bible/usfmtc/blob/0afa385a1f282b286cc6bff7bbc953ae788aa10c/src/usfmtc/usjproc.py\n */\n\nimport { DOMParser, Element } from \"@xmldom/xmldom\";\nimport { MarkerContent, MarkerObject, USJ_TYPE, USJ_VERSION, Usj } from \"./usj.model\";\nimport { USX_TYPE } from \"./usx.model\";\n\ntype Action = \"append\" | \"merge\" | \"ignore\";\ntype Attribs = { [name: string]: string };\n\nexport function usxStringToUsj(usxString: string): Usj {\n const parser = new DOMParser();\n const inputUsxDom = parser.parseFromString(usxString, \"text/xml\");\n return usxDomToUsj(inputUsxDom.documentElement);\n}\n\nexport function usxDomToUsj(inputUsxDom: Element | null): Usj {\n const [outputJson] = inputUsxDom\n ? convertUsxRecurse(inputUsxDom)\n : [{ content: [] as MarkerContent[] } as Usj];\n outputJson.type = USJ_TYPE;\n outputJson.version = USJ_VERSION;\n return outputJson;\n}\n\nfunction convertUsxRecurse<T extends Usj | MarkerObject = Usj>(\n inputUsxElement: Element,\n): [outputJson: T, action: Action] {\n const attribs: Attribs = {};\n let type: string = inputUsxElement.tagName;\n let marker: string | undefined;\n let text: string | undefined;\n let action: Action = \"append\";\n\n if ([\"row\", \"cell\"].includes(type)) type = \"table:\" + type;\n if (inputUsxElement.attributes) {\n for (const attrib of Array.from(inputUsxElement.attributes)) {\n attribs[attrib.name] = attrib.value;\n }\n }\n\n if (attribs.style) {\n marker = attribs.style;\n delete attribs.style;\n }\n // dropping because presence of vid in para elements is not consistent in USX\n if (attribs.vid) delete attribs.vid;\n // Not dropping `attribs.closed` for backwards compatibility.\n // dropping because it is nonstandard derived metadata that could get out of date\n if (attribs.status) delete attribs.status;\n\n let outObj: T = { type } as T;\n if (marker) (outObj as MarkerObject).marker = marker;\n outObj = { ...outObj, ...attribs };\n\n if (\n inputUsxElement.firstChild &&\n inputUsxElement.firstChild.nodeType === inputUsxElement.firstChild.TEXT_NODE &&\n inputUsxElement.firstChild.nodeValue &&\n asciiTrim(inputUsxElement.firstChild.nodeValue) !== \"\"\n ) {\n text = inputUsxElement.firstChild.nodeValue;\n }\n\n const children = Array.from(inputUsxElement.childNodes);\n outObj.content = [];\n\n if (text) {\n outObj.content.push(text);\n }\n\n for (const child of children) {\n // ChildNodes are Elements.\n if ((child as Element).tagName === undefined) {\n continue;\n }\n // ChildNodes are Elements.\n const [childDict, whatToDo] = convertUsxRecurse<MarkerObject>(child as Element);\n\n switch (whatToDo) {\n case \"append\":\n outObj.content.push(childDict);\n break;\n case \"merge\":\n outObj.content = outObj.content.concat(childDict);\n break;\n case \"ignore\":\n break;\n default:\n break;\n }\n\n // Handle tail text\n if (\n child.nextSibling &&\n child.nextSibling.nodeType === child.nextSibling.TEXT_NODE &&\n child.nextSibling.nodeValue &&\n (asciiTrim(child.nextSibling.nodeValue) !== \"\" || child.nextSibling.nodeValue === \" \")\n ) {\n outObj.content.push(child.nextSibling.nodeValue);\n }\n }\n\n // For backward compatibility, not deleting content for type: chapter, verse, optbreak, ms OR\n // marker: va, ca, b.\n if (outObj.content.length === 0 && outObj.type !== USX_TYPE) {\n delete outObj.content;\n }\n\n if (\"eid\" in outObj && [\"verse\", \"chapter\"].includes(type)) {\n action = \"ignore\";\n }\n\n return [outObj, action];\n}\n\n/**\n * Removes leading and trailing ASCII whitespace.\n *\n * Only trim ASCII whitespace characters: space, tab, line feed, carriage return, form feed,\n * vertical tab.\n * @param str - The string to remove whitespace from.\n * @returns the string with leading and trailing whitespace removed.\n */\nfunction asciiTrim(str: string): string {\n return str.replace(/(^[ \\t\\n\\r\\f\\v]+)|([ \\t\\n\\r\\f\\v]+$)/g, \"\");\n}\n","/**\n * Convert Scripture from USJ to USX.\n * Adapted to TypeScript from this file:\n * @see https://github.com/usfm-bible/usfmtc/blob/0afa385a1f282b286cc6bff7bbc953ae788aa10c/src/usfmtc/usjproc.py\n */\n\nimport { DOMImplementation, Document, Element, Text } from \"@xmldom/xmldom\";\nimport { MarkerContent, MarkerObject, Usj } from \"./usj.model\";\nimport { USX_TYPE, USX_VERSION } from \"./usx.model\";\n\nlet chapterEid: string | undefined;\nlet verseEid: string | undefined;\n\nexport function usjToUsxString(usj: Usj): string {\n const usxDoc = new DOMImplementation().createDocument(\"\", USX_TYPE);\n if (usxDoc.documentElement) {\n usxDoc.documentElement.setAttribute(\"version\", USX_VERSION);\n usjToUsxDom(usj, usxDoc);\n }\n return usxDoc.toString();\n}\n\nexport function usjToUsxDom(usj: Usj, usxDoc: Document): Element | undefined {\n if (!usxDoc.documentElement) return undefined;\n\n for (const [index, markerContent] of usj.content.entries()) {\n const isLastItem = index === usj.content.length - 1;\n convertUsjRecurse(markerContent, usxDoc.documentElement, usxDoc, isLastItem);\n }\n return usxDoc.documentElement ?? undefined;\n}\n\nfunction convertUsjRecurse(\n markerContent: MarkerContent,\n parentElement: Element,\n usxDoc: Document,\n isLastItem: boolean,\n) {\n let element: Text | Element;\n let type: string | undefined;\n let eidElement: Element | undefined;\n if (typeof markerContent === \"string\") element = usxDoc.createTextNode(markerContent);\n else {\n type = markerContent.type.replace(\"table:\", \"\");\n element = usxDoc.createElement(type);\n setAttributes(element, markerContent);\n if (markerContent.content) {\n for (const [index, item] of markerContent.content.entries()) {\n const _isLastItem = index === markerContent.content.length - 1;\n convertUsjRecurse(item, element, usxDoc, _isLastItem);\n }\n }\n }\n\n // Create chapter and verse end elements from SID attributes.\n if (verseEid && (type === \"verse\" || (parentElement.tagName === \"para\" && isLastItem))) {\n eidElement = createVerseEndElement(usxDoc, verseEid);\n verseEid = undefined;\n }\n if (type === \"verse\" && typeof markerContent !== \"string\" && markerContent.sid !== undefined)\n verseEid = markerContent.sid;\n\n if (chapterEid && (type === \"chapter\" || (type === \"para\" && isLastItem))) {\n eidElement = createChapterEndElement(usxDoc, chapterEid);\n chapterEid = undefined;\n }\n if (type === \"chapter\" && typeof markerContent !== \"string\" && markerContent.sid !== undefined)\n chapterEid = markerContent.sid;\n\n // Append to parent.\n const isVerseInImpliedPara =\n parentElement.nodeName === USX_TYPE && eidElement?.tagName === \"verse\";\n if (eidElement && (!isLastItem || isVerseInImpliedPara)) parentElement.appendChild(eidElement);\n parentElement.appendChild(element);\n if (eidElement && isLastItem && !isVerseInImpliedPara) parentElement.appendChild(eidElement);\n\n // Allow for final chapter and verse end elements at the end of an implied para.\n if (isLastItem && parentElement.nodeName === USX_TYPE) {\n if (verseEid) parentElement.appendChild(createVerseEndElement(usxDoc, verseEid));\n if (chapterEid) parentElement.appendChild(createChapterEndElement(usxDoc, chapterEid));\n verseEid = undefined;\n chapterEid = undefined;\n }\n}\n\nfunction setAttributes(element: Element, markerContent: MarkerObject) {\n if (markerContent.type === \"unmatched\") element.setAttribute(\"marker\", markerContent.marker);\n else element.setAttribute(\"style\", markerContent.marker);\n for (const [key, value] of Object.entries(markerContent)) {\n if (value && ![\"type\", \"marker\", \"content\"].includes(key)) {\n element.setAttribute(key, value as string);\n }\n }\n}\n\nfunction createVerseEndElement(usxDoc: Document, verseEid: string): Element {\n const eidElement = usxDoc.createElement(\"verse\");\n eidElement.setAttribute(\"eid\", verseEid);\n return eidElement;\n}\n\nfunction createChapterEndElement(usxDoc: Document, chapterEid: string): Element {\n const eidElement = usxDoc.createElement(\"chapter\");\n eidElement.setAttribute(\"eid\", chapterEid);\n return eidElement;\n}\n","const JSON_PATH_START = \"$\";\nconst JSON_PATH_CONTENT = \".content[\";\n\n/**\n * Converts a USJ JSONPath string into an array of indexes.\n *\n * @param jsonPath - The USJ JSONPath string to convert. It must start with `$` and contain `.content[index]` segments.\n * @returns An array of numeric indexes extracted from the JSONPath.\n * @throws Will throw an error if the JSONPath does not start with `$`.\n */\nexport function indexesFromUsjJsonPath(jsonPath: string): number[] {\n const path = jsonPath.split(JSON_PATH_CONTENT);\n if (path.shift() !== JSON_PATH_START)\n throw new Error(`indexesFromJsonPath: jsonPath didn't start with '${JSON_PATH_START}'`);\n\n const indexes = path.map((str) => parseInt(str, 10));\n return indexes;\n}\n\n/**\n * Converts an array of indexes into a USJ JSONPath string.\n *\n * @param indexes - An array of numeric indexes to convert.\n * @returns A USJ JSONPath string constructed from the indexes.\n */\nexport function usjJsonPathFromIndexes(indexes: number[]): string {\n return indexes.reduce((path, index) => `${path}${JSON_PATH_CONTENT}${index}]`, JSON_PATH_START);\n}\n"],"names":["USJ_TYPE","USJ_VERSION","MARKER_OBJECT_PROPS","isValidBookCode","code","VALID_BOOK_CODES","USX_TYPE","USX_VERSION","usxStringToUsj","usxString","inputUsxDom","DOMParser","usxDomToUsj","outputJson","convertUsxRecurse","inputUsxElement","attribs","type","marker","text","action","attrib","outObj","asciiTrim","children","child","childDict","whatToDo","str","chapterEid","verseEid","usjToUsxString","usj","usxDoc","DOMImplementation","usjToUsxDom","index","markerContent","isLastItem","convertUsjRecurse","parentElement","element","eidElement","setAttributes","item","_isLastItem","createVerseEndElement","createChapterEndElement","isVerseInImpliedPara","key","value","JSON_PATH_START","JSON_PATH_CONTENT","indexesFromUsjJsonPath","jsonPath","path","usjJsonPathFromIndexes","indexes"],"mappings":"kHAOaA,EAAW,MAEXC,EAAc,MAEdC,EAA8C,CACzD,OACA,SACA,UACA,MACA,MACA,SACA,OACA,YACA,YACA,SACA,QACA,UACF,EAiDO,SAASC,EAAgBC,EAAuB,CACrD,OAAOC,EAAiB,SAASD,CAAgB,CACnD,CAKA,MAAMC,EAAmB,CAEvB,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MAEA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MAEA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MAEA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,KACF,EClMaC,EAAW,MAEXC,EAAc,MCIpB,SAASC,EAAeC,EAAwB,CAErD,MAAMC,EADS,IAAIC,YAAA,EACQ,gBAAgBF,EAAW,UAAU,EAChE,OAAOG,EAAYF,EAAY,eAAe,CAChD,CAEO,SAASE,EAAYF,EAAkC,CAC5D,KAAM,CAACG,CAAU,EAAIH,EACjBI,EAAkBJ,CAAW,EAC7B,CAAC,CAAE,QAAS,CAAA,EAA8B,EAC9C,OAAAG,EAAW,KAAOb,EAClBa,EAAW,QAAUZ,EACdY,CACT,CAEA,SAASC,EACPC,EACiC,CACjC,MAAMC,EAAmB,CAAA,EACzB,IAAIC,EAAeF,EAAgB,QAC/BG,EACAC,EACAC,EAAiB,SAGrB,GADI,CAAC,MAAO,MAAM,EAAE,SAASH,CAAI,MAAU,SAAWA,G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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/converters/usj/usj.model.ts","../src/converters/usj/usx.model.ts","../src/converters/usj/usx-to-usj.ts","../src/converters/usj/usj-to-usx.ts","../src/converters/usj/jsonpath-indexes.ts"],"sourcesContent":["/**\n * Unified Scripture JSON (USJ) - The JSON variant of USFM and USX data models.\n * These types follow this schema:\n * @see https://github.com/usfm-bible/tcdocs/blob/usj/grammar/usj.js\n */\n\n/** The USJ spec type */\nexport const USJ_TYPE = \"USJ\";\n\n/** The USJ spec version */\nexport const USJ_VERSION = \"3.1\";\n\nexport const EMPTY_USJ = Object.freeze<Usj>({ type: USJ_TYPE, version: USJ_VERSION, content: [] });\n\n/** List of known properties of `MarkerObject` */\nexport const MARKER_OBJECT_PROPS: (keyof MarkerObject)[] = [\n \"type\",\n \"marker\",\n \"content\",\n \"sid\",\n \"eid\",\n \"number\",\n \"code\",\n \"altnumber\",\n \"pubnumber\",\n \"caller\",\n \"align\",\n \"category\",\n];\n\n/** Single piece of Scripture content */\nexport type MarkerContent = string | MarkerObject;\n\n/** A Scripture Marker and its contents */\nexport interface MarkerObject {\n /**\n * The kind/category of node or element this is, corresponding the USFM marker and USX node\n * @example `para`, `verse`, `char`\n */\n type: string;\n /**\n * The corresponding marker in USFM or style in USX\n * @example `p`, `v`, `nd`\n */\n marker: string;\n /** This marker's contents laid out in order */\n content?: MarkerContent[];\n /** Indicates the Book-chapter-verse value in the paragraph based structure */\n sid?: string;\n /** Milestone end ID, matches start ID (not currently included in USJ spec) */\n eid?: string;\n /** Chapter number or verse number */\n number?: string;\n /** The 3-letter book code in ID element */\n code?: BookCode;\n /** Alternate chapter number or verse number */\n altnumber?: string;\n /** Published character of chapter or verse */\n pubnumber?: string;\n /** Caller character for footnotes and cross-refs */\n caller?: string;\n /** Alignment of table cells */\n align?: string;\n /** Category of extended study bible sections */\n category?: string;\n}\n\n/** Scripture data represented in JSON format. Data compatible transformation from USX/USFM */\nexport interface Usj {\n /** The USJ spec type */\n type: typeof USJ_TYPE;\n /** The USJ spec version */\n version: typeof USJ_VERSION;\n /** The JSON representation of scripture contents from USFM/USX */\n content: MarkerContent[];\n}\n\nexport function isValidBookCode(code: string): boolean {\n return VALID_BOOK_CODES.includes(code as BookCode);\n}\n\n/** 3-letter Scripture book code */\nexport type BookCode = (typeof VALID_BOOK_CODES)[number];\n\nconst VALID_BOOK_CODES = [\n // Old Testament\n \"GEN\",\n \"EXO\",\n \"LEV\",\n \"NUM\",\n \"DEU\",\n \"JOS\",\n \"JDG\",\n \"RUT\",\n \"1SA\",\n \"2SA\",\n \"1KI\",\n \"2KI\",\n \"1CH\",\n \"2CH\",\n \"EZR\",\n \"NEH\",\n \"EST\",\n \"JOB\",\n \"PSA\",\n \"PRO\",\n \"ECC\",\n \"SNG\",\n \"ISA\",\n \"JER\",\n \"LAM\",\n \"EZK\",\n \"DAN\",\n \"HOS\",\n \"JOL\",\n \"AMO\",\n \"OBA\",\n \"JON\",\n \"MIC\",\n \"NAM\",\n \"HAB\",\n \"ZEP\",\n \"HAG\",\n \"ZEC\",\n \"MAL\",\n // New Testament\n \"MAT\",\n \"MRK\",\n \"LUK\",\n \"JHN\",\n \"ACT\",\n \"ROM\",\n \"1CO\",\n \"2CO\",\n \"GAL\",\n \"EPH\",\n \"PHP\",\n \"COL\",\n \"1TH\",\n \"2TH\",\n \"1TI\",\n \"2TI\",\n \"TIT\",\n \"PHM\",\n \"HEB\",\n \"JAS\",\n \"1PE\",\n \"2PE\",\n \"1JN\",\n \"2JN\",\n \"3JN\",\n \"JUD\",\n \"REV\",\n // Deuterocanon\n \"TOB\",\n \"JDT\",\n \"ESG\",\n \"WIS\",\n \"SIR\",\n \"BAR\",\n \"LJE\",\n \"S3Y\",\n \"SUS\",\n \"BEL\",\n \"1MA\",\n \"2MA\",\n \"3MA\",\n \"4MA\",\n \"1ES\",\n \"2ES\",\n \"MAN\",\n \"PS2\",\n \"ODA\",\n \"PSS\",\n \"EZA\",\n \"5EZ\",\n \"6EZ\",\n \"DAG\",\n \"PS3\",\n \"2BA\",\n \"LBA\",\n \"JUB\",\n \"ENO\",\n \"1MQ\",\n \"2MQ\",\n \"3MQ\",\n \"REP\",\n \"4BA\",\n \"LAO\",\n // Non scripture\n \"FRT\",\n \"BAK\",\n \"OTH\",\n \"INT\",\n \"CNC\",\n \"GLO\",\n \"TDX\",\n \"NDX\",\n \"XXA\",\n \"XXB\",\n \"XXC\",\n \"XXD\",\n \"XXE\",\n \"XXF\",\n \"XXG\",\n] as const;\n","/**\n * Unified Scripture XML (USX).\n * These types follow this schema:\n * @see https://github.com/usfm-bible/tcdocs/blob/main/grammar/usx.rng\n */\n\n/** The USX spec type */\nexport const USX_TYPE = \"usx\";\n\n/** The USX spec version */\nexport const USX_VERSION = \"3.1\";\n\nexport const EMPTY_USX = `<${USX_TYPE} version=\"${USX_VERSION}\" />`;\n","/**\n * Convert Scripture from USX to USJ.\n * Adapted to TypeScript from this file:\n * @see https://github.com/usfm-bible/usfmtc/blob/0afa385a1f282b286cc6bff7bbc953ae788aa10c/src/usfmtc/usjproc.py\n */\n\nimport { DOMParser, Element } from \"@xmldom/xmldom\";\nimport { MarkerContent, MarkerObject, USJ_TYPE, USJ_VERSION, Usj } from \"./usj.model.js\";\nimport { USX_TYPE } from \"./usx.model.js\";\n\ntype Action = \"append\" | \"merge\" | \"ignore\";\ninterface Attribs {\n [name: string]: string;\n}\n\nexport function usxStringToUsj(usxString: string): Usj {\n const parser = new DOMParser();\n const inputUsxDom = parser.parseFromString(usxString, \"text/xml\");\n return usxDomToUsj(inputUsxDom.documentElement);\n}\n\nexport function usxDomToUsj(inputUsxDom: Element | null): Usj {\n const [outputJson] = inputUsxDom\n ? convertUsxRecurse(inputUsxDom)\n : [{ content: [] as MarkerContent[] } as Usj];\n outputJson.type = USJ_TYPE;\n outputJson.version = USJ_VERSION;\n return outputJson;\n}\n\nfunction convertUsxRecurse<T extends Usj | MarkerObject = Usj>(\n inputUsxElement: Element,\n): [outputJson: T, action: Action] {\n const attribs: Attribs = {};\n let type: string = inputUsxElement.tagName;\n let marker: string | undefined;\n let text: string | undefined;\n let action: Action = \"append\";\n\n if ([\"row\", \"cell\"].includes(type)) type = \"table:\" + type;\n if (inputUsxElement.attributes) {\n for (const attrib of Array.from(inputUsxElement.attributes)) {\n attribs[attrib.name] = attrib.value;\n }\n }\n\n if (attribs.style) {\n marker = attribs.style;\n delete attribs.style;\n }\n // dropping because presence of vid in para elements is not consistent in USX\n if (attribs.vid) delete attribs.vid;\n // Not dropping `attribs.closed` for backwards compatibility.\n // dropping because it is nonstandard derived metadata that could get out of date\n if (attribs.status) delete attribs.status;\n\n let outObj: T = { type } as T;\n if (marker) (outObj as MarkerObject).marker = marker;\n outObj = { ...outObj, ...attribs };\n\n if (\n inputUsxElement.firstChild &&\n inputUsxElement.firstChild.nodeType === inputUsxElement.firstChild.TEXT_NODE &&\n inputUsxElement.firstChild.nodeValue &&\n asciiTrim(inputUsxElement.firstChild.nodeValue) !== \"\"\n ) {\n text = inputUsxElement.firstChild.nodeValue;\n }\n\n const children = Array.from(inputUsxElement.childNodes);\n outObj.content = [];\n\n if (text) {\n outObj.content.push(text);\n }\n\n for (const child of children) {\n // ChildNodes are Elements.\n if ((child as Element).tagName === undefined) {\n continue;\n }\n // ChildNodes are Elements.\n const [childDict, whatToDo] = convertUsxRecurse<MarkerObject>(child as Element);\n\n switch (whatToDo) {\n case \"append\":\n outObj.content.push(childDict);\n break;\n case \"merge\":\n outObj.content = outObj.content.concat(childDict);\n break;\n case \"ignore\":\n break;\n default:\n break;\n }\n\n // Handle tail text\n if (\n child.nextSibling &&\n child.nextSibling.nodeType === child.nextSibling.TEXT_NODE &&\n child.nextSibling.nodeValue &&\n (asciiTrim(child.nextSibling.nodeValue) !== \"\" || child.nextSibling.nodeValue === \" \")\n ) {\n outObj.content.push(child.nextSibling.nodeValue);\n }\n }\n\n // For backward compatibility, not deleting content for type: chapter, verse, optbreak, ms OR\n // marker: va, ca, b.\n if (outObj.content.length === 0 && outObj.type !== USX_TYPE) {\n delete outObj.content;\n }\n\n if (\"eid\" in outObj && [\"verse\", \"chapter\"].includes(type)) {\n action = \"ignore\";\n }\n\n return [outObj, action];\n}\n\n/**\n * Removes leading and trailing ASCII whitespace.\n *\n * Only trim ASCII whitespace characters: space, tab, line feed, carriage return, form feed,\n * vertical tab.\n * @param str - The string to remove whitespace from.\n * @returns the string with leading and trailing whitespace removed.\n */\nfunction asciiTrim(str: string): string {\n return str.replace(/(^[ \\t\\n\\r\\f\\v]+)|([ \\t\\n\\r\\f\\v]+$)/g, \"\");\n}\n","/**\n * Convert Scripture from USJ to USX.\n * Adapted to TypeScript from this file:\n * @see https://github.com/usfm-bible/usfmtc/blob/0afa385a1f282b286cc6bff7bbc953ae788aa10c/src/usfmtc/usjproc.py\n */\n\nimport { DOMImplementation, Document, Element, Text } from \"@xmldom/xmldom\";\nimport { MarkerContent, MarkerObject, Usj } from \"./usj.model.js\";\nimport { USX_TYPE, USX_VERSION } from \"./usx.model.js\";\n\nlet chapterEid: string | undefined;\nlet verseEid: string | undefined;\n\nexport function usjToUsxString(usj: Usj): string {\n const usxDoc = new DOMImplementation().createDocument(\"\", USX_TYPE);\n if (usxDoc.documentElement) {\n usxDoc.documentElement.setAttribute(\"version\", USX_VERSION);\n usjToUsxDom(usj, usxDoc);\n }\n return usxDoc.toString();\n}\n\nexport function usjToUsxDom(usj: Usj, usxDoc: Document): Element | undefined {\n if (!usxDoc.documentElement) return undefined;\n\n for (const [index, markerContent] of usj.content.entries()) {\n const isLastItem = index === usj.content.length - 1;\n convertUsjRecurse(markerContent, usxDoc.documentElement, usxDoc, isLastItem);\n }\n return usxDoc.documentElement ?? undefined;\n}\n\nfunction convertUsjRecurse(\n markerContent: MarkerContent,\n parentElement: Element,\n usxDoc: Document,\n isLastItem: boolean,\n) {\n let element: Text | Element;\n let type: string | undefined;\n let eidElement: Element | undefined;\n if (typeof markerContent === \"string\") element = usxDoc.createTextNode(markerContent);\n else {\n type = markerContent.type.replace(\"table:\", \"\");\n element = usxDoc.createElement(type);\n setAttributes(element, markerContent);\n if (markerContent.content) {\n for (const [index, item] of markerContent.content.entries()) {\n const _isLastItem = index === markerContent.content.length - 1;\n convertUsjRecurse(item, element, usxDoc, _isLastItem);\n }\n }\n }\n\n // Create chapter and verse end elements from SID attributes.\n if (verseEid && (type === \"verse\" || (parentElement.tagName === \"para\" && isLastItem))) {\n eidElement = createVerseEndElement(usxDoc, verseEid);\n verseEid = undefined;\n }\n if (type === \"verse\" && typeof markerContent !== \"string\" && markerContent.sid !== undefined)\n verseEid = markerContent.sid;\n\n if (chapterEid && (type === \"chapter\" || (type === \"para\" && isLastItem))) {\n eidElement = createChapterEndElement(usxDoc, chapterEid);\n chapterEid = undefined;\n }\n if (type === \"chapter\" && typeof markerContent !== \"string\" && markerContent.sid !== undefined)\n chapterEid = markerContent.sid;\n\n // Append to parent.\n const isVerseInImpliedPara =\n parentElement.nodeName === USX_TYPE && eidElement?.tagName === \"verse\";\n if (eidElement && (!isLastItem || isVerseInImpliedPara)) parentElement.appendChild(eidElement);\n parentElement.appendChild(element);\n if (eidElement && isLastItem && !isVerseInImpliedPara) parentElement.appendChild(eidElement);\n\n // Allow for final chapter and verse end elements at the end of an implied para.\n if (isLastItem && parentElement.nodeName === USX_TYPE) {\n if (verseEid) parentElement.appendChild(createVerseEndElement(usxDoc, verseEid));\n if (chapterEid) parentElement.appendChild(createChapterEndElement(usxDoc, chapterEid));\n verseEid = undefined;\n chapterEid = undefined;\n }\n}\n\nfunction setAttributes(element: Element, markerContent: MarkerObject) {\n if (markerContent.type === \"unmatched\") element.setAttribute(\"marker\", markerContent.marker);\n else element.setAttribute(\"style\", markerContent.marker);\n for (const [key, value] of Object.entries(markerContent)) {\n if (value && ![\"type\", \"marker\", \"content\"].includes(key)) {\n element.setAttribute(key, value as string);\n }\n }\n}\n\nfunction createVerseEndElement(usxDoc: Document, verseEid: string): Element {\n const eidElement = usxDoc.createElement(\"verse\");\n eidElement.setAttribute(\"eid\", verseEid);\n return eidElement;\n}\n\nfunction createChapterEndElement(usxDoc: Document, chapterEid: string): Element {\n const eidElement = usxDoc.createElement(\"chapter\");\n eidElement.setAttribute(\"eid\", chapterEid);\n return eidElement;\n}\n","const JSON_PATH_START = \"$\";\nconst JSON_PATH_CONTENT = \".content[\";\n\n/**\n * Converts a USJ JSONPath string into an array of indexes.\n *\n * @param jsonPath - The USJ JSONPath string to convert. It must start with `$` and contain `.content[index]` segments.\n * @returns An array of numeric indexes extracted from the JSONPath.\n * @throws Will throw an error if the JSONPath does not start with `$`.\n */\nexport function indexesFromUsjJsonPath(jsonPath: string): number[] {\n const path = jsonPath.split(JSON_PATH_CONTENT);\n if (path.shift() !== JSON_PATH_START)\n throw new Error(`indexesFromJsonPath: jsonPath didn't start with '${JSON_PATH_START}'`);\n\n const indexes = path.map((str) => parseInt(str, 10));\n return indexes;\n}\n\n/**\n * Converts an array of indexes into a USJ JSONPath string.\n *\n * @param indexes - An array of numeric indexes to convert.\n * @returns A USJ JSONPath string constructed from the indexes.\n */\nexport function usjJsonPathFromIndexes(indexes: number[]): string {\n return indexes.reduce((path, index) => `${path}${JSON_PATH_CONTENT}${index}]`, JSON_PATH_START);\n}\n"],"names":["USJ_TYPE","USJ_VERSION","EMPTY_USJ","MARKER_OBJECT_PROPS","isValidBookCode","code","VALID_BOOK_CODES","USX_TYPE","USX_VERSION","EMPTY_USX","usxStringToUsj","usxString","inputUsxDom","DOMParser","usxDomToUsj","outputJson","convertUsxRecurse","inputUsxElement","attribs","type","marker","text","action","attrib","outObj","asciiTrim","children","child","childDict","whatToDo","str","chapterEid","verseEid","usjToUsxString","usj","usxDoc","DOMImplementation","usjToUsxDom","index","markerContent","isLastItem","convertUsjRecurse","parentElement","element","eidElement","setAttributes","item","_isLastItem","createVerseEndElement","createChapterEndElement","isVerseInImpliedPara","key","value","JSON_PATH_START","JSON_PATH_CONTENT","indexesFromUsjJsonPath","jsonPath","path","usjJsonPathFromIndexes","indexes"],"mappings":"kHAOaA,EAAW,MAGXC,EAAc,MAEdC,EAAY,OAAO,OAAY,CAAE,KAAMF,EAAU,QAASC,EAAa,QAAS,EAAC,CAAG,EAGpFE,EAA8C,CACzD,OACA,SACA,UACA,MACA,MACA,SACA,OACA,YACA,YACA,SACA,QACA,UACF,EAiDO,SAASC,EAAgBC,EAAuB,CACrD,OAAOC,EAAiB,SAASD,CAAgB,CACnD,CAKA,MAAMC,EAAmB,CAEvB,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MAEA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MAEA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MAEA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,KACF,ECtMaC,EAAW,MAGXC,EAAc,MAEdC,EAAY,IAAIF,CAAQ,aAAaC,CAAW,OCGtD,SAASE,EAAeC,EAAwB,CAErD,MAAMC,EADS,IAAIC,YAAA,EACQ,gBAAgBF,EAAW,UAAU,EAChE,OAAOG,EAAYF,EAAY,eAAe,CAChD,CAEO,SAASE,EAAYF,EAAkC,CAC5D,KAAM,CAACG,CAAU,EAAIH,EACjBI,EAAkBJ,CAAW,EAC7B,CAAC,CAAE,QAAS,CAAA,EAA8B,EAC9C,OAAAG,EAAW,KAAOf,EAClBe,EAAW,QAAUd,EACdc,CACT,CAEA,SAASC,EACPC,EACiC,CACjC,MAAMC,EAAmB,CAAA,EACzB,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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,95 @@
1
- export type { Usj, BookCode, MarkerContent, MarkerObject } from './converters/usj/usj.model';
2
- export { MARKER_OBJECT_PROPS, USJ_TYPE, USJ_VERSION, isValidBookCode, } from './converters/usj/usj.model';
3
- export { usxStringToUsj } from './converters/usj/usx-to-usj';
4
- export { usjToUsxString } from './converters/usj/usj-to-usx';
5
- export { indexesFromUsjJsonPath, usjJsonPathFromIndexes } from './converters/usj/jsonpath-indexes';
1
+ /** 3-letter Scripture book code */
2
+ export declare type BookCode = (typeof VALID_BOOK_CODES)[number];
3
+
4
+ export declare const EMPTY_USJ: Readonly<Usj>;
5
+
6
+ export declare const EMPTY_USX = "<usx version=\"3.1\" />";
7
+
8
+ /**
9
+ * Converts a USJ JSONPath string into an array of indexes.
10
+ *
11
+ * @param jsonPath - The USJ JSONPath string to convert. It must start with `$` and contain `.content[index]` segments.
12
+ * @returns An array of numeric indexes extracted from the JSONPath.
13
+ * @throws Will throw an error if the JSONPath does not start with `$`.
14
+ */
15
+ export declare function indexesFromUsjJsonPath(jsonPath: string): number[];
16
+
17
+ export declare function isValidBookCode(code: string): boolean;
18
+
19
+ /** List of known properties of `MarkerObject` */
20
+ export declare const MARKER_OBJECT_PROPS: (keyof MarkerObject)[];
21
+
22
+ /** Single piece of Scripture content */
23
+ export declare type MarkerContent = string | MarkerObject;
24
+
25
+ /** A Scripture Marker and its contents */
26
+ export declare interface MarkerObject {
27
+ /**
28
+ * The kind/category of node or element this is, corresponding the USFM marker and USX node
29
+ * @example `para`, `verse`, `char`
30
+ */
31
+ type: string;
32
+ /**
33
+ * The corresponding marker in USFM or style in USX
34
+ * @example `p`, `v`, `nd`
35
+ */
36
+ marker: string;
37
+ /** This marker's contents laid out in order */
38
+ content?: MarkerContent[];
39
+ /** Indicates the Book-chapter-verse value in the paragraph based structure */
40
+ sid?: string;
41
+ /** Milestone end ID, matches start ID (not currently included in USJ spec) */
42
+ eid?: string;
43
+ /** Chapter number or verse number */
44
+ number?: string;
45
+ /** The 3-letter book code in ID element */
46
+ code?: BookCode;
47
+ /** Alternate chapter number or verse number */
48
+ altnumber?: string;
49
+ /** Published character of chapter or verse */
50
+ pubnumber?: string;
51
+ /** Caller character for footnotes and cross-refs */
52
+ caller?: string;
53
+ /** Alignment of table cells */
54
+ align?: string;
55
+ /** Category of extended study bible sections */
56
+ category?: string;
57
+ }
58
+
59
+ /** Scripture data represented in JSON format. Data compatible transformation from USX/USFM */
60
+ export declare interface Usj {
61
+ /** The USJ spec type */
62
+ type: typeof USJ_TYPE;
63
+ /** The USJ spec version */
64
+ version: typeof USJ_VERSION;
65
+ /** The JSON representation of scripture contents from USFM/USX */
66
+ content: MarkerContent[];
67
+ }
68
+
69
+ /** The USJ spec type */
70
+ export declare const USJ_TYPE = "USJ";
71
+
72
+ /** The USJ spec version */
73
+ export declare const USJ_VERSION = "3.1";
74
+
75
+ /**
76
+ * Converts an array of indexes into a USJ JSONPath string.
77
+ *
78
+ * @param indexes - An array of numeric indexes to convert.
79
+ * @returns A USJ JSONPath string constructed from the indexes.
80
+ */
81
+ export declare function usjJsonPathFromIndexes(indexes: number[]): string;
82
+
83
+ export declare function usjToUsxString(usj: Usj): string;
84
+
85
+ /** The USX spec type */
86
+ export declare const USX_TYPE = "usx";
87
+
88
+ /** The USX spec version */
89
+ export declare const USX_VERSION = "3.1";
90
+
91
+ export declare function usxStringToUsj(usxString: string): Usj;
92
+
93
+ declare const VALID_BOOK_CODES: readonly ["GEN", "EXO", "LEV", "NUM", "DEU", "JOS", "JDG", "RUT", "1SA", "2SA", "1KI", "2KI", "1CH", "2CH", "EZR", "NEH", "EST", "JOB", "PSA", "PRO", "ECC", "SNG", "ISA", "JER", "LAM", "EZK", "DAN", "HOS", "JOL", "AMO", "OBA", "JON", "MIC", "NAM", "HAB", "ZEP", "HAG", "ZEC", "MAL", "MAT", "MRK", "LUK", "JHN", "ACT", "ROM", "1CO", "2CO", "GAL", "EPH", "PHP", "COL", "1TH", "2TH", "1TI", "2TI", "TIT", "PHM", "HEB", "JAS", "1PE", "2PE", "1JN", "2JN", "3JN", "JUD", "REV", "TOB", "JDT", "ESG", "WIS", "SIR", "BAR", "LJE", "S3Y", "SUS", "BEL", "1MA", "2MA", "3MA", "4MA", "1ES", "2ES", "MAN", "PS2", "ODA", "PSS", "EZA", "5EZ", "6EZ", "DAG", "PS3", "2BA", "LBA", "JUB", "ENO", "1MQ", "2MQ", "3MQ", "REP", "4BA", "LAO", "FRT", "BAK", "OTH", "INT", "CNC", "GLO", "TDX", "NDX", "XXA", "XXB", "XXC", "XXD", "XXE", "XXF", "XXG"];
94
+
95
+ export { }
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { DOMParser as b, DOMImplementation as g } from "@xmldom/xmldom";
2
- const v = "USJ", J = "3.1", B = [
1
+ import { DOMParser as g, DOMImplementation as J } from "@xmldom/xmldom";
2
+ const p = "USJ", O = "3.1", _ = Object.freeze({ type: p, version: O, content: [] }), B = [
3
3
  "type",
4
4
  "marker",
5
5
  "content",
@@ -14,9 +14,9 @@ const v = "USJ", J = "3.1", B = [
14
14
  "category"
15
15
  ];
16
16
  function H(e) {
17
- return P.includes(e);
17
+ return M.includes(e);
18
18
  }
19
- const P = [
19
+ const M = [
20
20
  // Old Testament
21
21
  "GEN",
22
22
  "EXO",
@@ -137,16 +137,16 @@ const P = [
137
137
  "XXE",
138
138
  "XXF",
139
139
  "XXG"
140
- ], u = "usx", m = "3.1";
141
- function I(e) {
142
- const n = new b().parseFromString(e, "text/xml");
143
- return y(n.documentElement);
140
+ ], l = "usx", N = "3.1", I = `<${l} version="${N}" />`;
141
+ function C(e) {
142
+ const n = new g().parseFromString(e, "text/xml");
143
+ return m(n.documentElement);
144
144
  }
145
- function y(e) {
146
- const [t] = e ? p(e) : [{ content: [] }];
147
- return t.type = v, t.version = J, t;
145
+ function m(e) {
146
+ const [t] = e ? b(e) : [{ content: [] }];
147
+ return t.type = p, t.version = O, t;
148
148
  }
149
- function p(e) {
149
+ function b(e) {
150
150
  const t = {};
151
151
  let n = e.tagName, o, s, c = "append";
152
152
  if (["row", "cell"].includes(n) && (n = "table:" + n), e.attributes)
@@ -155,84 +155,88 @@ function p(e) {
155
155
  t.style && (o = t.style, delete t.style), t.vid && delete t.vid, t.status && delete t.status;
156
156
  let i = { type: n };
157
157
  o && (i.marker = o), i = { ...i, ...t }, e.firstChild && e.firstChild.nodeType === e.firstChild.TEXT_NODE && e.firstChild.nodeValue && E(e.firstChild.nodeValue) !== "" && (s = e.firstChild.nodeValue);
158
- const l = Array.from(e.childNodes);
158
+ const f = Array.from(e.childNodes);
159
159
  i.content = [], s && i.content.push(s);
160
- for (const r of l) {
160
+ for (const r of f) {
161
161
  if (r.tagName === void 0)
162
162
  continue;
163
- const [f, A] = p(r);
164
- switch (A) {
163
+ const [u, S] = b(r);
164
+ switch (S) {
165
165
  case "append":
166
- i.content.push(f);
166
+ i.content.push(u);
167
167
  break;
168
168
  case "merge":
169
- i.content = i.content.concat(f);
169
+ i.content = i.content.concat(u);
170
170
  break;
171
171
  }
172
172
  r.nextSibling && r.nextSibling.nodeType === r.nextSibling.TEXT_NODE && r.nextSibling.nodeValue && (E(r.nextSibling.nodeValue) !== "" || r.nextSibling.nodeValue === " ") && i.content.push(r.nextSibling.nodeValue);
173
173
  }
174
- return i.content.length === 0 && i.type !== u && delete i.content, "eid" in i && ["verse", "chapter"].includes(n) && (c = "ignore"), [i, c];
174
+ return i.content.length === 0 && i.type !== l && delete i.content, "eid" in i && ["verse", "chapter"].includes(n) && (c = "ignore"), [i, c];
175
175
  }
176
176
  function E(e) {
177
177
  return e.replace(/(^[ \t\n\r\f\v]+)|([ \t\n\r\f\v]+$)/g, "");
178
178
  }
179
179
  let d, a;
180
- function C(e) {
181
- const t = new g().createDocument("", u);
182
- return t.documentElement && (t.documentElement.setAttribute("version", m), M(e, t)), t.toString();
180
+ function V(e) {
181
+ const t = new J().createDocument("", l);
182
+ return t.documentElement && (t.documentElement.setAttribute("version", N), y(e, t)), t.toString();
183
183
  }
184
- function M(e, t) {
184
+ function y(e, t) {
185
185
  if (t.documentElement) {
186
186
  for (const [n, o] of e.content.entries()) {
187
187
  const s = n === e.content.length - 1;
188
- O(o, t.documentElement, t, s);
188
+ v(o, t.documentElement, t, s);
189
189
  }
190
190
  return t.documentElement ?? void 0;
191
191
  }
192
192
  }
193
- function O(e, t, n, o) {
193
+ function v(e, t, n, o) {
194
194
  let s, c, i;
195
195
  if (typeof e == "string") s = n.createTextNode(e);
196
196
  else if (c = e.type.replace("table:", ""), s = n.createElement(c), X(s, e), e.content)
197
- for (const [r, f] of e.content.entries()) {
198
- const A = r === e.content.length - 1;
199
- O(f, s, n, A);
197
+ for (const [r, u] of e.content.entries()) {
198
+ const S = r === e.content.length - 1;
199
+ v(u, s, n, S);
200
200
  }
201
- a && (c === "verse" || t.tagName === "para" && o) && (i = h(n, a), a = void 0), c === "verse" && typeof e != "string" && e.sid !== void 0 && (a = e.sid), d && (c === "chapter" || c === "para" && o) && (i = T(n, d), d = void 0), c === "chapter" && typeof e != "string" && e.sid !== void 0 && (d = e.sid);
202
- const l = t.nodeName === u && (i == null ? void 0 : i.tagName) === "verse";
203
- i && (!o || l) && t.appendChild(i), t.appendChild(s), i && o && !l && t.appendChild(i), o && t.nodeName === u && (a && t.appendChild(h(n, a)), d && t.appendChild(T(n, d)), a = void 0, d = void 0);
201
+ a && (c === "verse" || t.tagName === "para" && o) && (i = T(n, a), a = void 0), c === "verse" && typeof e != "string" && e.sid !== void 0 && (a = e.sid), d && (c === "chapter" || c === "para" && o) && (i = h(n, d), d = void 0), c === "chapter" && typeof e != "string" && e.sid !== void 0 && (d = e.sid);
202
+ const f = t.nodeName === l && (i == null ? void 0 : i.tagName) === "verse";
203
+ i && (!o || f) && t.appendChild(i), t.appendChild(s), i && o && !f && t.appendChild(i), o && t.nodeName === l && (a && t.appendChild(T(n, a)), d && t.appendChild(h(n, d)), a = void 0, d = void 0);
204
204
  }
205
205
  function X(e, t) {
206
206
  t.type === "unmatched" ? e.setAttribute("marker", t.marker) : e.setAttribute("style", t.marker);
207
207
  for (const [n, o] of Object.entries(t))
208
208
  o && !["type", "marker", "content"].includes(n) && e.setAttribute(n, o);
209
209
  }
210
- function h(e, t) {
210
+ function T(e, t) {
211
211
  const n = e.createElement("verse");
212
212
  return n.setAttribute("eid", t), n;
213
213
  }
214
- function T(e, t) {
214
+ function h(e, t) {
215
215
  const n = e.createElement("chapter");
216
216
  return n.setAttribute("eid", t), n;
217
217
  }
218
- const S = "$", N = ".content[";
219
- function V(e) {
220
- const t = e.split(N);
221
- if (t.shift() !== S)
222
- throw new Error(`indexesFromJsonPath: jsonPath didn't start with '${S}'`);
218
+ const A = "$", P = ".content[";
219
+ function D(e) {
220
+ const t = e.split(P);
221
+ if (t.shift() !== A)
222
+ throw new Error(`indexesFromJsonPath: jsonPath didn't start with '${A}'`);
223
223
  return t.map((o) => parseInt(o, 10));
224
224
  }
225
- function _(e) {
226
- return e.reduce((t, n) => `${t}${N}${n}]`, S);
225
+ function U(e) {
226
+ return e.reduce((t, n) => `${t}${P}${n}]`, A);
227
227
  }
228
228
  export {
229
+ _ as EMPTY_USJ,
230
+ I as EMPTY_USX,
229
231
  B as MARKER_OBJECT_PROPS,
230
- v as USJ_TYPE,
231
- J as USJ_VERSION,
232
- V as indexesFromUsjJsonPath,
232
+ p as USJ_TYPE,
233
+ O as USJ_VERSION,
234
+ l as USX_TYPE,
235
+ N as USX_VERSION,
236
+ D as indexesFromUsjJsonPath,
233
237
  H as isValidBookCode,
234
- _ as usjJsonPathFromIndexes,
235
- C as usjToUsxString,
236
- I as usxStringToUsj
238
+ U as usjJsonPathFromIndexes,
239
+ V as usjToUsxString,
240
+ C as usxStringToUsj
237
241
  };
238
242
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/converters/usj/usj.model.ts","../src/converters/usj/usx.model.ts","../src/converters/usj/usx-to-usj.ts","../src/converters/usj/usj-to-usx.ts","../src/converters/usj/jsonpath-indexes.ts"],"sourcesContent":["/**\n * Unified Scripture JSON (USJ) - The JSON variant of USFM and USX data models.\n * These types follow this schema:\n * @see https://github.com/usfm-bible/tcdocs/blob/usj/grammar/usj.js\n */\n\n/** The USJ spec type */\nexport const USJ_TYPE = \"USJ\";\n/** The USJ spec version */\nexport const USJ_VERSION = \"3.1\";\n/** List of known properties of `MarkerObject` */\nexport const MARKER_OBJECT_PROPS: (keyof MarkerObject)[] = [\n \"type\",\n \"marker\",\n \"content\",\n \"sid\",\n \"eid\",\n \"number\",\n \"code\",\n \"altnumber\",\n \"pubnumber\",\n \"caller\",\n \"align\",\n \"category\",\n];\n\n/** Single piece of Scripture content */\nexport type MarkerContent = string | MarkerObject;\n\n/** A Scripture Marker and its contents */\nexport type MarkerObject = {\n /**\n * The kind/category of node or element this is, corresponding the USFM marker and USX node\n * @example `para`, `verse`, `char`\n */\n type: string;\n /**\n * The corresponding marker in USFM or style in USX\n * @example `p`, `v`, `nd`\n */\n marker: string;\n /** This marker's contents laid out in order */\n content?: MarkerContent[];\n /** Indicates the Book-chapter-verse value in the paragraph based structure */\n sid?: string;\n /** Milestone end ID, matches start ID (not currently included in USJ spec) */\n eid?: string;\n /** Chapter number or verse number */\n number?: string;\n /** The 3-letter book code in ID element */\n code?: BookCode;\n /** Alternate chapter number or verse number */\n altnumber?: string;\n /** Published character of chapter or verse */\n pubnumber?: string;\n /** Caller character for footnotes and cross-refs */\n caller?: string;\n /** Alignment of table cells */\n align?: string;\n /** Category of extended study bible sections */\n category?: string;\n};\n\n/** Scripture data represented in JSON format. Data compatible transformation from USX/USFM */\nexport type Usj = {\n /** The USJ spec type */\n type: typeof USJ_TYPE;\n /** The USJ spec version */\n version: typeof USJ_VERSION;\n /** The JSON representation of scripture contents from USFM/USX */\n content: MarkerContent[];\n};\n\nexport function isValidBookCode(code: string): boolean {\n return VALID_BOOK_CODES.includes(code as BookCode);\n}\n\n/** 3-letter Scripture book code */\nexport type BookCode = (typeof VALID_BOOK_CODES)[number];\n\nconst VALID_BOOK_CODES = [\n // Old Testament\n \"GEN\",\n \"EXO\",\n \"LEV\",\n \"NUM\",\n \"DEU\",\n \"JOS\",\n \"JDG\",\n \"RUT\",\n \"1SA\",\n \"2SA\",\n \"1KI\",\n \"2KI\",\n \"1CH\",\n \"2CH\",\n \"EZR\",\n \"NEH\",\n \"EST\",\n \"JOB\",\n \"PSA\",\n \"PRO\",\n \"ECC\",\n \"SNG\",\n \"ISA\",\n \"JER\",\n \"LAM\",\n \"EZK\",\n \"DAN\",\n \"HOS\",\n \"JOL\",\n \"AMO\",\n \"OBA\",\n \"JON\",\n \"MIC\",\n \"NAM\",\n \"HAB\",\n \"ZEP\",\n \"HAG\",\n \"ZEC\",\n \"MAL\",\n // New Testament\n \"MAT\",\n \"MRK\",\n \"LUK\",\n \"JHN\",\n \"ACT\",\n \"ROM\",\n \"1CO\",\n \"2CO\",\n \"GAL\",\n \"EPH\",\n \"PHP\",\n \"COL\",\n \"1TH\",\n \"2TH\",\n \"1TI\",\n \"2TI\",\n \"TIT\",\n \"PHM\",\n \"HEB\",\n \"JAS\",\n \"1PE\",\n \"2PE\",\n \"1JN\",\n \"2JN\",\n \"3JN\",\n \"JUD\",\n \"REV\",\n // Deuterocanon\n \"TOB\",\n \"JDT\",\n \"ESG\",\n \"WIS\",\n \"SIR\",\n \"BAR\",\n \"LJE\",\n \"S3Y\",\n \"SUS\",\n \"BEL\",\n \"1MA\",\n \"2MA\",\n \"3MA\",\n \"4MA\",\n \"1ES\",\n \"2ES\",\n \"MAN\",\n \"PS2\",\n \"ODA\",\n \"PSS\",\n \"EZA\",\n \"5EZ\",\n \"6EZ\",\n \"DAG\",\n \"PS3\",\n \"2BA\",\n \"LBA\",\n \"JUB\",\n \"ENO\",\n \"1MQ\",\n \"2MQ\",\n \"3MQ\",\n \"REP\",\n \"4BA\",\n \"LAO\",\n // Non scripture\n \"FRT\",\n \"BAK\",\n \"OTH\",\n \"INT\",\n \"CNC\",\n \"GLO\",\n \"TDX\",\n \"NDX\",\n \"XXA\",\n \"XXB\",\n \"XXC\",\n \"XXD\",\n \"XXE\",\n \"XXF\",\n \"XXG\",\n] as const;\n","/**\n * Unified Scripture XML (USX).\n * These types follow this schema:\n * @see https://github.com/usfm-bible/tcdocs/blob/main/grammar/usx.rng\n */\n\n/** The USX spec type */\nexport const USX_TYPE = \"usx\";\n/** The USX spec version */\nexport const USX_VERSION = \"3.1\";\n","/**\n * Convert Scripture from USX to USJ.\n * Adapted to TypeScript from this file:\n * @see https://github.com/usfm-bible/usfmtc/blob/0afa385a1f282b286cc6bff7bbc953ae788aa10c/src/usfmtc/usjproc.py\n */\n\nimport { DOMParser, Element } from \"@xmldom/xmldom\";\nimport { MarkerContent, MarkerObject, USJ_TYPE, USJ_VERSION, Usj } from \"./usj.model\";\nimport { USX_TYPE } from \"./usx.model\";\n\ntype Action = \"append\" | \"merge\" | \"ignore\";\ntype Attribs = { [name: string]: string };\n\nexport function usxStringToUsj(usxString: string): Usj {\n const parser = new DOMParser();\n const inputUsxDom = parser.parseFromString(usxString, \"text/xml\");\n return usxDomToUsj(inputUsxDom.documentElement);\n}\n\nexport function usxDomToUsj(inputUsxDom: Element | null): Usj {\n const [outputJson] = inputUsxDom\n ? convertUsxRecurse(inputUsxDom)\n : [{ content: [] as MarkerContent[] } as Usj];\n outputJson.type = USJ_TYPE;\n outputJson.version = USJ_VERSION;\n return outputJson;\n}\n\nfunction convertUsxRecurse<T extends Usj | MarkerObject = Usj>(\n inputUsxElement: Element,\n): [outputJson: T, action: Action] {\n const attribs: Attribs = {};\n let type: string = inputUsxElement.tagName;\n let marker: string | undefined;\n let text: string | undefined;\n let action: Action = \"append\";\n\n if ([\"row\", \"cell\"].includes(type)) type = \"table:\" + type;\n if (inputUsxElement.attributes) {\n for (const attrib of Array.from(inputUsxElement.attributes)) {\n attribs[attrib.name] = attrib.value;\n }\n }\n\n if (attribs.style) {\n marker = attribs.style;\n delete attribs.style;\n }\n // dropping because presence of vid in para elements is not consistent in USX\n if (attribs.vid) delete attribs.vid;\n // Not dropping `attribs.closed` for backwards compatibility.\n // dropping because it is nonstandard derived metadata that could get out of date\n if (attribs.status) delete attribs.status;\n\n let outObj: T = { type } as T;\n if (marker) (outObj as MarkerObject).marker = marker;\n outObj = { ...outObj, ...attribs };\n\n if (\n inputUsxElement.firstChild &&\n inputUsxElement.firstChild.nodeType === inputUsxElement.firstChild.TEXT_NODE &&\n inputUsxElement.firstChild.nodeValue &&\n asciiTrim(inputUsxElement.firstChild.nodeValue) !== \"\"\n ) {\n text = inputUsxElement.firstChild.nodeValue;\n }\n\n const children = Array.from(inputUsxElement.childNodes);\n outObj.content = [];\n\n if (text) {\n outObj.content.push(text);\n }\n\n for (const child of children) {\n // ChildNodes are Elements.\n if ((child as Element).tagName === undefined) {\n continue;\n }\n // ChildNodes are Elements.\n const [childDict, whatToDo] = convertUsxRecurse<MarkerObject>(child as Element);\n\n switch (whatToDo) {\n case \"append\":\n outObj.content.push(childDict);\n break;\n case \"merge\":\n outObj.content = outObj.content.concat(childDict);\n break;\n case \"ignore\":\n break;\n default:\n break;\n }\n\n // Handle tail text\n if (\n child.nextSibling &&\n child.nextSibling.nodeType === child.nextSibling.TEXT_NODE &&\n child.nextSibling.nodeValue &&\n (asciiTrim(child.nextSibling.nodeValue) !== \"\" || child.nextSibling.nodeValue === \" \")\n ) {\n outObj.content.push(child.nextSibling.nodeValue);\n }\n }\n\n // For backward compatibility, not deleting content for type: chapter, verse, optbreak, ms OR\n // marker: va, ca, b.\n if (outObj.content.length === 0 && outObj.type !== USX_TYPE) {\n delete outObj.content;\n }\n\n if (\"eid\" in outObj && [\"verse\", \"chapter\"].includes(type)) {\n action = \"ignore\";\n }\n\n return [outObj, action];\n}\n\n/**\n * Removes leading and trailing ASCII whitespace.\n *\n * Only trim ASCII whitespace characters: space, tab, line feed, carriage return, form feed,\n * vertical tab.\n * @param str - The string to remove whitespace from.\n * @returns the string with leading and trailing whitespace removed.\n */\nfunction asciiTrim(str: string): string {\n return str.replace(/(^[ \\t\\n\\r\\f\\v]+)|([ \\t\\n\\r\\f\\v]+$)/g, \"\");\n}\n","/**\n * Convert Scripture from USJ to USX.\n * Adapted to TypeScript from this file:\n * @see https://github.com/usfm-bible/usfmtc/blob/0afa385a1f282b286cc6bff7bbc953ae788aa10c/src/usfmtc/usjproc.py\n */\n\nimport { DOMImplementation, Document, Element, Text } from \"@xmldom/xmldom\";\nimport { MarkerContent, MarkerObject, Usj } from \"./usj.model\";\nimport { USX_TYPE, USX_VERSION } from \"./usx.model\";\n\nlet chapterEid: string | undefined;\nlet verseEid: string | undefined;\n\nexport function usjToUsxString(usj: Usj): string {\n const usxDoc = new DOMImplementation().createDocument(\"\", USX_TYPE);\n if (usxDoc.documentElement) {\n usxDoc.documentElement.setAttribute(\"version\", USX_VERSION);\n usjToUsxDom(usj, usxDoc);\n }\n return usxDoc.toString();\n}\n\nexport function usjToUsxDom(usj: Usj, usxDoc: Document): Element | undefined {\n if (!usxDoc.documentElement) return undefined;\n\n for (const [index, markerContent] of usj.content.entries()) {\n const isLastItem = index === usj.content.length - 1;\n convertUsjRecurse(markerContent, usxDoc.documentElement, usxDoc, isLastItem);\n }\n return usxDoc.documentElement ?? undefined;\n}\n\nfunction convertUsjRecurse(\n markerContent: MarkerContent,\n parentElement: Element,\n usxDoc: Document,\n isLastItem: boolean,\n) {\n let element: Text | Element;\n let type: string | undefined;\n let eidElement: Element | undefined;\n if (typeof markerContent === \"string\") element = usxDoc.createTextNode(markerContent);\n else {\n type = markerContent.type.replace(\"table:\", \"\");\n element = usxDoc.createElement(type);\n setAttributes(element, markerContent);\n if (markerContent.content) {\n for (const [index, item] of markerContent.content.entries()) {\n const _isLastItem = index === markerContent.content.length - 1;\n convertUsjRecurse(item, element, usxDoc, _isLastItem);\n }\n }\n }\n\n // Create chapter and verse end elements from SID attributes.\n if (verseEid && (type === \"verse\" || (parentElement.tagName === \"para\" && isLastItem))) {\n eidElement = createVerseEndElement(usxDoc, verseEid);\n verseEid = undefined;\n }\n if (type === \"verse\" && typeof markerContent !== \"string\" && markerContent.sid !== undefined)\n verseEid = markerContent.sid;\n\n if (chapterEid && (type === \"chapter\" || (type === \"para\" && isLastItem))) {\n eidElement = createChapterEndElement(usxDoc, chapterEid);\n chapterEid = undefined;\n }\n if (type === \"chapter\" && typeof markerContent !== \"string\" && markerContent.sid !== undefined)\n chapterEid = markerContent.sid;\n\n // Append to parent.\n const isVerseInImpliedPara =\n parentElement.nodeName === USX_TYPE && eidElement?.tagName === \"verse\";\n if (eidElement && (!isLastItem || isVerseInImpliedPara)) parentElement.appendChild(eidElement);\n parentElement.appendChild(element);\n if (eidElement && isLastItem && !isVerseInImpliedPara) parentElement.appendChild(eidElement);\n\n // Allow for final chapter and verse end elements at the end of an implied para.\n if (isLastItem && parentElement.nodeName === USX_TYPE) {\n if (verseEid) parentElement.appendChild(createVerseEndElement(usxDoc, verseEid));\n if (chapterEid) parentElement.appendChild(createChapterEndElement(usxDoc, chapterEid));\n verseEid = undefined;\n chapterEid = undefined;\n }\n}\n\nfunction setAttributes(element: Element, markerContent: MarkerObject) {\n if (markerContent.type === \"unmatched\") element.setAttribute(\"marker\", markerContent.marker);\n else element.setAttribute(\"style\", markerContent.marker);\n for (const [key, value] of Object.entries(markerContent)) {\n if (value && ![\"type\", \"marker\", \"content\"].includes(key)) {\n element.setAttribute(key, value as string);\n }\n }\n}\n\nfunction createVerseEndElement(usxDoc: Document, verseEid: string): Element {\n const eidElement = usxDoc.createElement(\"verse\");\n eidElement.setAttribute(\"eid\", verseEid);\n return eidElement;\n}\n\nfunction createChapterEndElement(usxDoc: Document, chapterEid: string): Element {\n const eidElement = usxDoc.createElement(\"chapter\");\n eidElement.setAttribute(\"eid\", chapterEid);\n return eidElement;\n}\n","const JSON_PATH_START = \"$\";\nconst JSON_PATH_CONTENT = \".content[\";\n\n/**\n * Converts a USJ JSONPath string into an array of indexes.\n *\n * @param jsonPath - The USJ JSONPath string to convert. It must start with `$` and contain `.content[index]` segments.\n * @returns An array of numeric indexes extracted from the JSONPath.\n * @throws Will throw an error if the JSONPath does not start with `$`.\n */\nexport function indexesFromUsjJsonPath(jsonPath: string): number[] {\n const path = jsonPath.split(JSON_PATH_CONTENT);\n if (path.shift() !== JSON_PATH_START)\n throw new Error(`indexesFromJsonPath: jsonPath didn't start with '${JSON_PATH_START}'`);\n\n const indexes = path.map((str) => parseInt(str, 10));\n return indexes;\n}\n\n/**\n * Converts an array of indexes into a USJ JSONPath string.\n *\n * @param indexes - An array of numeric indexes to convert.\n * @returns A USJ JSONPath string constructed from the indexes.\n */\nexport function usjJsonPathFromIndexes(indexes: number[]): string {\n return indexes.reduce((path, index) => `${path}${JSON_PATH_CONTENT}${index}]`, JSON_PATH_START);\n}\n"],"names":["USJ_TYPE","USJ_VERSION","MARKER_OBJECT_PROPS","isValidBookCode","code","VALID_BOOK_CODES","USX_TYPE","USX_VERSION","usxStringToUsj","usxString","inputUsxDom","DOMParser","usxDomToUsj","outputJson","convertUsxRecurse","inputUsxElement","attribs","type","marker","text","action","attrib","outObj","asciiTrim","children","child","childDict","whatToDo","str","chapterEid","verseEid","usjToUsxString","usj","usxDoc","DOMImplementation","usjToUsxDom","index","markerContent","isLastItem","convertUsjRecurse","parentElement","element","eidElement","setAttributes","item","_isLastItem","createVerseEndElement","createChapterEndElement","isVerseInImpliedPara","key","value","JSON_PATH_START","JSON_PATH_CONTENT","indexesFromUsjJsonPath","jsonPath","path","usjJsonPathFromIndexes","indexes"],"mappings":";AAOO,MAAMA,IAAW,OAEXC,IAAc,OAEdC,IAA8C;AAAA,EACzD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAiDO,SAASC,EAAgBC,GAAuB;AACrD,SAAOC,EAAiB,SAASD,CAAgB;AACnD;AAKA,MAAMC,IAAmB;AAAA;AAAA,EAEvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GClMaC,IAAW,OAEXC,IAAc;ACIpB,SAASC,EAAeC,GAAwB;AAErD,QAAMC,IADS,IAAIC,EAAA,EACQ,gBAAgBF,GAAW,UAAU;AAChE,SAAOG,EAAYF,EAAY,eAAe;AAChD;AAEO,SAASE,EAAYF,GAAkC;AAC5D,QAAM,CAACG,CAAU,IAAIH,IACjBI,EAAkBJ,CAAW,IAC7B,CAAC,EAAE,SAAS,CAAA,GAA8B;AAC9C,SAAAG,EAAW,OAAOb,GAClBa,EAAW,UAAUZ,GACdY;AACT;AAEA,SAASC,EACPC,GACiC;AACjC,QAAMC,IAAmB,CAAA;AACzB,MAAIC,IAAeF,EAAgB,SAC/BG,GACAC,GACAC,IAAiB;AAGrB,MADI,CAAC,OAAO,MAAM,EAAE,SAASH,CAAI,UAAU,WAAWA,IAClDF,EAAgB;AAClB,eAAWM,KAAU,MAAM,KAAKN,EAAgB,UAAU;AACxD,MAAAC,EAAQK,EAAO,IAAI,IAAIA,EAAO;AAIlC,EAAIL,EAAQ,UACVE,IAASF,EAAQ,OACjB,OAAOA,EAAQ,QAGbA,EAAQ,OAAK,OAAOA,EAAQ,KAG5BA,EAAQ,UAAQ,OAAOA,EAAQ;AAEnC,MAAIM,IAAY,EAAE,MAAAL,EAAA;AAClB,EAAIC,MAASI,EAAwB,SAASJ,IAC9CI,IAAS,EAAE,GAAGA,GAAQ,GAAGN,EAAA,GAGvBD,EAAgB,cAChBA,EAAgB,WAAW,aAAaA,EAAgB,WAAW,aACnEA,EAAgB,WAAW,aAC3BQ,EAAUR,EAAgB,WAAW,SAAS,MAAM,OAEpDI,IAAOJ,EAAgB,WAAW;AAGpC,QAAMS,IAAW,MAAM,KAAKT,EAAgB,UAAU;AACtD,EAAAO,EAAO,UAAU,CAAA,GAEbH,KACFG,EAAO,QAAQ,KAAKH,CAAI;AAG1B,aAAWM,KAASD,GAAU;AAE5B,QAAKC,EAAkB,YAAY;AACjC;AAGF,UAAM,CAACC,GAAWC,CAAQ,IAAIb,EAAgCW,CAAgB;AAE9E,YAAQE,GAAA;AAAA,MACN,KAAK;AACH,QAAAL,EAAO,QAAQ,KAAKI,CAAS;AAC7B;AAAA,MACF,KAAK;AACH,QAAAJ,EAAO,UAAUA,EAAO,QAAQ,OAAOI,CAAS;AAChD;AAAA,IAIA;AAIJ,IACED,EAAM,eACNA,EAAM,YAAY,aAAaA,EAAM,YAAY,aACjDA,EAAM,YAAY,cACjBF,EAAUE,EAAM,YAAY,SAAS,MAAM,MAAMA,EAAM,YAAY,cAAc,QAElFH,EAAO,QAAQ,KAAKG,EAAM,YAAY,SAAS;AAAA,EACjD;AAKF,SAAIH,EAAO,QAAQ,WAAW,KAAKA,EAAO,SAAShB,KACjD,OAAOgB,EAAO,SAGZ,SAASA,KAAU,CAAC,SAAS,SAAS,EAAE,SAASL,CAAI,MACvDG,IAAS,WAGJ,CAACE,GAAQF,CAAM;AACxB;AAUA,SAASG,EAAUK,GAAqB;AACtC,SAAOA,EAAI,QAAQ,wCAAwC,EAAE;AAC/D;ACvHA,IAAIC,GACAC;AAEG,SAASC,EAAeC,GAAkB;AAC/C,QAAMC,IAAS,IAAIC,EAAA,EAAoB,eAAe,IAAI5B,CAAQ;AAClE,SAAI2B,EAAO,oBACTA,EAAO,gBAAgB,aAAa,WAAW1B,CAAW,GAC1D4B,EAAYH,GAAKC,CAAM,IAElBA,EAAO,SAAA;AAChB;AAEO,SAASE,EAAYH,GAAUC,GAAuC;AAC3E,MAAKA,EAAO,iBAEZ;AAAA,eAAW,CAACG,GAAOC,CAAa,KAAKL,EAAI,QAAQ,WAAW;AAC1D,YAAMM,IAAaF,MAAUJ,EAAI,QAAQ,SAAS;AAClD,MAAAO,EAAkBF,GAAeJ,EAAO,iBAAiBA,GAAQK,CAAU;AAAA,IAAA;AAE7E,WAAOL,EAAO,mBAAmB;AAAA;AACnC;AAEA,SAASM,EACPF,GACAG,GACAP,GACAK,GACA;AACA,MAAIG,GACAxB,GACAyB;AACJ,MAAI,OAAOL,KAAkB,SAAU,CAAAI,IAAUR,EAAO,eAAeI,CAAa;AAAA,WAElFpB,IAAOoB,EAAc,KAAK,QAAQ,UAAU,EAAE,GAC9CI,IAAUR,EAAO,cAAchB,CAAI,GACnC0B,EAAcF,GAASJ,CAAa,GAChCA,EAAc;AAChB,eAAW,CAACD,GAAOQ,CAAI,KAAKP,EAAc,QAAQ,WAAW;AAC3D,YAAMQ,IAAcT,MAAUC,EAAc,QAAQ,SAAS;AAC7D,MAAAE,EAAkBK,GAAMH,GAASR,GAAQY,CAAW;AAAA,IAAA;AAM1D,EAAIf,MAAab,MAAS,WAAYuB,EAAc,YAAY,UAAUF,OACxEI,IAAaI,EAAsBb,GAAQH,CAAQ,GACnDA,IAAW,SAETb,MAAS,WAAW,OAAOoB,KAAkB,YAAYA,EAAc,QAAQ,WACjFP,IAAWO,EAAc,MAEvBR,MAAeZ,MAAS,aAAcA,MAAS,UAAUqB,OAC3DI,IAAaK,EAAwBd,GAAQJ,CAAU,GACvDA,IAAa,SAEXZ,MAAS,aAAa,OAAOoB,KAAkB,YAAYA,EAAc,QAAQ,WACnFR,IAAaQ,EAAc;AAG7B,QAAMW,IACJR,EAAc,aAAalC,MAAYoC,KAAA,gBAAAA,EAAY,aAAY;AACjE,EAAIA,MAAe,CAACJ,KAAcU,MAAuBR,EAAc,YAAYE,CAAU,GAC7FF,EAAc,YAAYC,CAAO,GAC7BC,KAAcJ,KAAc,CAACU,KAAsBR,EAAc,YAAYE,CAAU,GAGvFJ,KAAcE,EAAc,aAAalC,MACvCwB,KAAUU,EAAc,YAAYM,EAAsBb,GAAQH,CAAQ,CAAC,GAC3ED,KAAYW,EAAc,YAAYO,EAAwBd,GAAQJ,CAAU,CAAC,GACrFC,IAAW,QACXD,IAAa;AAEjB;AAEA,SAASc,EAAcF,GAAkBJ,GAA6B;AACpE,EAAIA,EAAc,SAAS,gBAAqB,aAAa,UAAUA,EAAc,MAAM,IACtFI,EAAQ,aAAa,SAASJ,EAAc,MAAM;AACvD,aAAW,CAACY,GAAKC,CAAK,KAAK,OAAO,QAAQb,CAAa;AACrD,IAAIa,KAAS,CAAC,CAAC,QAAQ,UAAU,SAAS,EAAE,SAASD,CAAG,KACtDR,EAAQ,aAAaQ,GAAKC,CAAe;AAG/C;AAEA,SAASJ,EAAsBb,GAAkBH,GAA2B;AAC1E,QAAMY,IAAaT,EAAO,cAAc,OAAO;AAC/C,SAAAS,EAAW,aAAa,OAAOZ,CAAQ,GAChCY;AACT;AAEA,SAASK,EAAwBd,GAAkBJ,GAA6B;AAC9E,QAAMa,IAAaT,EAAO,cAAc,SAAS;AACjD,SAAAS,EAAW,aAAa,OAAOb,CAAU,GAClCa;AACT;ACzGA,MAAMS,IAAkB,KAClBC,IAAoB;AASnB,SAASC,EAAuBC,GAA4B;AACjE,QAAMC,IAAOD,EAAS,MAAMF,CAAiB;AAC7C,MAAIG,EAAK,YAAYJ;AACnB,UAAM,IAAI,MAAM,oDAAoDA,CAAe,GAAG;AAGxF,SADgBI,EAAK,IAAI,CAAC3B,MAAQ,SAASA,GAAK,EAAE,CAAC;AAErD;AAQO,SAAS4B,EAAuBC,GAA2B;AAChE,SAAOA,EAAQ,OAAO,CAACF,GAAMnB,MAAU,GAAGmB,CAAI,GAAGH,CAAiB,GAAGhB,CAAK,KAAKe,CAAe;AAChG;"}
1
+ {"version":3,"file":"index.js","sources":["../src/converters/usj/usj.model.ts","../src/converters/usj/usx.model.ts","../src/converters/usj/usx-to-usj.ts","../src/converters/usj/usj-to-usx.ts","../src/converters/usj/jsonpath-indexes.ts"],"sourcesContent":["/**\n * Unified Scripture JSON (USJ) - The JSON variant of USFM and USX data models.\n * These types follow this schema:\n * @see https://github.com/usfm-bible/tcdocs/blob/usj/grammar/usj.js\n */\n\n/** The USJ spec type */\nexport const USJ_TYPE = \"USJ\";\n\n/** The USJ spec version */\nexport const USJ_VERSION = \"3.1\";\n\nexport const EMPTY_USJ = Object.freeze<Usj>({ type: USJ_TYPE, version: USJ_VERSION, content: [] });\n\n/** List of known properties of `MarkerObject` */\nexport const MARKER_OBJECT_PROPS: (keyof MarkerObject)[] = [\n \"type\",\n \"marker\",\n \"content\",\n \"sid\",\n \"eid\",\n \"number\",\n \"code\",\n \"altnumber\",\n \"pubnumber\",\n \"caller\",\n \"align\",\n \"category\",\n];\n\n/** Single piece of Scripture content */\nexport type MarkerContent = string | MarkerObject;\n\n/** A Scripture Marker and its contents */\nexport interface MarkerObject {\n /**\n * The kind/category of node or element this is, corresponding the USFM marker and USX node\n * @example `para`, `verse`, `char`\n */\n type: string;\n /**\n * The corresponding marker in USFM or style in USX\n * @example `p`, `v`, `nd`\n */\n marker: string;\n /** This marker's contents laid out in order */\n content?: MarkerContent[];\n /** Indicates the Book-chapter-verse value in the paragraph based structure */\n sid?: string;\n /** Milestone end ID, matches start ID (not currently included in USJ spec) */\n eid?: string;\n /** Chapter number or verse number */\n number?: string;\n /** The 3-letter book code in ID element */\n code?: BookCode;\n /** Alternate chapter number or verse number */\n altnumber?: string;\n /** Published character of chapter or verse */\n pubnumber?: string;\n /** Caller character for footnotes and cross-refs */\n caller?: string;\n /** Alignment of table cells */\n align?: string;\n /** Category of extended study bible sections */\n category?: string;\n}\n\n/** Scripture data represented in JSON format. Data compatible transformation from USX/USFM */\nexport interface Usj {\n /** The USJ spec type */\n type: typeof USJ_TYPE;\n /** The USJ spec version */\n version: typeof USJ_VERSION;\n /** The JSON representation of scripture contents from USFM/USX */\n content: MarkerContent[];\n}\n\nexport function isValidBookCode(code: string): boolean {\n return VALID_BOOK_CODES.includes(code as BookCode);\n}\n\n/** 3-letter Scripture book code */\nexport type BookCode = (typeof VALID_BOOK_CODES)[number];\n\nconst VALID_BOOK_CODES = [\n // Old Testament\n \"GEN\",\n \"EXO\",\n \"LEV\",\n \"NUM\",\n \"DEU\",\n \"JOS\",\n \"JDG\",\n \"RUT\",\n \"1SA\",\n \"2SA\",\n \"1KI\",\n \"2KI\",\n \"1CH\",\n \"2CH\",\n \"EZR\",\n \"NEH\",\n \"EST\",\n \"JOB\",\n \"PSA\",\n \"PRO\",\n \"ECC\",\n \"SNG\",\n \"ISA\",\n \"JER\",\n \"LAM\",\n \"EZK\",\n \"DAN\",\n \"HOS\",\n \"JOL\",\n \"AMO\",\n \"OBA\",\n \"JON\",\n \"MIC\",\n \"NAM\",\n \"HAB\",\n \"ZEP\",\n \"HAG\",\n \"ZEC\",\n \"MAL\",\n // New Testament\n \"MAT\",\n \"MRK\",\n \"LUK\",\n \"JHN\",\n \"ACT\",\n \"ROM\",\n \"1CO\",\n \"2CO\",\n \"GAL\",\n \"EPH\",\n \"PHP\",\n \"COL\",\n \"1TH\",\n \"2TH\",\n \"1TI\",\n \"2TI\",\n \"TIT\",\n \"PHM\",\n \"HEB\",\n \"JAS\",\n \"1PE\",\n \"2PE\",\n \"1JN\",\n \"2JN\",\n \"3JN\",\n \"JUD\",\n \"REV\",\n // Deuterocanon\n \"TOB\",\n \"JDT\",\n \"ESG\",\n \"WIS\",\n \"SIR\",\n \"BAR\",\n \"LJE\",\n \"S3Y\",\n \"SUS\",\n \"BEL\",\n \"1MA\",\n \"2MA\",\n \"3MA\",\n \"4MA\",\n \"1ES\",\n \"2ES\",\n \"MAN\",\n \"PS2\",\n \"ODA\",\n \"PSS\",\n \"EZA\",\n \"5EZ\",\n \"6EZ\",\n \"DAG\",\n \"PS3\",\n \"2BA\",\n \"LBA\",\n \"JUB\",\n \"ENO\",\n \"1MQ\",\n \"2MQ\",\n \"3MQ\",\n \"REP\",\n \"4BA\",\n \"LAO\",\n // Non scripture\n \"FRT\",\n \"BAK\",\n \"OTH\",\n \"INT\",\n \"CNC\",\n \"GLO\",\n \"TDX\",\n \"NDX\",\n \"XXA\",\n \"XXB\",\n \"XXC\",\n \"XXD\",\n \"XXE\",\n \"XXF\",\n \"XXG\",\n] as const;\n","/**\n * Unified Scripture XML (USX).\n * These types follow this schema:\n * @see https://github.com/usfm-bible/tcdocs/blob/main/grammar/usx.rng\n */\n\n/** The USX spec type */\nexport const USX_TYPE = \"usx\";\n\n/** The USX spec version */\nexport const USX_VERSION = \"3.1\";\n\nexport const EMPTY_USX = `<${USX_TYPE} version=\"${USX_VERSION}\" />`;\n","/**\n * Convert Scripture from USX to USJ.\n * Adapted to TypeScript from this file:\n * @see https://github.com/usfm-bible/usfmtc/blob/0afa385a1f282b286cc6bff7bbc953ae788aa10c/src/usfmtc/usjproc.py\n */\n\nimport { DOMParser, Element } from \"@xmldom/xmldom\";\nimport { MarkerContent, MarkerObject, USJ_TYPE, USJ_VERSION, Usj } from \"./usj.model.js\";\nimport { USX_TYPE } from \"./usx.model.js\";\n\ntype Action = \"append\" | \"merge\" | \"ignore\";\ninterface Attribs {\n [name: string]: string;\n}\n\nexport function usxStringToUsj(usxString: string): Usj {\n const parser = new DOMParser();\n const inputUsxDom = parser.parseFromString(usxString, \"text/xml\");\n return usxDomToUsj(inputUsxDom.documentElement);\n}\n\nexport function usxDomToUsj(inputUsxDom: Element | null): Usj {\n const [outputJson] = inputUsxDom\n ? convertUsxRecurse(inputUsxDom)\n : [{ content: [] as MarkerContent[] } as Usj];\n outputJson.type = USJ_TYPE;\n outputJson.version = USJ_VERSION;\n return outputJson;\n}\n\nfunction convertUsxRecurse<T extends Usj | MarkerObject = Usj>(\n inputUsxElement: Element,\n): [outputJson: T, action: Action] {\n const attribs: Attribs = {};\n let type: string = inputUsxElement.tagName;\n let marker: string | undefined;\n let text: string | undefined;\n let action: Action = \"append\";\n\n if ([\"row\", \"cell\"].includes(type)) type = \"table:\" + type;\n if (inputUsxElement.attributes) {\n for (const attrib of Array.from(inputUsxElement.attributes)) {\n attribs[attrib.name] = attrib.value;\n }\n }\n\n if (attribs.style) {\n marker = attribs.style;\n delete attribs.style;\n }\n // dropping because presence of vid in para elements is not consistent in USX\n if (attribs.vid) delete attribs.vid;\n // Not dropping `attribs.closed` for backwards compatibility.\n // dropping because it is nonstandard derived metadata that could get out of date\n if (attribs.status) delete attribs.status;\n\n let outObj: T = { type } as T;\n if (marker) (outObj as MarkerObject).marker = marker;\n outObj = { ...outObj, ...attribs };\n\n if (\n inputUsxElement.firstChild &&\n inputUsxElement.firstChild.nodeType === inputUsxElement.firstChild.TEXT_NODE &&\n inputUsxElement.firstChild.nodeValue &&\n asciiTrim(inputUsxElement.firstChild.nodeValue) !== \"\"\n ) {\n text = inputUsxElement.firstChild.nodeValue;\n }\n\n const children = Array.from(inputUsxElement.childNodes);\n outObj.content = [];\n\n if (text) {\n outObj.content.push(text);\n }\n\n for (const child of children) {\n // ChildNodes are Elements.\n if ((child as Element).tagName === undefined) {\n continue;\n }\n // ChildNodes are Elements.\n const [childDict, whatToDo] = convertUsxRecurse<MarkerObject>(child as Element);\n\n switch (whatToDo) {\n case \"append\":\n outObj.content.push(childDict);\n break;\n case \"merge\":\n outObj.content = outObj.content.concat(childDict);\n break;\n case \"ignore\":\n break;\n default:\n break;\n }\n\n // Handle tail text\n if (\n child.nextSibling &&\n child.nextSibling.nodeType === child.nextSibling.TEXT_NODE &&\n child.nextSibling.nodeValue &&\n (asciiTrim(child.nextSibling.nodeValue) !== \"\" || child.nextSibling.nodeValue === \" \")\n ) {\n outObj.content.push(child.nextSibling.nodeValue);\n }\n }\n\n // For backward compatibility, not deleting content for type: chapter, verse, optbreak, ms OR\n // marker: va, ca, b.\n if (outObj.content.length === 0 && outObj.type !== USX_TYPE) {\n delete outObj.content;\n }\n\n if (\"eid\" in outObj && [\"verse\", \"chapter\"].includes(type)) {\n action = \"ignore\";\n }\n\n return [outObj, action];\n}\n\n/**\n * Removes leading and trailing ASCII whitespace.\n *\n * Only trim ASCII whitespace characters: space, tab, line feed, carriage return, form feed,\n * vertical tab.\n * @param str - The string to remove whitespace from.\n * @returns the string with leading and trailing whitespace removed.\n */\nfunction asciiTrim(str: string): string {\n return str.replace(/(^[ \\t\\n\\r\\f\\v]+)|([ \\t\\n\\r\\f\\v]+$)/g, \"\");\n}\n","/**\n * Convert Scripture from USJ to USX.\n * Adapted to TypeScript from this file:\n * @see https://github.com/usfm-bible/usfmtc/blob/0afa385a1f282b286cc6bff7bbc953ae788aa10c/src/usfmtc/usjproc.py\n */\n\nimport { DOMImplementation, Document, Element, Text } from \"@xmldom/xmldom\";\nimport { MarkerContent, MarkerObject, Usj } from \"./usj.model.js\";\nimport { USX_TYPE, USX_VERSION } from \"./usx.model.js\";\n\nlet chapterEid: string | undefined;\nlet verseEid: string | undefined;\n\nexport function usjToUsxString(usj: Usj): string {\n const usxDoc = new DOMImplementation().createDocument(\"\", USX_TYPE);\n if (usxDoc.documentElement) {\n usxDoc.documentElement.setAttribute(\"version\", USX_VERSION);\n usjToUsxDom(usj, usxDoc);\n }\n return usxDoc.toString();\n}\n\nexport function usjToUsxDom(usj: Usj, usxDoc: Document): Element | undefined {\n if (!usxDoc.documentElement) return undefined;\n\n for (const [index, markerContent] of usj.content.entries()) {\n const isLastItem = index === usj.content.length - 1;\n convertUsjRecurse(markerContent, usxDoc.documentElement, usxDoc, isLastItem);\n }\n return usxDoc.documentElement ?? undefined;\n}\n\nfunction convertUsjRecurse(\n markerContent: MarkerContent,\n parentElement: Element,\n usxDoc: Document,\n isLastItem: boolean,\n) {\n let element: Text | Element;\n let type: string | undefined;\n let eidElement: Element | undefined;\n if (typeof markerContent === \"string\") element = usxDoc.createTextNode(markerContent);\n else {\n type = markerContent.type.replace(\"table:\", \"\");\n element = usxDoc.createElement(type);\n setAttributes(element, markerContent);\n if (markerContent.content) {\n for (const [index, item] of markerContent.content.entries()) {\n const _isLastItem = index === markerContent.content.length - 1;\n convertUsjRecurse(item, element, usxDoc, _isLastItem);\n }\n }\n }\n\n // Create chapter and verse end elements from SID attributes.\n if (verseEid && (type === \"verse\" || (parentElement.tagName === \"para\" && isLastItem))) {\n eidElement = createVerseEndElement(usxDoc, verseEid);\n verseEid = undefined;\n }\n if (type === \"verse\" && typeof markerContent !== \"string\" && markerContent.sid !== undefined)\n verseEid = markerContent.sid;\n\n if (chapterEid && (type === \"chapter\" || (type === \"para\" && isLastItem))) {\n eidElement = createChapterEndElement(usxDoc, chapterEid);\n chapterEid = undefined;\n }\n if (type === \"chapter\" && typeof markerContent !== \"string\" && markerContent.sid !== undefined)\n chapterEid = markerContent.sid;\n\n // Append to parent.\n const isVerseInImpliedPara =\n parentElement.nodeName === USX_TYPE && eidElement?.tagName === \"verse\";\n if (eidElement && (!isLastItem || isVerseInImpliedPara)) parentElement.appendChild(eidElement);\n parentElement.appendChild(element);\n if (eidElement && isLastItem && !isVerseInImpliedPara) parentElement.appendChild(eidElement);\n\n // Allow for final chapter and verse end elements at the end of an implied para.\n if (isLastItem && parentElement.nodeName === USX_TYPE) {\n if (verseEid) parentElement.appendChild(createVerseEndElement(usxDoc, verseEid));\n if (chapterEid) parentElement.appendChild(createChapterEndElement(usxDoc, chapterEid));\n verseEid = undefined;\n chapterEid = undefined;\n }\n}\n\nfunction setAttributes(element: Element, markerContent: MarkerObject) {\n if (markerContent.type === \"unmatched\") element.setAttribute(\"marker\", markerContent.marker);\n else element.setAttribute(\"style\", markerContent.marker);\n for (const [key, value] of Object.entries(markerContent)) {\n if (value && ![\"type\", \"marker\", \"content\"].includes(key)) {\n element.setAttribute(key, value as string);\n }\n }\n}\n\nfunction createVerseEndElement(usxDoc: Document, verseEid: string): Element {\n const eidElement = usxDoc.createElement(\"verse\");\n eidElement.setAttribute(\"eid\", verseEid);\n return eidElement;\n}\n\nfunction createChapterEndElement(usxDoc: Document, chapterEid: string): Element {\n const eidElement = usxDoc.createElement(\"chapter\");\n eidElement.setAttribute(\"eid\", chapterEid);\n return eidElement;\n}\n","const JSON_PATH_START = \"$\";\nconst JSON_PATH_CONTENT = \".content[\";\n\n/**\n * Converts a USJ JSONPath string into an array of indexes.\n *\n * @param jsonPath - The USJ JSONPath string to convert. It must start with `$` and contain `.content[index]` segments.\n * @returns An array of numeric indexes extracted from the JSONPath.\n * @throws Will throw an error if the JSONPath does not start with `$`.\n */\nexport function indexesFromUsjJsonPath(jsonPath: string): number[] {\n const path = jsonPath.split(JSON_PATH_CONTENT);\n if (path.shift() !== JSON_PATH_START)\n throw new Error(`indexesFromJsonPath: jsonPath didn't start with '${JSON_PATH_START}'`);\n\n const indexes = path.map((str) => parseInt(str, 10));\n return indexes;\n}\n\n/**\n * Converts an array of indexes into a USJ JSONPath string.\n *\n * @param indexes - An array of numeric indexes to convert.\n * @returns A USJ JSONPath string constructed from the indexes.\n */\nexport function usjJsonPathFromIndexes(indexes: number[]): string {\n return indexes.reduce((path, index) => `${path}${JSON_PATH_CONTENT}${index}]`, JSON_PATH_START);\n}\n"],"names":["USJ_TYPE","USJ_VERSION","EMPTY_USJ","MARKER_OBJECT_PROPS","isValidBookCode","code","VALID_BOOK_CODES","USX_TYPE","USX_VERSION","EMPTY_USX","usxStringToUsj","usxString","inputUsxDom","DOMParser","usxDomToUsj","outputJson","convertUsxRecurse","inputUsxElement","attribs","type","marker","text","action","attrib","outObj","asciiTrim","children","child","childDict","whatToDo","str","chapterEid","verseEid","usjToUsxString","usj","usxDoc","DOMImplementation","usjToUsxDom","index","markerContent","isLastItem","convertUsjRecurse","parentElement","element","eidElement","setAttributes","item","_isLastItem","createVerseEndElement","createChapterEndElement","isVerseInImpliedPara","key","value","JSON_PATH_START","JSON_PATH_CONTENT","indexesFromUsjJsonPath","jsonPath","path","usjJsonPathFromIndexes","indexes"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eten-tech-foundation/scripture-utilities",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Utilities for working with Scripture data.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/eten-tech-foundation/scripture-editors/tree/main/packages/utilities#readme",
@@ -16,15 +16,17 @@
16
16
  "module": "dist/index.js",
17
17
  "types": "dist/index.d.ts",
18
18
  "exports": {
19
+ "./package.json": "./package.json",
19
20
  ".": {
21
+ "development": "./src/index.ts",
20
22
  "types": "./dist/index.d.ts",
21
23
  "import": "./dist/index.js",
22
- "require": "./dist/index.cjs"
24
+ "require": "./dist/index.cjs",
25
+ "default": "./dist/index.js"
23
26
  }
24
27
  },
25
28
  "files": [
26
29
  "dist",
27
- "!dist/package.json",
28
30
  "src",
29
31
  "!src/**/*.test.ts",
30
32
  "!src/**/*.data.ts"
@@ -33,12 +35,14 @@
33
35
  "@xmldom/xmldom": "^0.9.8"
34
36
  },
35
37
  "devDependencies": {
36
- "lexical": "^0.33.0"
38
+ "lexical": "^0.34.0"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public",
42
+ "provenance": true
37
43
  },
38
44
  "volta": {
39
45
  "extends": "../../package.json"
40
46
  },
41
- "scripts": {
42
- "prepublish": "cd ../.. && nx build utilities"
43
- }
47
+ "scripts": {}
44
48
  }
@@ -5,8 +5,8 @@
5
5
  */
6
6
 
7
7
  import { DOMImplementation, Document, Element, Text } from "@xmldom/xmldom";
8
- import { MarkerContent, MarkerObject, Usj } from "./usj.model";
9
- import { USX_TYPE, USX_VERSION } from "./usx.model";
8
+ import { MarkerContent, MarkerObject, Usj } from "./usj.model.js";
9
+ import { USX_TYPE, USX_VERSION } from "./usx.model.js";
10
10
 
11
11
  let chapterEid: string | undefined;
12
12
  let verseEid: string | undefined;
@@ -6,8 +6,12 @@
6
6
 
7
7
  /** The USJ spec type */
8
8
  export const USJ_TYPE = "USJ";
9
+
9
10
  /** The USJ spec version */
10
11
  export const USJ_VERSION = "3.1";
12
+
13
+ export const EMPTY_USJ = Object.freeze<Usj>({ type: USJ_TYPE, version: USJ_VERSION, content: [] });
14
+
11
15
  /** List of known properties of `MarkerObject` */
12
16
  export const MARKER_OBJECT_PROPS: (keyof MarkerObject)[] = [
13
17
  "type",
@@ -28,7 +32,7 @@ export const MARKER_OBJECT_PROPS: (keyof MarkerObject)[] = [
28
32
  export type MarkerContent = string | MarkerObject;
29
33
 
30
34
  /** A Scripture Marker and its contents */
31
- export type MarkerObject = {
35
+ export interface MarkerObject {
32
36
  /**
33
37
  * The kind/category of node or element this is, corresponding the USFM marker and USX node
34
38
  * @example `para`, `verse`, `char`
@@ -59,17 +63,17 @@ export type MarkerObject = {
59
63
  align?: string;
60
64
  /** Category of extended study bible sections */
61
65
  category?: string;
62
- };
66
+ }
63
67
 
64
68
  /** Scripture data represented in JSON format. Data compatible transformation from USX/USFM */
65
- export type Usj = {
69
+ export interface Usj {
66
70
  /** The USJ spec type */
67
71
  type: typeof USJ_TYPE;
68
72
  /** The USJ spec version */
69
73
  version: typeof USJ_VERSION;
70
74
  /** The JSON representation of scripture contents from USFM/USX */
71
75
  content: MarkerContent[];
72
- };
76
+ }
73
77
 
74
78
  export function isValidBookCode(code: string): boolean {
75
79
  return VALID_BOOK_CODES.includes(code as BookCode);
@@ -5,11 +5,13 @@
5
5
  */
6
6
 
7
7
  import { DOMParser, Element } from "@xmldom/xmldom";
8
- import { MarkerContent, MarkerObject, USJ_TYPE, USJ_VERSION, Usj } from "./usj.model";
9
- import { USX_TYPE } from "./usx.model";
8
+ import { MarkerContent, MarkerObject, USJ_TYPE, USJ_VERSION, Usj } from "./usj.model.js";
9
+ import { USX_TYPE } from "./usx.model.js";
10
10
 
11
11
  type Action = "append" | "merge" | "ignore";
12
- type Attribs = { [name: string]: string };
12
+ interface Attribs {
13
+ [name: string]: string;
14
+ }
13
15
 
14
16
  export function usxStringToUsj(usxString: string): Usj {
15
17
  const parser = new DOMParser();
@@ -6,5 +6,8 @@
6
6
 
7
7
  /** The USX spec type */
8
8
  export const USX_TYPE = "usx";
9
+
9
10
  /** The USX spec version */
10
11
  export const USX_VERSION = "3.1";
12
+
13
+ export const EMPTY_USX = `<${USX_TYPE} version="${USX_VERSION}" />`;
package/src/index.ts CHANGED
@@ -1,10 +1,15 @@
1
- export type { Usj, BookCode, MarkerContent, MarkerObject } from "./converters/usj/usj.model";
1
+ export type { Usj, BookCode, MarkerContent, MarkerObject } from "./converters/usj/usj.model.js";
2
2
  export {
3
+ EMPTY_USJ,
3
4
  MARKER_OBJECT_PROPS,
4
5
  USJ_TYPE,
5
6
  USJ_VERSION,
6
7
  isValidBookCode,
7
- } from "./converters/usj/usj.model";
8
- export { usxStringToUsj } from "./converters/usj/usx-to-usj";
9
- export { usjToUsxString } from "./converters/usj/usj-to-usx";
10
- export { indexesFromUsjJsonPath, usjJsonPathFromIndexes } from "./converters/usj/jsonpath-indexes";
8
+ } from "./converters/usj/usj.model.js";
9
+ export { EMPTY_USX, USX_TYPE, USX_VERSION } from "./converters/usj/usx.model.js";
10
+ export { usxStringToUsj } from "./converters/usj/usx-to-usj.js";
11
+ export { usjToUsxString } from "./converters/usj/usj-to-usx.js";
12
+ export {
13
+ indexesFromUsjJsonPath,
14
+ usjJsonPathFromIndexes,
15
+ } from "./converters/usj/jsonpath-indexes.js";
@@ -1,15 +0,0 @@
1
- /**
2
- * Converts a USJ JSONPath string into an array of indexes.
3
- *
4
- * @param jsonPath - The USJ JSONPath string to convert. It must start with `$` and contain `.content[index]` segments.
5
- * @returns An array of numeric indexes extracted from the JSONPath.
6
- * @throws Will throw an error if the JSONPath does not start with `$`.
7
- */
8
- export declare function indexesFromUsjJsonPath(jsonPath: string): number[];
9
- /**
10
- * Converts an array of indexes into a USJ JSONPath string.
11
- *
12
- * @param indexes - An array of numeric indexes to convert.
13
- * @returns A USJ JSONPath string constructed from the indexes.
14
- */
15
- export declare function usjJsonPathFromIndexes(indexes: number[]): string;
@@ -1,4 +0,0 @@
1
- import { Document, Element } from '@xmldom/xmldom';
2
- import { Usj } from './usj.model';
3
- export declare function usjToUsxString(usj: Usj): string;
4
- export declare function usjToUsxDom(usj: Usj, usxDoc: Document): Element | undefined;
@@ -1,60 +0,0 @@
1
- /**
2
- * Unified Scripture JSON (USJ) - The JSON variant of USFM and USX data models.
3
- * These types follow this schema:
4
- * @see https://github.com/usfm-bible/tcdocs/blob/usj/grammar/usj.js
5
- */
6
- /** The USJ spec type */
7
- export declare const USJ_TYPE = "USJ";
8
- /** The USJ spec version */
9
- export declare const USJ_VERSION = "3.1";
10
- /** List of known properties of `MarkerObject` */
11
- export declare const MARKER_OBJECT_PROPS: (keyof MarkerObject)[];
12
- /** Single piece of Scripture content */
13
- export type MarkerContent = string | MarkerObject;
14
- /** A Scripture Marker and its contents */
15
- export type MarkerObject = {
16
- /**
17
- * The kind/category of node or element this is, corresponding the USFM marker and USX node
18
- * @example `para`, `verse`, `char`
19
- */
20
- type: string;
21
- /**
22
- * The corresponding marker in USFM or style in USX
23
- * @example `p`, `v`, `nd`
24
- */
25
- marker: string;
26
- /** This marker's contents laid out in order */
27
- content?: MarkerContent[];
28
- /** Indicates the Book-chapter-verse value in the paragraph based structure */
29
- sid?: string;
30
- /** Milestone end ID, matches start ID (not currently included in USJ spec) */
31
- eid?: string;
32
- /** Chapter number or verse number */
33
- number?: string;
34
- /** The 3-letter book code in ID element */
35
- code?: BookCode;
36
- /** Alternate chapter number or verse number */
37
- altnumber?: string;
38
- /** Published character of chapter or verse */
39
- pubnumber?: string;
40
- /** Caller character for footnotes and cross-refs */
41
- caller?: string;
42
- /** Alignment of table cells */
43
- align?: string;
44
- /** Category of extended study bible sections */
45
- category?: string;
46
- };
47
- /** Scripture data represented in JSON format. Data compatible transformation from USX/USFM */
48
- export type Usj = {
49
- /** The USJ spec type */
50
- type: typeof USJ_TYPE;
51
- /** The USJ spec version */
52
- version: typeof USJ_VERSION;
53
- /** The JSON representation of scripture contents from USFM/USX */
54
- content: MarkerContent[];
55
- };
56
- export declare function isValidBookCode(code: string): boolean;
57
- /** 3-letter Scripture book code */
58
- export type BookCode = (typeof VALID_BOOK_CODES)[number];
59
- declare const VALID_BOOK_CODES: readonly ["GEN", "EXO", "LEV", "NUM", "DEU", "JOS", "JDG", "RUT", "1SA", "2SA", "1KI", "2KI", "1CH", "2CH", "EZR", "NEH", "EST", "JOB", "PSA", "PRO", "ECC", "SNG", "ISA", "JER", "LAM", "EZK", "DAN", "HOS", "JOL", "AMO", "OBA", "JON", "MIC", "NAM", "HAB", "ZEP", "HAG", "ZEC", "MAL", "MAT", "MRK", "LUK", "JHN", "ACT", "ROM", "1CO", "2CO", "GAL", "EPH", "PHP", "COL", "1TH", "2TH", "1TI", "2TI", "TIT", "PHM", "HEB", "JAS", "1PE", "2PE", "1JN", "2JN", "3JN", "JUD", "REV", "TOB", "JDT", "ESG", "WIS", "SIR", "BAR", "LJE", "S3Y", "SUS", "BEL", "1MA", "2MA", "3MA", "4MA", "1ES", "2ES", "MAN", "PS2", "ODA", "PSS", "EZA", "5EZ", "6EZ", "DAG", "PS3", "2BA", "LBA", "JUB", "ENO", "1MQ", "2MQ", "3MQ", "REP", "4BA", "LAO", "FRT", "BAK", "OTH", "INT", "CNC", "GLO", "TDX", "NDX", "XXA", "XXB", "XXC", "XXD", "XXE", "XXF", "XXG"];
60
- export {};
@@ -1,4 +0,0 @@
1
- import { Element } from '@xmldom/xmldom';
2
- import { Usj } from './usj.model';
3
- export declare function usxStringToUsj(usxString: string): Usj;
4
- export declare function usxDomToUsj(inputUsxDom: Element | null): Usj;
@@ -1,9 +0,0 @@
1
- /**
2
- * Unified Scripture XML (USX).
3
- * These types follow this schema:
4
- * @see https://github.com/usfm-bible/tcdocs/blob/main/grammar/usx.rng
5
- */
6
- /** The USX spec type */
7
- export declare const USX_TYPE = "usx";
8
- /** The USX spec version */
9
- export declare const USX_VERSION = "3.1";