@@ -47,13 +47,33 @@ const getXPath = (node: Node, path: string[] = []) => {
4747 * For the given path sgement lists, this function returns the the
4848 * start & end XPath expression pair.
4949 */
50- const toTEIXPaths = ( startPath : string [ ] , endPath : string [ ] , selectedRange : Range ) => {
50+ const toTEIXPaths = ( container : HTMLElement , startPath : string [ ] , endPath : string [ ] , selectedRange : Range ) => {
51+
52+ const findFirstTEIChild = ( node : Node ) : Element | null => {
53+ const iterator = document . createNodeIterator (
54+ node ,
55+ NodeFilter . SHOW_ELEMENT ,
56+ ( node ) => {
57+ return ( node as Element ) . nodeName . toLowerCase ( ) . startsWith ( 'tei-' )
58+ ? NodeFilter . FILTER_ACCEPT
59+ : NodeFilter . FILTER_SKIP ;
60+ }
61+ ) ;
62+
63+ return iterator . nextNode ( ) as Element | null ;
64+ }
65+
5166 // For a given node, returns the closest parent that is a TEI element
5267 const getClosestTEINode = ( node : Node | null ) => {
5368 if ( ! node ) return null ;
5469
55- return ( node . nodeName . toLowerCase ( ) . indexOf ( 'tei-' ) === 0 ) ?
56- node : getClosestTEINode ( node . parentNode ) ;
70+ // Edge case: node is the container itself
71+ if ( node === container ) {
72+ return findFirstTEIChild ( node ) ;
73+ } else {
74+ return ( node . nodeName . toLowerCase ( ) . indexOf ( 'tei-' ) === 0 ) ?
75+ node : getClosestTEINode ( node . parentNode ) ;
76+ }
5777 } ;
5878
5979 // Helper to compute char offsets between end of XPath and a given reference node
@@ -85,15 +105,15 @@ const toTEIXPaths = (startPath: string[], endPath: string[], selectedRange: Rang
85105 * Using the DOM Range from a (revived!) TextSelector, this function computes
86106 * the TEIRangeSelector corresponding to that range.
87107 */
88- export const textToTEISelector = ( selector : TextSelector ) : TEIRangeSelector => {
108+ export const textToTEISelector = ( container : HTMLElement ) => ( selector : TextSelector ) : TEIRangeSelector => {
89109 const { range } = selector ;
90110
91111 // XPath segments for Range start and end nodes as a list
92112 const startPathSegments : string [ ] = getXPath ( range . startContainer ) ;
93113 const endPathSegments : string [ ] = getXPath ( range . endContainer ) ;
94114
95115 // TEI XPath expressions
96- const { start, end } = toTEIXPaths ( startPathSegments , endPathSegments , range ) ;
116+ const { start, end } = toTEIXPaths ( container , startPathSegments , endPathSegments , range ) ;
97117
98118 return {
99119 start : selector . start ,
@@ -179,7 +199,7 @@ export const textToTEITarget = (container: HTMLElement) => (t: TextAnnotationTa
179199 const target = reviveTarget ( t , container ) ;
180200 return {
181201 ...t ,
182- selector : target . selector . map ( textToTEISelector )
202+ selector : target . selector . map ( textToTEISelector ( container ) )
183203 }
184204}
185205
0 commit comments