1+ import { Fragment } from "react" ;
2+
13/**
24 * A set of names, for generating unambiguous abbreviations.
35 */
46class NameSet {
5- private readonly abbreviations = new Map < string , string > ( ) ;
7+ private readonly abbreviations = new Map < string , React . ReactNode > ( ) ;
68
79 constructor ( readonly names : string [ ] ) {
810 const qnames = names . map ( parseName ) ;
@@ -14,7 +16,7 @@ class NameSet {
1416 } ) ;
1517 }
1618
17- public getAbbreviation ( name : string ) {
19+ public getAbbreviation ( name : string ) : React . ReactNode {
1820 return this . abbreviations . get ( name ) ?? name ;
1921 }
2022}
@@ -84,7 +86,7 @@ class TrieNode {
8486
8587interface VisitResult {
8688 node : TrieNode ;
87- abbreviate : ( ) => string ;
89+ abbreviate : ( ) => React . ReactNode ;
8890}
8991
9092class TrieBuilder {
@@ -117,20 +119,28 @@ class TrieBuilder {
117119 return {
118120 node : trieNode ,
119121 abbreviate : ( ) => {
120- let result = "" ;
122+ const result : React . ReactNode [ ] = [ ] ;
121123 if ( prefix != null ) {
122- result += prefix . abbreviate ( ) ;
123- result += "::" ;
124+ result . push ( prefix . abbreviate ( ) ) ;
125+ result . push ( "::" ) ;
124126 }
125- result += qname . name ;
127+ result . push ( qname . name ) ;
126128 if ( args != null ) {
127- result += "<" ;
129+ result . push ( "<" ) ;
128130 if ( trieNodeBeforeArgs . children . size === 1 ) {
129- result += "..." ;
131+ result . push ( "..." ) ;
130132 } else {
131- result += args . map ( ( arg ) => arg . abbreviate ( ) ) . join ( "," ) ;
133+ let first = true ;
134+ for ( const arg of args ) {
135+ result . push ( arg . abbreviate ( ) ) ;
136+ if ( first ) {
137+ first = false ;
138+ } else {
139+ result . push ( "," ) ;
140+ }
141+ }
132142 }
133- result += ">" ;
143+ result . push ( ">" ) ;
134144 }
135145 return result ;
136146 } ,
@@ -140,12 +150,31 @@ class TrieBuilder {
140150
141151const nameTokenRegex = / \b [ ^ ] + : : [ ^ ( ] + \b / g;
142152
143- export function abbreviateRASteps ( steps : string [ ] ) : string [ ] {
153+ export function abbreviateRASteps ( steps : string [ ] ) : React . ReactNode [ ] {
144154 const nameTokens = steps . flatMap ( ( step ) =>
145155 Array . from ( step . matchAll ( nameTokenRegex ) ) . map ( ( tok ) => tok [ 0 ] ) ,
146156 ) ;
147157 const nameSet = new NameSet ( nameTokens ) ;
148- return steps . map ( ( step ) =>
149- step . replace ( nameTokenRegex , ( match ) => nameSet . getAbbreviation ( match ) ) ,
150- ) ;
158+ return steps . map ( ( step , index ) => {
159+ const matches = Array . from ( step . matchAll ( nameTokenRegex ) ) ;
160+ const result : React . ReactNode [ ] = [ ] ;
161+ for ( let i = 0 ; i < matches . length ; i ++ ) {
162+ const match = matches [ i ] ;
163+ const before = step . slice (
164+ i === 0 ? 0 : matches [ i - 1 ] . index + matches [ i - 1 ] [ 0 ] . length ,
165+ match . index ,
166+ ) ;
167+ result . push ( before ) ;
168+ result . push ( nameSet . getAbbreviation ( match [ 0 ] ) ) ;
169+ }
170+ result . push (
171+ matches . length === 0
172+ ? step
173+ : step . slice (
174+ matches [ matches . length - 1 ] . index +
175+ matches [ matches . length - 1 ] [ 0 ] . length ,
176+ ) ,
177+ ) ;
178+ return < Fragment key = { index } > { result } </ Fragment > ;
179+ } ) ;
151180}
0 commit comments