22// Use of this source code is governed by a BSD-style license that can be
33// found in the LICENSE file.
44/* eslint-disable rulesdir/no-imperative-dom-api */
5+ /* eslint-disable rulesdir/no-lit-render-outside-of-view */
56
67import * as Common from '../../core/common/common.js' ;
78import * as i18n from '../../core/i18n/i18n.js' ;
89import * as Platform from '../../core/platform/platform.js' ;
910import * as TextUtils from '../../models/text_utils/text_utils.js' ;
1011import type * as Workspace from '../../models/workspace/workspace.js' ;
11- import * as Components from '../../ui/legacy/components/utils/utils.js' ;
1212import * as UI from '../../ui/legacy/legacy.js' ;
13+ import { html , render } from '../../ui/lit/lit.js' ;
1314
1415import searchResultsPaneStyles from './searchResultsPane.css.js' ;
1516import type { SearchResult } from './SearchScope.js' ;
@@ -137,31 +138,23 @@ export class SearchResultsTreeElement extends UI.TreeOutline.TreeElement {
137138
138139 private updateSearchMatches ( ) : void {
139140 this . listItemElement . classList . add ( 'search-result' ) ;
140-
141- const fileNameSpan = span ( this . searchResult . label ( ) , 'search-result-file-name' ) ;
142- fileNameSpan . appendChild ( span ( '\u2014' , 'search-result-dash' ) ) ;
143- fileNameSpan . appendChild ( span ( this . searchResult . description ( ) , 'search-result-qualifier' ) ) ;
141+ // clang-format off
142+ render ( html `
143+ < span class ="search-result-file-name "> ${ this . searchResult . label ( ) }
144+ < span class ="search-result-dash "> ${ '\u2014' } </ span >
145+ < span class ="search-result-qualifier "> ${ this . searchResult . description ( ) } </ span >
146+ </ span >
147+ < span class ="search-result-matches-count "
148+ aria-label =${ i18nString ( UIStrings . matchesCountS , { PH1 : this . searchResult . matchesCount ( ) } ) } >
149+ ${ this . searchResult . matchesCount ( ) }
150+ </ span > ` ,
151+ this . listItemElement ) ;
152+ // clang-format on
144153
145154 this . tooltip = this . searchResult . description ( ) ;
146- this . listItemElement . appendChild ( fileNameSpan ) ;
147- const matchesCountSpan = document . createElement ( 'span' ) ;
148- matchesCountSpan . className = 'search-result-matches-count' ;
149-
150- matchesCountSpan . textContent = `${ this . searchResult . matchesCount ( ) } ` ;
151- UI . ARIAUtils . setLabel (
152- matchesCountSpan , i18nString ( UIStrings . matchesCountS , { PH1 : this . searchResult . matchesCount ( ) } ) ) ;
153-
154- this . listItemElement . appendChild ( matchesCountSpan ) ;
155155 if ( this . expanded ) {
156156 this . updateMatchesUI ( ) ;
157157 }
158-
159- function span ( text : string , className : string ) : Element {
160- const span = document . createElement ( 'span' ) ;
161- span . className = className ;
162- span . textContent = text ;
163- return span ;
164- }
165158 }
166159
167160 private appendSearchMatches ( fromIndex : number , toIndex : number ) : void {
@@ -195,28 +188,29 @@ export class SearchResultsTreeElement extends UI.TreeOutline.TreeElement {
195188 ( { lineSegment : lineContent , matchRanges} = lineSegmentForMultipleMatches ( lineContent , matchRanges ) ) ;
196189 }
197190
198- const anchor = Components . Linkifier . Linkifier . linkifyRevealable (
199- searchResult . matchRevealable ( i ) , '' , undefined , undefined , undefined , 'search-match' ) ;
200- anchor . classList . add ( 'search-match-link' ) ;
201- anchor . tabIndex = 0 ;
202- const labelSpan = document . createElement ( 'span' ) ;
203- labelSpan . classList . add ( 'search-match-line-number' ) ;
204191 const resultLabel = searchResult . matchLabel ( i ) ;
205- labelSpan . textContent = resultLabel ;
206- if ( typeof resultLabel === 'number' && ! isNaN ( resultLabel ) ) {
207- UI . ARIAUtils . setLabel ( labelSpan , i18nString ( UIStrings . lineS , { PH1 : resultLabel } ) ) ;
208- } else {
209- UI . ARIAUtils . setLabel ( labelSpan , resultLabel ) ;
210- }
211- anchor . appendChild ( labelSpan ) ;
212-
213- const contentSpan = this . createContentSpan ( lineContent , matchRanges ) ;
214- anchor . appendChild ( contentSpan ) ;
215192
216193 const searchMatchElement = new UI . TreeOutline . TreeElement ( ) ;
217194 this . appendChild ( searchMatchElement ) ;
195+ // clang-format off
196+ render ( html `
197+ < button class ="devtools-link text-button link-style search-match-link "
198+ jslog ="Link; context: search-match; track: click " role ="link " tabindex ="0 "
199+ @click =${ ( ) => void Common . Revealer . reveal ( searchResult . matchRevealable ( i ) ) } >
200+ < span class ="search-match-line-number "
201+ aria-label =${ typeof resultLabel === 'number' && ! isNaN ( resultLabel )
202+ ? i18nString ( UIStrings . lineS , { PH1 : resultLabel } ) : resultLabel } >
203+ ${ resultLabel }
204+ </ span >
205+ < span class ="search-match-content " aria-label ="${ lineContent } line ">
206+ ${ lineContent }
207+ </ span >
208+ </ button > ` ,
209+ searchMatchElement . listItemElement ) ;
210+ // clang-format on
211+ const contentSpan = searchMatchElement . listItemElement . querySelector ( '.search-match-content' ) as HTMLElement ;
212+ UI . UIUtils . highlightRangesWithStyleClass ( contentSpan , matchRanges , 'highlighted-search-result' ) ;
218213 searchMatchElement . listItemElement . className = 'search-match' ;
219- searchMatchElement . listItemElement . appendChild ( anchor ) ;
220214 searchMatchElement . listItemElement . addEventListener ( 'keydown' , event => {
221215 if ( event . key === 'Enter' ) {
222216 event . consume ( true ) ;
@@ -237,15 +231,6 @@ export class SearchResultsTreeElement extends UI.TreeOutline.TreeElement {
237231 this . showMoreMatchesElementSelected . bind ( this , showMoreMatchesTreeElement , startMatchIndex ) ;
238232 }
239233
240- private createContentSpan ( lineContent : string , matchRanges : TextUtils . TextRange . SourceRange [ ] ) : Element {
241- const contentSpan = document . createElement ( 'span' ) ;
242- contentSpan . className = 'search-match-content' ;
243- contentSpan . textContent = lineContent ;
244- UI . ARIAUtils . setLabel ( contentSpan , `${ lineContent } line` ) ;
245- UI . UIUtils . highlightRangesWithStyleClass ( contentSpan , matchRanges , 'highlighted-search-result' ) ;
246- return contentSpan ;
247- }
248-
249234 private regexMatchRanges ( lineContent : string , regex : RegExp ) : TextUtils . TextRange . SourceRange [ ] {
250235 regex . lastIndex = 0 ;
251236 let match ;
0 commit comments