@eten-tech-foundation/scripture-utilities 0.1.4 → 0.1.6
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/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +363 -1
- package/dist/index.js +130 -88
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/converters/usj/converter.utils.ts +15 -0
- package/src/converters/usj/jsonpath-indexes.ts +7 -2
- package/src/converters/usj/usj-document-location.model.ts +238 -0
- package/src/converters/usj/usj-document-location.utils.ts +187 -0
- package/src/converters/usj/usx-to-usj.ts +2 -0
- package/src/index.ts +19 -6
- package/src/types/rollup-parseAst.d.ts +0 -5
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("@xmldom/xmldom"),X=new Set(["__proto__","prototype","constructor"]);function U(e){if(X.has(e))throw new Error(`The key "${e}" is not allowed to avoid prototype pollution.`)}const A="$",j=".content[";function k(e){const t=e.split(j);if(t.shift()!==A)throw new Error(`indexesFromJsonPath: jsonPath didn't start with '${A}'`);return t.map(r=>parseInt(r,10))}function R(e){return e.reduce((t,n)=>`${t}${j}${n}]`,A)}function M(e){return e!=null&&"jsonPath"in e&&!("offset"in e)&&!("closingMarkerOffset"in e)&&!("propertyOffset"in e)&&!("keyName"in e)}function g(e){return e!=null&&"jsonPath"in e&&"closingMarkerOffset"in e}function N(e){return e!=null&&"jsonPath"in e&&"offset"in e&&!("propertyOffset"in e)&&!("keyName"in e)}function b(e){return e!=null&&"jsonPath"in e&&"propertyOffset"in e}function m(e){return e!=null&&"jsonPath"in e&&"keyName"in e&&"keyOffset"in e}function L(e){return e!=null&&"jsonPath"in e&&"keyName"in e&&!("keyOffset"in e)&&!("keyClosingMarkerOffset"in e)}function J(e){return e!=null&&"jsonPath"in e&&"keyName"in e&&"keyClosingMarkerOffset"in e}function V(e){return e===void 0?"undefined":e===null?"null":J(e)?"UsjClosingAttributeMarkerLocation":m(e)?"UsjAttributeKeyLocation":L(e)?"UsjAttributeMarkerLocation":b(e)?"UsjPropertyValueLocation":g(e)?"UsjClosingMarkerLocation":N(e)?"UsjTextContentLocation":M(e)?"UsjMarkerLocation":"Unknown"}const a="usx",E="3.1",I=`<${a} version="${E}" />`;let c,f;function B(e){const t=new P.DOMImplementation().createDocument("",a);return t.documentElement&&(t.documentElement.setAttribute("version",E),D(e,t)),t.toString()}function D(e,t){if(t.documentElement){for(const[n,r]of e.content.entries()){const o=n===e.content.length-1;_(r,t.documentElement,t,o)}return t.documentElement??void 0}}function _(e,t,n,r){let o,u,i;if(typeof e=="string")o=n.createTextNode(e);else if(u=e.type.replace("table:",""),o=n.createElement(u),H(o,e),e.content)for(const[s,l]of e.content.entries()){const S=s===e.content.length-1;_(l,o,n,S)}f&&(u==="verse"||t.tagName==="para"&&r)&&(i=O(n,f),f=void 0),u==="verse"&&typeof e!="string"&&e.sid!==void 0&&(f=e.sid),c&&(u==="chapter"||u==="para"&&r)&&(i=h(n,c),c=void 0),u==="chapter"&&typeof e!="string"&&e.sid!==void 0&&(c=e.sid);const d=t.nodeName===a&&(i==null?void 0:i.tagName)==="verse";i&&(!r||d)&&t.appendChild(i),t.appendChild(o),i&&r&&!d&&t.appendChild(i),r&&t.nodeName===a&&(f&&t.appendChild(O(n,f)),c&&t.appendChild(h(n,c)),f=void 0,c=void 0)}function H(e,t){t.marker&&(t.type==="unmatched"?e.setAttribute("marker",t.marker):e.setAttribute("style",t.marker));for(const[n,r]of Object.entries(t))r&&!["type","marker","content"].includes(n)&&e.setAttribute(n,r)}function O(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 p="USJ",T="3.1",K=Object.freeze({type:p,version:T,content:[]}),x=["type","marker","content","sid","eid","number","code","altnumber","pubnumber","caller","align","category"];function w(e){return v.includes(e)}const v=["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"];function Y(e){const n=new P.DOMParser().parseFromString(e,"text/xml");return F(n.documentElement)}function F(e){const[t]=e?C(e):[{content:[]}];return t.type=p,t.version=T,t}function C(e){const t={};let n=e.tagName,r,o,u="append";if(["row","cell"].includes(n)&&(n="table:"+n),e.attributes)for(const s of Array.from(e.attributes))U(s.name),t[s.name]=s.value;t.style&&(r=t.style,delete t.style),t.vid&&delete t.vid,t.status&&delete t.status;let i={type:n};r&&(i.marker=r),i={...i,...t},e.firstChild&&e.firstChild.nodeType===e.firstChild.TEXT_NODE&&e.firstChild.nodeValue&&y(e.firstChild.nodeValue)!==""&&(o=e.firstChild.nodeValue);const d=Array.from(e.childNodes);i.content=[],o&&i.content.push(o);for(const s of d){if(s.tagName===void 0)continue;const[l,S]=C(s);switch(S){case"append":i.content.push(l);break;case"merge":i.content=i.content.concat(l);break}s.nextSibling&&s.nextSibling.nodeType===s.nextSibling.TEXT_NODE&&s.nextSibling.nodeValue&&(y(s.nextSibling.nodeValue)!==""||s.nextSibling.nodeValue===" ")&&i.content.push(s.nextSibling.nodeValue)}return i.content.length===0&&i.type!==a&&delete i.content,"eid"in i&&["verse","chapter"].includes(n)&&(u="ignore"),[i,u]}function y(e){return e.replace(/(^[ \t\n\r\f\v]+)|([ \t\n\r\f\v]+$)/g,"")}exports.EMPTY_USJ=K;exports.EMPTY_USX=I;exports.MARKER_OBJECT_PROPS=x;exports.USJ_TYPE=p;exports.USJ_VERSION=T;exports.USX_TYPE=a;exports.USX_VERSION=E;exports.VALID_BOOK_CODES=v;exports.assertSafeKey=U;exports.getUsjDocumentLocationTypeName=V;exports.indexesFromUsjJsonPath=k;exports.isUsjAttributeKeyLocation=m;exports.isUsjAttributeMarkerLocation=L;exports.isUsjClosingAttributeMarkerLocation=J;exports.isUsjClosingMarkerLocation=g;exports.isUsjMarkerLocation=M;exports.isUsjPropertyValueLocation=b;exports.isUsjTextContentLocation=N;exports.isValidBookCode=w;exports.usjJsonPathFromIndexes=R;exports.usjToUsxString=B;exports.usxStringToUsj=Y;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -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/**\n * The USJ spec type\n * @public\n */\nexport const USJ_TYPE = \"USJ\";\n\n/**\n * The USJ spec version\n * @public\n */\nexport const USJ_VERSION = \"3.1\";\n\n/**\n * An empty USJ object\n * @public\n */\nexport const EMPTY_USJ = Object.freeze<Usj>({ type: USJ_TYPE, version: USJ_VERSION, content: [] });\n\n/**\n * List of known properties of `MarkerObject`\n * @public\n */\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/**\n * Single piece of Scripture content\n * @public\n */\nexport type MarkerContent = string | MarkerObject;\n\n/**\n * A Scripture Marker and its contents\n * @public\n */\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/**\n * Scripture data represented in JSON format. Data compatible transformation from USX/USFM\n * @public\n */\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\n/**\n * Check if the given code is a valid 3-letter Scripture book code.\n * @public\n */\nexport function isValidBookCode(code: string): boolean {\n return VALID_BOOK_CODES.includes(code as BookCode);\n}\n\n/**\n * 3-letter Scripture book code\n * @public\n */\nexport type BookCode = (typeof VALID_BOOK_CODES)[number];\n\n/**\n * List of valid 3-letter Scripture book codes\n * @public\n */\nexport const 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/**\n * The USX spec type\n * @public\n */\nexport const USX_TYPE = \"usx\";\n\n/**\n * The USX spec version\n * @public\n */\nexport const USX_VERSION = \"3.1\";\n\n/**\n * An empty USX string\n * @public\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\n/**\n * Converts a USX string to a USJ object.\n *\n * @param usxString - The USX string to convert.\n * @returns The converted USJ object.\n *\n * @public\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\n/**\n * Converts a USJ object to a USX string.\n *\n * @param usj - The USJ object to convert\n * @returns The converted USX string.\n *\n * @public\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.marker) {\n if (markerContent.type === \"unmatched\") element.setAttribute(\"marker\", markerContent.marker);\n else element.setAttribute(\"style\", markerContent.marker);\n }\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 *\n * @public\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 *\n * @public\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":"kHAUaA,EAAW,MAMXC,EAAc,MAMdC,EAAY,OAAO,OAAY,CAAE,KAAMF,EAAU,QAASC,EAAa,QAAS,EAAC,CAAG,EAMpFE,EAA8C,CACzD,OACA,SACA,UACA,MACA,MACA,SACA,OACA,YACA,YACA,SACA,QACA,UACF,EA8DO,SAASC,EAAgBC,EAAuB,CACrD,OAAOC,EAAiB,SAASD,CAAgB,CACnD,CAYO,MAAMC,EAAmB,CAE9B,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,ECpOaC,EAAW,MAMXC,EAAc,MAMdC,EAAY,IAAIF,CAAQ,aAAaC,CAAW,OCCtD,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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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/converters/usj/converter.utils.ts","../src/converters/usj/jsonpath-indexes.ts","../src/converters/usj/usj-document-location.utils.ts","../src/converters/usj/usx.model.ts","../src/converters/usj/usj-to-usx.ts","../src/converters/usj/usj.model.ts","../src/converters/usj/usx-to-usj.ts"],"sourcesContent":["/* Utility functions for converters */\n\nconst UNSAFE_KEYS = new Set([\"__proto__\", \"prototype\", \"constructor\"]);\n\n/**\n * Avoid prototype pollution by disallowing unsafe keys.\n * @param key - The array key to validate.\n *\n * @public\n */\nexport function assertSafeKey(key: string): void {\n if (!UNSAFE_KEYS.has(key)) return;\n\n throw new Error(`The key \"${key}\" is not allowed to avoid prototype pollution.`);\n}\n","import type { ContentJsonPath } from \"./usj-document-location.model.js\";\n\nconst 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 *\n * @public\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 *\n * @public\n */\nexport function usjJsonPathFromIndexes(indexes: number[]): ContentJsonPath {\n return indexes.reduce<string>(\n (path, index) => `${path}${JSON_PATH_CONTENT}${index}]`,\n JSON_PATH_START,\n ) as ContentJsonPath;\n}\n","/**\n * Type guards for {@link UsjDocumentLocation} subtypes.\n *\n * These guards enable runtime type narrowing to distinguish between the different\n * location types in a USJ document.\n */\n\nimport type {\n UsjDocumentLocation,\n UsjMarkerLocation,\n UsjClosingMarkerLocation,\n UsjTextContentLocation,\n UsjPropertyValueLocation,\n UsjAttributeKeyLocation,\n UsjAttributeMarkerLocation,\n UsjClosingAttributeMarkerLocation,\n} from \"./usj-document-location.model.js\";\n\n/**\n * Type guard to check if a location is a {@link UsjMarkerLocation}.\n *\n * A marker location points to the very beginning of a marker (at the backslash in USFM).\n * It only has a `jsonPath` property with no offset properties.\n *\n * @param location - The location to check.\n * @returns `true` if the location is a `UsjMarkerLocation`, `false` otherwise.\n *\n * @public\n */\nexport function isUsjMarkerLocation(\n location: UsjDocumentLocation | undefined | null,\n): location is UsjMarkerLocation {\n return (\n location != null &&\n \"jsonPath\" in location &&\n !(\"offset\" in location) &&\n !(\"closingMarkerOffset\" in location) &&\n !(\"propertyOffset\" in location) &&\n !(\"keyName\" in location)\n );\n}\n\n/**\n * Type guard to check if a location is a {@link UsjClosingMarkerLocation}.\n *\n * A closing marker location points to a specific point in the closing marker representation\n * of a marker object (e.g., `\\nd*` in USFM).\n *\n * @param location - The location to check.\n * @returns `true` if the location is a `UsjClosingMarkerLocation`, `false` otherwise.\n *\n * @public\n */\nexport function isUsjClosingMarkerLocation(\n location: UsjDocumentLocation | undefined | null,\n): location is UsjClosingMarkerLocation {\n return location != null && \"jsonPath\" in location && \"closingMarkerOffset\" in location;\n}\n\n/**\n * Type guard to check if a location is a {@link UsjTextContentLocation}.\n *\n * A text content location points to a specific character offset within a text content string\n * in a marker's content array.\n *\n * @param location - The location to check.\n * @returns `true` if the location is a `UsjTextContentLocation`, `false` otherwise.\n *\n * @public\n */\nexport function isUsjTextContentLocation(\n location: UsjDocumentLocation | undefined | null,\n): location is UsjTextContentLocation {\n return (\n location != null &&\n \"jsonPath\" in location &&\n \"offset\" in location &&\n !(\"propertyOffset\" in location) &&\n !(\"keyName\" in location)\n );\n}\n\n/**\n * Type guard to check if a location is a {@link UsjPropertyValueLocation}.\n *\n * A property value location points to a specific character offset within a property value\n * (such as `marker` or an attribute value).\n *\n * @param location - The location to check.\n * @returns `true` if the location is a `UsjPropertyValueLocation`, `false` otherwise.\n *\n * @public\n */\nexport function isUsjPropertyValueLocation(\n location: UsjDocumentLocation | undefined | null,\n): location is UsjPropertyValueLocation {\n return location != null && \"jsonPath\" in location && \"propertyOffset\" in location;\n}\n\n/**\n * Type guard to check if a location is a {@link UsjAttributeKeyLocation}.\n *\n * An attribute key location points to a specific character offset within an attribute's key string.\n *\n * @param location - The location to check.\n * @returns `true` if the location is a `UsjAttributeKeyLocation`, `false` otherwise.\n *\n * @public\n */\nexport function isUsjAttributeKeyLocation(\n location: UsjDocumentLocation | undefined | null,\n): location is UsjAttributeKeyLocation {\n return (\n location != null && \"jsonPath\" in location && \"keyName\" in location && \"keyOffset\" in location\n );\n}\n\n/**\n * Type guard to check if a location is a {@link UsjAttributeMarkerLocation}.\n *\n * An attribute marker location points to the beginning of an attribute marker\n * (at the backslash in USFM, e.g., `\\ca` for chapter alternate number).\n *\n * @param location - The location to check.\n * @returns `true` if the location is a `UsjAttributeMarkerLocation`, `false` otherwise.\n *\n * @public\n */\nexport function isUsjAttributeMarkerLocation(\n location: UsjDocumentLocation | undefined | null,\n): location is UsjAttributeMarkerLocation {\n return (\n location != null &&\n \"jsonPath\" in location &&\n \"keyName\" in location &&\n !(\"keyOffset\" in location) &&\n !(\"keyClosingMarkerOffset\" in location)\n );\n}\n\n/**\n * Type guard to check if a location is a {@link UsjClosingAttributeMarkerLocation}.\n *\n * A closing attribute marker location points to a specific point in the closing marker\n * representation of an attribute marker (e.g., `\\ca*` in USFM).\n *\n * @param location - The location to check.\n * @returns `true` if the location is a `UsjClosingAttributeMarkerLocation`, `false` otherwise.\n *\n * @public\n */\nexport function isUsjClosingAttributeMarkerLocation(\n location: UsjDocumentLocation | undefined | null,\n): location is UsjClosingAttributeMarkerLocation {\n return (\n location != null &&\n \"jsonPath\" in location &&\n \"keyName\" in location &&\n \"keyClosingMarkerOffset\" in location\n );\n}\n\n/**\n * Gets a human-readable name for the type of a {@link UsjDocumentLocation}.\n *\n * Useful for error messages when an unsupported location type is encountered.\n *\n * @param location - The location to get the type name for.\n * @returns A string describing the location type, or \"undefined\" / \"null\" if the location is not\n * provided.\n *\n * @public\n */\nexport function getUsjDocumentLocationTypeName(\n location: UsjDocumentLocation | undefined | null,\n): string {\n if (location === undefined) return \"undefined\";\n if (location === null) return \"null\";\n if (isUsjClosingAttributeMarkerLocation(location)) return \"UsjClosingAttributeMarkerLocation\";\n if (isUsjAttributeKeyLocation(location)) return \"UsjAttributeKeyLocation\";\n if (isUsjAttributeMarkerLocation(location)) return \"UsjAttributeMarkerLocation\";\n if (isUsjPropertyValueLocation(location)) return \"UsjPropertyValueLocation\";\n if (isUsjClosingMarkerLocation(location)) return \"UsjClosingMarkerLocation\";\n if (isUsjTextContentLocation(location)) return \"UsjTextContentLocation\";\n if (isUsjMarkerLocation(location)) return \"UsjMarkerLocation\";\n return \"Unknown\";\n}\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/**\n * The USX spec type\n * @public\n */\nexport const USX_TYPE = \"usx\";\n\n/**\n * The USX spec version\n * @public\n */\nexport const USX_VERSION = \"3.1\";\n\n/**\n * An empty USX string\n * @public\n */\nexport const EMPTY_USX = `<${USX_TYPE} version=\"${USX_VERSION}\" />`;\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\n/**\n * Converts a USJ object to a USX string.\n *\n * @param usj - The USJ object to convert\n * @returns The converted USX string.\n *\n * @public\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.marker) {\n if (markerContent.type === \"unmatched\") element.setAttribute(\"marker\", markerContent.marker);\n else element.setAttribute(\"style\", markerContent.marker);\n }\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","/**\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/**\n * The USJ spec type\n * @public\n */\nexport const USJ_TYPE = \"USJ\";\n\n/**\n * The USJ spec version\n * @public\n */\nexport const USJ_VERSION = \"3.1\";\n\n/**\n * An empty USJ object\n * @public\n */\nexport const EMPTY_USJ = Object.freeze<Usj>({ type: USJ_TYPE, version: USJ_VERSION, content: [] });\n\n/**\n * List of known properties of `MarkerObject`\n * @public\n */\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/**\n * Single piece of Scripture content\n * @public\n */\nexport type MarkerContent = string | MarkerObject;\n\n/**\n * A Scripture Marker and its contents\n * @public\n */\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/**\n * Scripture data represented in JSON format. Data compatible transformation from USX/USFM\n * @public\n */\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\n/**\n * Check if the given code is a valid 3-letter Scripture book code.\n * @public\n */\nexport function isValidBookCode(code: string): boolean {\n return VALID_BOOK_CODES.includes(code as BookCode);\n}\n\n/**\n * 3-letter Scripture book code\n * @public\n */\nexport type BookCode = (typeof VALID_BOOK_CODES)[number];\n\n/**\n * List of valid 3-letter Scripture book codes\n * @public\n */\nexport const 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 * 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\";\nimport { assertSafeKey } from \"./converter.utils.js\";\n\ntype Action = \"append\" | \"merge\" | \"ignore\";\ninterface Attribs {\n [name: string]: string;\n}\n\n/**\n * Converts a USX string to a USJ object.\n *\n * @param usxString - The USX string to convert.\n * @returns The converted USJ object.\n *\n * @public\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 assertSafeKey(attrib.name);\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"],"names":["UNSAFE_KEYS","assertSafeKey","key","JSON_PATH_START","JSON_PATH_CONTENT","indexesFromUsjJsonPath","jsonPath","path","str","usjJsonPathFromIndexes","indexes","index","isUsjMarkerLocation","location","isUsjClosingMarkerLocation","isUsjTextContentLocation","isUsjPropertyValueLocation","isUsjAttributeKeyLocation","isUsjAttributeMarkerLocation","isUsjClosingAttributeMarkerLocation","getUsjDocumentLocationTypeName","USX_TYPE","USX_VERSION","EMPTY_USX","chapterEid","verseEid","usjToUsxString","usj","usxDoc","DOMImplementation","usjToUsxDom","markerContent","isLastItem","convertUsjRecurse","parentElement","element","type","eidElement","setAttributes","item","_isLastItem","createVerseEndElement","createChapterEndElement","isVerseInImpliedPara","value","USJ_TYPE","USJ_VERSION","EMPTY_USJ","MARKER_OBJECT_PROPS","isValidBookCode","code","VALID_BOOK_CODES","usxStringToUsj","usxString","inputUsxDom","DOMParser","usxDomToUsj","outputJson","convertUsxRecurse","inputUsxElement","attribs","marker","text","action","attrib","outObj","asciiTrim","children","child","childDict","whatToDo"],"mappings":"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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,ECtNO,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,KAAOZ,EAClBY,EAAW,QAAUX,EACdW,CACT,CAEA,SAASC,EACPC,EACiC,CACjC,MAAMC,EAAmB,CAAA,EACzB,IAAIxB,EAAeuB,EAAgB,QAC/BE,EACAC,EACAC,EAAiB,SAGrB,GADI,CAAC,MAAO,MAAM,EAAE,SAAS3B,CAAI,MAAU,SAAWA,GAClDuB,EAAgB,WAClB,UAAWK,KAAU,MAAM,KAAKL,EAAgB,UAAU,EACxD1D,EAAc+D,EAAO,IAAI,EACzBJ,EAAQI,EAAO,IAAI,EAAIA,EAAO,MAI9BJ,EAAQ,QACVC,EAASD,EAAQ,MACjB,OAAOA,EAAQ,OAGbA,EAAQ,KAAK,OAAOA,EAAQ,IAG5BA,EAAQ,QAAQ,OAAOA,EAAQ,OAEnC,IAAIK,EAAY,CAAE,KAAA7B,CAAA,EACdyB,IAASI,EAAwB,OAASJ,GAC9CI,EAAS,CAAE,GAAGA,EAAQ,GAAGL,CAAA,EAGvBD,EAAgB,YAChBA,EAAgB,WAAW,WAAaA,EAAgB,WAAW,WACnEA,EAAgB,WAAW,WAC3BO,EAAUP,EAAgB,WAAW,SAAS,IAAM,KAEpDG,EAAOH,EAAgB,WAAW,WAGpC,MAAMQ,EAAW,MAAM,KAAKR,EAAgB,UAAU,EACtDM,EAAO,QAAU,CAAA,EAEbH,GACFG,EAAO,QAAQ,KAAKH,CAAI,EAG1B,UAAWM,KAASD,EAAU,CAE5B,GAAKC,EAAkB,UAAY,OACjC,SAGF,KAAM,CAACC,EAAWC,CAAQ,EAAIZ,EAAgCU,CAAgB,EAE9E,OAAQE,EAAA,CACN,IAAK,SACHL,EAAO,QAAQ,KAAKI,CAAS,EAC7B,MACF,IAAK,QACHJ,EAAO,QAAUA,EAAO,QAAQ,OAAOI,CAAS,EAChD,KAIA,CAKFD,EAAM,aACNA,EAAM,YAAY,WAAaA,EAAM,YAAY,WACjDA,EAAM,YAAY,YACjBF,EAAUE,EAAM,YAAY,SAAS,IAAM,IAAMA,EAAM,YAAY,YAAc,MAElFH,EAAO,QAAQ,KAAKG,EAAM,YAAY,SAAS,CAEnD,CAIA,OAAIH,EAAO,QAAQ,SAAW,GAAKA,EAAO,OAAS5C,GACjD,OAAO4C,EAAO,QAGZ,QAASA,GAAU,CAAC,QAAS,SAAS,EAAE,SAAS7B,CAAI,IACvD2B,EAAS,UAGJ,CAACE,EAAQF,CAAM,CACxB,CAUA,SAASG,EAAU1D,EAAqB,CACtC,OAAOA,EAAI,QAAQ,uCAAwC,EAAE,CAC/D"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,12 +3,36 @@
|
|
|
3
3
|
* Utilities for Scripture data conversion and manipulation, including USJ/USX format conversion.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Avoid prototype pollution by disallowing unsafe keys.
|
|
8
|
+
* @param key - The array key to validate.
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export declare function assertSafeKey(key: string): void;
|
|
13
|
+
|
|
6
14
|
/**
|
|
7
15
|
* 3-letter Scripture book code
|
|
8
16
|
* @public
|
|
9
17
|
*/
|
|
10
18
|
export declare type BookCode = (typeof VALID_BOOK_CODES)[number];
|
|
11
19
|
|
|
20
|
+
/**
|
|
21
|
+
* JSON path to a {@link MarkerObject}, {@link Usj}, or text content string in the current USJ
|
|
22
|
+
* document.
|
|
23
|
+
*
|
|
24
|
+
* This could actually have more content clauses at the end, but TS types are limited
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export declare type ContentJsonPath =
|
|
29
|
+
| ""
|
|
30
|
+
| `$`
|
|
31
|
+
| `$.content[${number}]`
|
|
32
|
+
| `$.content[${number}].content[${number}]`
|
|
33
|
+
| `$.content[${number}].content[${number}].content[${number}]`
|
|
34
|
+
| `$.content[${number}].content[${number}].content[${number}].content[${number}]`;
|
|
35
|
+
|
|
12
36
|
/**
|
|
13
37
|
* An empty USJ object
|
|
14
38
|
* @public
|
|
@@ -21,6 +45,21 @@ export declare const EMPTY_USJ: Readonly<Usj>;
|
|
|
21
45
|
*/
|
|
22
46
|
export declare const EMPTY_USX = '<usx version="3.1" />';
|
|
23
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Gets a human-readable name for the type of a {@link UsjDocumentLocation}.
|
|
50
|
+
*
|
|
51
|
+
* Useful for error messages when an unsupported location type is encountered.
|
|
52
|
+
*
|
|
53
|
+
* @param location - The location to get the type name for.
|
|
54
|
+
* @returns A string describing the location type, or "undefined" / "null" if the location is not
|
|
55
|
+
* provided.
|
|
56
|
+
*
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
export declare function getUsjDocumentLocationTypeName(
|
|
60
|
+
location: UsjDocumentLocation | undefined | null,
|
|
61
|
+
): string;
|
|
62
|
+
|
|
24
63
|
/**
|
|
25
64
|
* Converts a USJ JSONPath string into an array of indexes.
|
|
26
65
|
*
|
|
@@ -32,6 +71,110 @@ export declare const EMPTY_USX = '<usx version="3.1" />';
|
|
|
32
71
|
*/
|
|
33
72
|
export declare function indexesFromUsjJsonPath(jsonPath: string): number[];
|
|
34
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Type guard to check if a location is a {@link UsjAttributeKeyLocation}.
|
|
76
|
+
*
|
|
77
|
+
* An attribute key location points to a specific character offset within an attribute's key string.
|
|
78
|
+
*
|
|
79
|
+
* @param location - The location to check.
|
|
80
|
+
* @returns `true` if the location is a `UsjAttributeKeyLocation`, `false` otherwise.
|
|
81
|
+
*
|
|
82
|
+
* @public
|
|
83
|
+
*/
|
|
84
|
+
export declare function isUsjAttributeKeyLocation(
|
|
85
|
+
location: UsjDocumentLocation | undefined | null,
|
|
86
|
+
): location is UsjAttributeKeyLocation;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Type guard to check if a location is a {@link UsjAttributeMarkerLocation}.
|
|
90
|
+
*
|
|
91
|
+
* An attribute marker location points to the beginning of an attribute marker
|
|
92
|
+
* (at the backslash in USFM, e.g., `\ca` for chapter alternate number).
|
|
93
|
+
*
|
|
94
|
+
* @param location - The location to check.
|
|
95
|
+
* @returns `true` if the location is a `UsjAttributeMarkerLocation`, `false` otherwise.
|
|
96
|
+
*
|
|
97
|
+
* @public
|
|
98
|
+
*/
|
|
99
|
+
export declare function isUsjAttributeMarkerLocation(
|
|
100
|
+
location: UsjDocumentLocation | undefined | null,
|
|
101
|
+
): location is UsjAttributeMarkerLocation;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Type guard to check if a location is a {@link UsjClosingAttributeMarkerLocation}.
|
|
105
|
+
*
|
|
106
|
+
* A closing attribute marker location points to a specific point in the closing marker
|
|
107
|
+
* representation of an attribute marker (e.g., `\ca*` in USFM).
|
|
108
|
+
*
|
|
109
|
+
* @param location - The location to check.
|
|
110
|
+
* @returns `true` if the location is a `UsjClosingAttributeMarkerLocation`, `false` otherwise.
|
|
111
|
+
*
|
|
112
|
+
* @public
|
|
113
|
+
*/
|
|
114
|
+
export declare function isUsjClosingAttributeMarkerLocation(
|
|
115
|
+
location: UsjDocumentLocation | undefined | null,
|
|
116
|
+
): location is UsjClosingAttributeMarkerLocation;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Type guard to check if a location is a {@link UsjClosingMarkerLocation}.
|
|
120
|
+
*
|
|
121
|
+
* A closing marker location points to a specific point in the closing marker representation
|
|
122
|
+
* of a marker object (e.g., `\nd*` in USFM).
|
|
123
|
+
*
|
|
124
|
+
* @param location - The location to check.
|
|
125
|
+
* @returns `true` if the location is a `UsjClosingMarkerLocation`, `false` otherwise.
|
|
126
|
+
*
|
|
127
|
+
* @public
|
|
128
|
+
*/
|
|
129
|
+
export declare function isUsjClosingMarkerLocation(
|
|
130
|
+
location: UsjDocumentLocation | undefined | null,
|
|
131
|
+
): location is UsjClosingMarkerLocation;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Type guard to check if a location is a {@link UsjMarkerLocation}.
|
|
135
|
+
*
|
|
136
|
+
* A marker location points to the very beginning of a marker (at the backslash in USFM).
|
|
137
|
+
* It only has a `jsonPath` property with no offset properties.
|
|
138
|
+
*
|
|
139
|
+
* @param location - The location to check.
|
|
140
|
+
* @returns `true` if the location is a `UsjMarkerLocation`, `false` otherwise.
|
|
141
|
+
*
|
|
142
|
+
* @public
|
|
143
|
+
*/
|
|
144
|
+
export declare function isUsjMarkerLocation(
|
|
145
|
+
location: UsjDocumentLocation | undefined | null,
|
|
146
|
+
): location is UsjMarkerLocation;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Type guard to check if a location is a {@link UsjPropertyValueLocation}.
|
|
150
|
+
*
|
|
151
|
+
* A property value location points to a specific character offset within a property value
|
|
152
|
+
* (such as `marker` or an attribute value).
|
|
153
|
+
*
|
|
154
|
+
* @param location - The location to check.
|
|
155
|
+
* @returns `true` if the location is a `UsjPropertyValueLocation`, `false` otherwise.
|
|
156
|
+
*
|
|
157
|
+
* @public
|
|
158
|
+
*/
|
|
159
|
+
export declare function isUsjPropertyValueLocation(
|
|
160
|
+
location: UsjDocumentLocation | undefined | null,
|
|
161
|
+
): location is UsjPropertyValueLocation;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Type guard to check if a location is a {@link UsjTextContentLocation}.
|
|
165
|
+
*
|
|
166
|
+
* A text content location points to a specific character offset within a text content string
|
|
167
|
+
* in a marker's content array.
|
|
168
|
+
*
|
|
169
|
+
* @param location - The location to check.
|
|
170
|
+
* @returns `true` if the location is a `UsjTextContentLocation`, `false` otherwise.
|
|
171
|
+
*
|
|
172
|
+
* @public
|
|
173
|
+
*/
|
|
174
|
+
export declare function isUsjTextContentLocation(
|
|
175
|
+
location: UsjDocumentLocation | undefined | null,
|
|
176
|
+
): location is UsjTextContentLocation;
|
|
177
|
+
|
|
35
178
|
/**
|
|
36
179
|
* Check if the given code is a valid 3-letter Scripture book code.
|
|
37
180
|
* @public
|
|
@@ -87,6 +230,28 @@ export declare interface MarkerObject {
|
|
|
87
230
|
category?: string;
|
|
88
231
|
}
|
|
89
232
|
|
|
233
|
+
/**
|
|
234
|
+
* JSON path to the `marker` or an attribute on a {@link MarkerObject} or {@link Usj} in the current
|
|
235
|
+
* USJ document. Note that it seems you must use `['bracket notation']` rather than `.dot` notation
|
|
236
|
+
* if there are symbols other than underscore in the property name
|
|
237
|
+
*
|
|
238
|
+
* This could actually have more content clauses at the end, but TS types are limited
|
|
239
|
+
*
|
|
240
|
+
* @public
|
|
241
|
+
*/
|
|
242
|
+
export declare type PropertyJsonPath =
|
|
243
|
+
| ""
|
|
244
|
+
| `$.${string}`
|
|
245
|
+
| `$['${string}']`
|
|
246
|
+
| `$.content[${number}].${string}`
|
|
247
|
+
| `$.content[${number}]['${string}']`
|
|
248
|
+
| `$.content[${number}].content[${number}].${string}`
|
|
249
|
+
| `$.content[${number}].content[${number}]['${string}']`
|
|
250
|
+
| `$.content[${number}].content[${number}].content[${number}].${string}`
|
|
251
|
+
| `$.content[${number}].content[${number}].content[${number}]['${string}']`
|
|
252
|
+
| `$.content[${number}].content[${number}].content[${number}].content[${number}].${string}`
|
|
253
|
+
| `$.content[${number}].content[${number}].content[${number}].content[${number}]['${string}']`;
|
|
254
|
+
|
|
90
255
|
/**
|
|
91
256
|
* Scripture data represented in JSON format. Data compatible transformation from USX/USFM
|
|
92
257
|
* @public
|
|
@@ -112,6 +277,151 @@ export declare const USJ_TYPE = "USJ";
|
|
|
112
277
|
*/
|
|
113
278
|
export declare const USJ_VERSION = "3.1";
|
|
114
279
|
|
|
280
|
+
/**
|
|
281
|
+
* A JSONPath query to a specific point in an attribute key string in a {@link MarkerObject} or
|
|
282
|
+
* {@link Usj}. The property cannot be `type` or `marker` because these properties' keys have no
|
|
283
|
+
* representation in USFM. The property also cannot be any special attribute whose key doesn't have
|
|
284
|
+
* a text representation in USFM like default attribute, leading attribute, text content attribute
|
|
285
|
+
*
|
|
286
|
+
* To represent a location in an attribute's value, use {@link UsjPropertyValueLocation}.
|
|
287
|
+
*
|
|
288
|
+
* @public
|
|
289
|
+
*/
|
|
290
|
+
export declare interface UsjAttributeKeyLocation {
|
|
291
|
+
/**
|
|
292
|
+
* JSON path to the marker whose attribute key the location is pointing to. The offset applies to
|
|
293
|
+
* this attribute's key string unless the attribute is an attribute marker in USFM.
|
|
294
|
+
*/
|
|
295
|
+
jsonPath: ContentJsonPath;
|
|
296
|
+
/** Attribute name on the marker object whose key this location is pointing to. */
|
|
297
|
+
keyName: string;
|
|
298
|
+
/**
|
|
299
|
+
* The character index in the attribute's key string where this location is pointing.
|
|
300
|
+
*
|
|
301
|
+
* If the attribute is an attribute marker in USFM, the location is at this offset within the
|
|
302
|
+
* marker name for this attribute marker (for example, `c`'s `altnumber` attribute has attribute
|
|
303
|
+
* marker `ca`, so its `keyOffset` applies to `ca`).
|
|
304
|
+
*
|
|
305
|
+
* If the attribute is not an attribute marker in USFM, the location is at this offset within the
|
|
306
|
+
* attribute's key string.
|
|
307
|
+
*/
|
|
308
|
+
keyOffset: number;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* A JSONPath query to an attribute marker derived from an attribute on a {@link MarkerObject} or
|
|
313
|
+
* {@link Usj}. Indicates the very beginning of that marker (at the backslash in USFM).
|
|
314
|
+
*
|
|
315
|
+
* @public
|
|
316
|
+
*/
|
|
317
|
+
export declare interface UsjAttributeMarkerLocation {
|
|
318
|
+
/** JSON path to the marker whose attribute marker the location is pointing to. */
|
|
319
|
+
jsonPath: ContentJsonPath;
|
|
320
|
+
/**
|
|
321
|
+
* Attribute name on the marker object whose key this location is pointing to. This attribute is
|
|
322
|
+
* an attribute marker in USFM.
|
|
323
|
+
*/
|
|
324
|
+
keyName: string;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* A JSONPath query to a specific point in the closing marker representation of an attribute marker
|
|
329
|
+
* derived from an attribute on a {@link MarkerObject} or {@link Usj}.
|
|
330
|
+
*
|
|
331
|
+
* @public
|
|
332
|
+
*/
|
|
333
|
+
export declare interface UsjClosingAttributeMarkerLocation {
|
|
334
|
+
/**
|
|
335
|
+
* JSON path to the marker whose attribute marker's closing marker the location is pointing to.
|
|
336
|
+
* The offset applies to the closing marker representation of that attribute marker (for example,
|
|
337
|
+
* `\ca*` in USFM).
|
|
338
|
+
*/
|
|
339
|
+
jsonPath: ContentJsonPath;
|
|
340
|
+
/**
|
|
341
|
+
* Attribute name on the marker object whose key this location is pointing to. This attribute is
|
|
342
|
+
* an attribute marker in USFM.
|
|
343
|
+
*/
|
|
344
|
+
keyName: string;
|
|
345
|
+
/**
|
|
346
|
+
* The character index in the closing marker representation where this location is pointing. The
|
|
347
|
+
* location is at this offset within the closing marker representation of the attribute marker.
|
|
348
|
+
*/
|
|
349
|
+
keyClosingMarkerOffset: number;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* A JSONPath query to a specific point in the closing marker representation of a
|
|
354
|
+
* {@link MarkerObject} or {@link Usj} node.
|
|
355
|
+
*
|
|
356
|
+
* @public
|
|
357
|
+
*/
|
|
358
|
+
export declare interface UsjClosingMarkerLocation {
|
|
359
|
+
/**
|
|
360
|
+
* JSON path to the marker object whose closing marker the location is pointing to. The offset
|
|
361
|
+
* applies to the closing marker representation of that marker (for example, `\nd*` in USFM).
|
|
362
|
+
*/
|
|
363
|
+
jsonPath: ContentJsonPath;
|
|
364
|
+
/**
|
|
365
|
+
* The character index in the closing marker representation where this location is pointing. The
|
|
366
|
+
* location is at this offset within the closing marker representation.
|
|
367
|
+
*/
|
|
368
|
+
closingMarkerOffset: number;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/** Serializable USJ locations relative to a specific USJ document (chapter or book) */
|
|
372
|
+
/**
|
|
373
|
+
* A JSONPath query to a {@link MarkerContent}, {@link Usj}, or property within a USJ document and
|
|
374
|
+
* additional information that point to a specific location in that USJ document.
|
|
375
|
+
*
|
|
376
|
+
* This type does not include a verse reference because the JSONPath is relative to a specific USJ
|
|
377
|
+
* document; that USJ document may have a book, a chapter, or something else in it. Use
|
|
378
|
+
* `UsjLocation` to specify which USJ document this location is relative to, making the
|
|
379
|
+
* location an absolute verse reference location. The closest equivalent concept in USFM to this
|
|
380
|
+
* relative document location is a string character index in a USFM document; such an index is
|
|
381
|
+
* relative to a specific USFM document rather than indicating an absolute position in a Scripture
|
|
382
|
+
* text.
|
|
383
|
+
*
|
|
384
|
+
* This type intends to represent USFM positions (`UsfmVerseLocation`) in USJ space. However,
|
|
385
|
+
* there are some USFM positions that are not currently representable with these types:
|
|
386
|
+
*
|
|
387
|
+
* - The second slash in `optbreak`'s USFM representation `//` (literally not representable)
|
|
388
|
+
* - Nested marker prefix on opening markers like `+` for character markers (literally not
|
|
389
|
+
* representable)
|
|
390
|
+
* - The bar `|` that indicates the start of closing marker attributes (no official representation)
|
|
391
|
+
* - The equals sign for closing marker attributes (no official representation)
|
|
392
|
+
* - The quotes around closing marker attribute values (no official representation)
|
|
393
|
+
* - The space between closing marker attributes (no official representation)
|
|
394
|
+
*
|
|
395
|
+
* Also note that the following types do not specify a concrete location that is actually in the USJ
|
|
396
|
+
* document but represent a USFM location relative to the most similar thing in USJ that there is:
|
|
397
|
+
*
|
|
398
|
+
* - {@link UsjClosingMarkerLocation} - there are no distinct closing objects in JSON; there is a
|
|
399
|
+
* common syntax for closing every object, but it is only one character and is on every single
|
|
400
|
+
* object as opposed to USFM closing markers which are multiple characters long and are only
|
|
401
|
+
* sometimes present.
|
|
402
|
+
* - {@link UsjAttributeKeyLocation} - when the attribute whose key is being pointed to is an
|
|
403
|
+
* attribute marker in USFM, the `keyOffset` does not apply to the USJ attribute name (e.g.
|
|
404
|
+
* `altnumber`) but to the USFM attribute marker name (e.g. `ca`).
|
|
405
|
+
* - {@link UsjAttributeMarkerLocation} - attribute markers are just properties in JSON; they do not
|
|
406
|
+
* have their own object such that they would have an opening that can be pointed to in the JSON
|
|
407
|
+
* like they have their own opening in USFM.
|
|
408
|
+
* - {@link UsjClosingAttributeMarkerLocation} - attribute markers are just properties in JSON, plus
|
|
409
|
+
* they are in the same situation as {@link UsjClosingMarkerLocation} as detailed above.
|
|
410
|
+
*
|
|
411
|
+
* To see many examples of the same point represented by both USFM and USJ locations, go to
|
|
412
|
+
* https://github.com/paranext/paranext-core/tree/main/lib/platform-bible-utils/src/scripture/usj-reader-writer-test-data/testUSFM-2SA-1-locations.ts
|
|
413
|
+
*
|
|
414
|
+
* @public
|
|
415
|
+
*/
|
|
416
|
+
export declare type UsjDocumentLocation =
|
|
417
|
+
| UsjMarkerLocation
|
|
418
|
+
| UsjClosingMarkerLocation
|
|
419
|
+
| UsjTextContentLocation
|
|
420
|
+
| UsjPropertyValueLocation
|
|
421
|
+
| UsjAttributeKeyLocation
|
|
422
|
+
| UsjAttributeMarkerLocation
|
|
423
|
+
| UsjClosingAttributeMarkerLocation;
|
|
424
|
+
|
|
115
425
|
/**
|
|
116
426
|
* Converts an array of indexes into a USJ JSONPath string.
|
|
117
427
|
*
|
|
@@ -120,7 +430,59 @@ export declare const USJ_VERSION = "3.1";
|
|
|
120
430
|
*
|
|
121
431
|
* @public
|
|
122
432
|
*/
|
|
123
|
-
export declare function usjJsonPathFromIndexes(indexes: number[]):
|
|
433
|
+
export declare function usjJsonPathFromIndexes(indexes: number[]): ContentJsonPath;
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* A JSONPath query to a {@link MarkerObject} or {@link Usj} node. Indicates the very beginning of
|
|
437
|
+
* that marker (at the backslash in USFM).
|
|
438
|
+
*
|
|
439
|
+
* @public
|
|
440
|
+
*/
|
|
441
|
+
export declare interface UsjMarkerLocation {
|
|
442
|
+
/** JSON path to the marker object the location is pointing to. */
|
|
443
|
+
jsonPath: ContentJsonPath;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* A JSONPath query to a specific point in a property (`marker` or an attribute) value string in a
|
|
448
|
+
* {@link MarkerObject} or {@link Usj}. The property cannot be `type` because `type`'s value has no
|
|
449
|
+
* representation in USFM.
|
|
450
|
+
*
|
|
451
|
+
* To represent a location in an attribute's key, use {@link UsjAttributeKeyLocation}.
|
|
452
|
+
*
|
|
453
|
+
* @public
|
|
454
|
+
*/
|
|
455
|
+
export declare interface UsjPropertyValueLocation {
|
|
456
|
+
/**
|
|
457
|
+
* JSON path to the property the location is pointing to. The offset applies to this property's
|
|
458
|
+
* value string.
|
|
459
|
+
*/
|
|
460
|
+
jsonPath: PropertyJsonPath;
|
|
461
|
+
/**
|
|
462
|
+
* The character index in the property's value string where this location is pointing. The
|
|
463
|
+
* location is at this offset within the property's value string.
|
|
464
|
+
*/
|
|
465
|
+
propertyOffset: number;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* A JSONPath query to a specific point in a text content string in a {@link MarkerObject.content}
|
|
470
|
+
* array.
|
|
471
|
+
*
|
|
472
|
+
* @public
|
|
473
|
+
*/
|
|
474
|
+
export declare interface UsjTextContentLocation {
|
|
475
|
+
/**
|
|
476
|
+
* JSON path to the text content string the location is pointing to. The offset applies to this
|
|
477
|
+
* text string.
|
|
478
|
+
*/
|
|
479
|
+
jsonPath: ContentJsonPath;
|
|
480
|
+
/**
|
|
481
|
+
* The character index in the text content string where this location is pointing. The location is
|
|
482
|
+
* at this offset within the text content string.
|
|
483
|
+
*/
|
|
484
|
+
offset: number;
|
|
485
|
+
}
|
|
124
486
|
|
|
125
487
|
/**
|
|
126
488
|
* Converts a USJ object to a USX string.
|