11import algoliasearch from 'algoliasearch/lite' ;
22import instantsearch from 'instantsearch.js' ;
3+ import historyRouter from 'instantsearch.js/es/lib/routers/history' ;
34import { connectSearchBox , connectCurrentRefinements } from 'instantsearch.js/es/connectors' ;
45import { hits , pagination , clearRefinements , menu , refinementList , configure , panel } from 'instantsearch.js/es/widgets' ;
56
@@ -34,6 +35,8 @@ if (decodeURI(location.search).match(/[<>]/)) {
3435 location . replace ( location . origin + location . pathname ) ;
3536}
3637
38+ var isSearchPage = location . pathname === '/search/' ;
39+ var originalPathname = location . pathname ;
3740var searchClient = algoliasearch ( algoliaConfig . app_id , algoliaConfig . search_key ) ;
3841var indexName = algoliaConfig . index_name ;
3942var searchThrottle = null ;
@@ -59,7 +62,12 @@ var customSearchClient = {
5962
6063// Show search container on initial load if URL has search params
6164var urlParams = new URLSearchParams ( window . location . search ) ;
62- if ( urlParams . get ( 'query' ) || urlParams . get ( 'q' ) || urlParams . get ( 'type' ) || urlParams . get ( 'tags' ) ) {
65+ var hasQuery = ( urlParams . get ( 'query' ) || '' ) . trim ( ) !== '' || ( urlParams . get ( 'q' ) || '' ) . trim ( ) !== '' ;
66+ var hasFilters = urlParams . get ( 'type' ) || urlParams . get ( 'tags' ) ;
67+ if ( ! isSearchPage && ! hasQuery && hasFilters ) {
68+ // Redirect to canonical /search/ URL with the filter params
69+ location . replace ( '/search/' + location . search ) ;
70+ } else if ( hasQuery || ( isSearchPage && hasFilters ) ) {
6371 document . querySelector ( '#search-container' ) . classList . remove ( 'hidden' ) ;
6472}
6573
@@ -70,9 +78,10 @@ var opts = {
7078 var indexState = uiState [ indexName ] || { } ;
7179 var searchResults = document . querySelector ( '#search-container' ) ;
7280
73- var hasSearch = ( indexState . query && indexState . query !== '' )
74- || ( indexState . menu && indexState . menu . type )
81+ var hasQuery = indexState . query && indexState . query . trim ( ) !== '' ;
82+ var hasFilters = ( indexState . menu && indexState . menu . type )
7583 || ( indexState . refinementList && indexState . refinementList . tags && indexState . refinementList . tags . length > 0 ) ;
84+ var hasSearch = hasQuery || ( isSearchPage && hasFilters ) ;
7685
7786 if ( ! hasSearch ) {
7887 searchResults . classList . add ( 'hidden' ) ;
@@ -98,6 +107,17 @@ var opts = {
98107 setUiState ( uiState ) ;
99108 } ,
100109 routing : {
110+ router : historyRouter ( {
111+ createURL : function ( { qsModule, routeState, location } ) {
112+ var queryString = qsModule . stringify ( routeState ) ;
113+ var protocol = location . protocol ;
114+ var hostname = location . hostname ;
115+ var port = location . port ? ':' + location . port : '' ;
116+ // Use /search/ as base path when there are search params, otherwise restore original path
117+ var pathname = queryString ? '/search/' : originalPathname ;
118+ return protocol + '//' + hostname + port + pathname + ( queryString ? '?' + queryString : '' ) + location . hash ;
119+ } ,
120+ } ) ,
101121 stateMapping : {
102122 stateToRoute : function ( uiState ) {
103123 var indexUiState = uiState [ indexName ] || { } ;
@@ -113,11 +133,10 @@ var opts = {
113133 routeState . query = routeState . q ;
114134 }
115135
116- if (
117- ( ! routeState . query || routeState . query === '' )
118- && ( ! routeState . type || routeState . type === '' )
119- && ( ! routeState . tags || routeState . tags === '' )
120- ) {
136+ var hasQuery = routeState . query && routeState . query . trim ( ) !== '' ;
137+ var hasFilters = ( routeState . type && routeState . type !== '' )
138+ || ( routeState . tags && routeState . tags !== '' ) ;
139+ if ( ! hasQuery && ! ( isSearchPage && hasFilters ) ) {
121140 return { [ indexName ] : { } } ;
122141 }
123142
@@ -251,7 +270,7 @@ search.addWidgets([
251270 if ( hit . abandoned ) {
252271 var replacementHtml = '' ;
253272 if ( hit . replacementPackage ) {
254- replacementHtml = ` See <a href="${ hit . replacementPackageUrl } ">${ hit . replacementPackage } </a>` ;
273+ replacementHtml = ` See <a href="${ hit . replacementPackageUrl } " rel="nofollow noindex" >${ hit . replacementPackage } </a>` ;
255274 }
256275 abandonedHtml = `<p class="abandoned"><i class="glyphicon glyphicon-exclamation-sign"></i> Abandoned!${ replacementHtml } </p>` ;
257276 }
@@ -275,7 +294,7 @@ search.addWidgets([
275294 <div class="col-sm-9 col-lg-10">
276295 <p class="pull-right language">${ hit . language || '' } </p>
277296 <h4 class="font-bold">
278- <a href="${ hit . url } " tabindex="2">${ nameHighlight } </a>${ extensionHtml }
297+ <a href="${ hit . url } " tabindex="2" rel="nofollow noindex" >${ nameHighlight } </a>${ extensionHtml }
279298 ${ virtualHtml }
280299 </h4>
281300 <p>${ descHighlight } </p>
@@ -330,4 +349,12 @@ if (location.href.match(/\/extensions/)) {
330349 search . addWidgets ( [ configure ( { filters : 'extension = 1' } ) ] ) ;
331350}
332351
352+ search . on ( 'render' , function ( ) {
353+ document . querySelectorAll ( '#search-container a[href]' ) . forEach ( function ( link ) {
354+ if ( ! link . getAttribute ( 'rel' ) ) {
355+ link . setAttribute ( 'rel' , 'nofollow noindex' ) ;
356+ }
357+ } ) ;
358+ } ) ;
359+
333360search . start ( ) ;
0 commit comments