@@ -451,11 +451,12 @@ define(function (require, exports, module) {
451451 * for sorting. It also has a stringRanges array, each entry with
452452 * "text", "matched" and "segment". If you string the "text" properties together, you will
453453 * get the original str. Using the matched property, you can highlight
454- * the string matches. The segment property tells you the most specific segment
455- * covered by the range, though there may be more than one segment convered.
454+ * the string matches. The segment property tells you the most specific (rightmost)
455+ * segment covered by the range, though there may be more than one segment covered.
456+ * Segments are currently determined by "/"s.
456457 *
457- * Use basicMatchSort() to sort the filtered results taking this ranking
458- * label of the SearchResult is set to 'str'.
458+ * Use basicMatchSort() to sort the filtered results taking this ranking into account.
459+ * The label of the SearchResult is set to 'str'.
459460 * @param {!string } str
460461 * @param {!string } query
461462 * @return {?SearchResult }
@@ -493,7 +494,7 @@ define(function (require, exports, module) {
493494 }
494495
495496 // No query? Short circuit the normal work done and just
496- // return a simple match with a range that covers the whole string.
497+ // return a single range that covers the whole string.
497498 if ( ! query ) {
498499 result = new SearchResult ( str ) ;
499500 result . matchGoodness = 0 ;
@@ -569,7 +570,7 @@ define(function (require, exports, module) {
569570 addToStringRanges ( Math . abs ( sequentialMatches ) , sequentialMatches > 0 ) ;
570571 }
571572
572- if ( strCounter > 0 ) {
573+ if ( strCounter >= 0 ) {
573574 stringRanges . unshift ( {
574575 text : str . substring ( 0 , strCounter + 1 ) ,
575576 matched : false ,
@@ -644,7 +645,7 @@ define(function (require, exports, module) {
644645 * within each tier.
645646 */
646647 function basicMatchSort ( searchResults ) {
647- multiFieldSort ( searchResults , { matchGoodness : 0 , label : 2 } ) ;
648+ multiFieldSort ( searchResults , { matchGoodness : 0 , label : 1 } ) ;
648649 }
649650
650651
@@ -713,55 +714,66 @@ define(function (require, exports, module) {
713714 }
714715
715716
716- function defaultResultsFormatter ( item , query ) {
717- query = query . slice ( query . indexOf ( "@" ) + 1 , query . length ) ;
718-
719- // Escape both query and item so the replace works properly below
720- query = StringUtils . htmlEscape ( query ) ;
717+ /**
718+ * Formats item's label as properly escaped HTML text, highlighting sections that match 'query'.
719+ * If item is a SearchResult generated by stringMatch(), uses its metadata about which string ranges
720+ * matched; else formats the label with no highlighting.
721+ * @param {!string|SearchResult } item
722+ * @param {?string } matchClass CSS class for highlighting matched text
723+ * @param {?function(number, string):string } rangeFilter
724+ * @return {!string } bolded, HTML-escaped result
725+ */
726+ function highlightMatch ( item , matchClass , rangeFilter ) {
721727 var label = item . label || item ;
722- var displayName = StringUtils . htmlEscape ( label ) ;
723-
724- if ( query . length > 0 ) {
725- // make the user's query bold within the item's text
726- displayName = displayName . replace (
727- new RegExp ( StringUtils . regexEscape ( query ) , "gi" ) ,
728- "<strong>$&</strong>"
729- ) ;
728+ matchClass = matchClass || "quicksearch-namematch" ;
729+
730+ var stringRanges = item . stringRanges ;
731+ if ( ! stringRanges ) {
732+ // If result didn't come from stringMatch(), highlight nothing
733+ stringRanges = [ {
734+ text : label ,
735+ matched : false ,
736+ segment : 0
737+ } ] ;
730738 }
731-
732- return "<li>" + displayName + "</li>" ;
733- }
734-
735- function _filenameResultsFormatter ( item , query ) {
736- // Use the filename formatter
737- query = StringUtils . htmlEscape ( query ) ;
738-
739- // put the path pieces together, highlighting the matched parts
740- // of the string
739+
741740 var displayName = "" ;
742- var displayPath = "" ;
743741
744- item . stringRanges . forEach ( function ( range ) {
742+ // Put the path pieces together, highlighting the matched parts
743+ stringRanges . forEach ( function ( range ) {
745744 if ( range . matched ) {
746- displayPath += '<span class="quicksearch-pathmatch">' ;
747- displayName += '<span class="quicksearch-namematch">' ;
748- } else {
749- displayPath += '<span>' ;
750- displayName += '<span>' ;
745+ displayName += "<span class='" + matchClass + "'>" ;
751746 }
752- displayPath += StringUtils . breakableUrl ( StringUtils . htmlEscape ( range . text ) ) ;
753- displayPath += '</span>' ;
754747
755- if ( range . segment === 0 ) {
756- var rightmostSlash = range . text . lastIndexOf ( '/' ) ;
757- if ( rightmostSlash > - 1 ) {
758- displayName += StringUtils . htmlEscape ( range . text . substring ( rightmostSlash + 1 ) ) ;
759- } else {
760- displayName += StringUtils . htmlEscape ( range . text ) ;
761- }
748+ var rangeText = rangeFilter ? rangeFilter ( range . segment , range . text ) : range . text ;
749+ displayName += StringUtils . breakableUrl ( StringUtils . htmlEscape ( rangeText ) ) ;
750+
751+ if ( range . matched ) {
752+ displayName += "</span>" ;
762753 }
763- displayName += '</span>' ;
764754 } ) ;
755+ return displayName ;
756+ }
757+
758+ function defaultResultsFormatter ( item , query ) {
759+ query = query . slice ( query . indexOf ( "@" ) + 1 , query . length ) ;
760+
761+ var displayName = highlightMatch ( item ) ;
762+ return "<li>" + displayName + "</li>" ;
763+ }
764+
765+ function _filenameResultsFormatter ( item , query ) {
766+ // For main label, we just want filename: drop most of the string
767+ function fileNameFilter ( segment , rangeText ) {
768+ if ( segment === 0 ) {
769+ var rightmostSlash = rangeText . lastIndexOf ( '/' ) ;
770+ return rangeText . substring ( rightmostSlash + 1 ) ; // safe even if rightmostSlash is -1
771+ } else {
772+ return "" ;
773+ }
774+ }
775+ var displayName = highlightMatch ( item , null , fileNameFilter ) ;
776+ var displayPath = highlightMatch ( item , "quicksearch-pathmatch" ) ;
765777
766778 return "<li>" + displayName + "<br /><span class='quick-open-path'>" + displayPath + "</span></li>" ;
767779 }
@@ -938,4 +950,5 @@ define(function (require, exports, module) {
938950 exports . stringMatch = stringMatch ;
939951 exports . basicMatchSort = basicMatchSort ;
940952 exports . multiFieldSort = multiFieldSort ;
953+ exports . highlightMatch = highlightMatch ;
941954} ) ;
0 commit comments