mirror of
https://github.com/StarCitizenTools/mediawiki-skins-Citizen.git
synced 2024-11-15 02:24:04 +00:00
refactor(core): ♻️ move some suggestion functions to searchResults
This commit is contained in:
parent
434ec2ebaf
commit
ae7a01f690
|
@ -2,8 +2,77 @@
|
||||||
// const htmlHelper = require( './htmlHelper.js' )();
|
// const htmlHelper = require( './htmlHelper.js' )();
|
||||||
const searchAction = require( './searchAction.js' )();
|
const searchAction = require( './searchAction.js' )();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an object with methods related to search results handling.
|
||||||
|
*
|
||||||
|
* @return {Object} An object with the following methods:
|
||||||
|
* - getRedirectLabel: A function that generates HTML for a search result label with redirection information.
|
||||||
|
* - highlightTitle: A function that highlights a matched title within a given text.
|
||||||
|
* - fetch: A function that fetches search results based on a query value using an active search client.
|
||||||
|
* - render: A function that renders search results in a specified typeahead element.
|
||||||
|
* - clear: A function that clears search results from a typeahead element.
|
||||||
|
*/
|
||||||
function searchResults() {
|
function searchResults() {
|
||||||
return {
|
return {
|
||||||
|
getRedirectLabel: function ( title, matchedTitle, queryValue ) {
|
||||||
|
const normalizeText = ( text ) => {
|
||||||
|
return text.replace( /[-\s]/g, ( match ) => match.toLowerCase() ).toLowerCase();
|
||||||
|
};
|
||||||
|
|
||||||
|
const redirectMessageCache = {};
|
||||||
|
const getRedirectMessage = () => {
|
||||||
|
if ( !redirectMessageCache[ matchedTitle ] ) {
|
||||||
|
redirectMessageCache[ matchedTitle ] = mw.message( 'search-redirect', matchedTitle ).plain();
|
||||||
|
}
|
||||||
|
return redirectMessageCache[ matchedTitle ];
|
||||||
|
};
|
||||||
|
|
||||||
|
const isRedirectUseful = () => {
|
||||||
|
const cleanTitle = normalizeText( title );
|
||||||
|
const cleanMatchedTitle = normalizeText( matchedTitle );
|
||||||
|
|
||||||
|
return !(
|
||||||
|
cleanTitle.includes( cleanMatchedTitle ) ||
|
||||||
|
cleanMatchedTitle.includes( cleanTitle )
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateRedirectHtml = () => {
|
||||||
|
const div = document.createElement( 'div' );
|
||||||
|
div.classList.add( 'citizen-typeahead__labelItem' );
|
||||||
|
div.title = getRedirectMessage( matchedTitle );
|
||||||
|
|
||||||
|
const spanIcon = document.createElement( 'span' );
|
||||||
|
spanIcon.classList.add( 'citizen-ui-icon', 'mw-ui-icon-wikimedia-articleRedirect' );
|
||||||
|
div.appendChild( spanIcon );
|
||||||
|
|
||||||
|
const spanText = document.createElement( 'span' );
|
||||||
|
spanText.textContent = this.highlightTitle( matchedTitle, queryValue );
|
||||||
|
div.appendChild( spanText );
|
||||||
|
|
||||||
|
return div.outerHTML;
|
||||||
|
};
|
||||||
|
|
||||||
|
let html = '';
|
||||||
|
if ( matchedTitle && isRedirectUseful() ) {
|
||||||
|
html = generateRedirectHtml();
|
||||||
|
}
|
||||||
|
|
||||||
|
return html;
|
||||||
|
},
|
||||||
|
highlightTitle: ( function () {
|
||||||
|
const regexCache = {};
|
||||||
|
return function ( title, match ) {
|
||||||
|
if ( !match ) {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
if ( !regexCache[ match ] ) {
|
||||||
|
regexCache[ match ] = new RegExp( mw.util.escapeRegExp( match ), 'i' );
|
||||||
|
}
|
||||||
|
const regex = regexCache[ match ];
|
||||||
|
return title.replace( regex, '<span class="citizen-typeahead__highlight">$&</span>' );
|
||||||
|
};
|
||||||
|
}() ),
|
||||||
fetch: function ( queryValue, activeSearchClient ) {
|
fetch: function ( queryValue, activeSearchClient ) {
|
||||||
return activeSearchClient.fetchByTitle( queryValue );
|
return activeSearchClient.fetchByTitle( queryValue );
|
||||||
},
|
},
|
||||||
|
|
|
@ -344,57 +344,6 @@ async function getSuggestions() {
|
||||||
const renderSuggestions = ( results ) => {
|
const renderSuggestions = ( results ) => {
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = document.createDocumentFragment();
|
||||||
if ( results.length > 0 ) {
|
if ( results.length > 0 ) {
|
||||||
/**
|
|
||||||
* Return the redirect title with search query highlight
|
|
||||||
*
|
|
||||||
* @param {string} text
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
const highlightTitle = ( text ) => {
|
|
||||||
const regex = new RegExp( mw.util.escapeRegExp( searchQuery.valueHtml ), 'i' );
|
|
||||||
return text.replace( regex, `<span class="${ PREFIX }__highlight">$&</span>` );
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Return the HTML of the redirect label
|
|
||||||
*
|
|
||||||
* @param {string} title
|
|
||||||
* @param {string} matchedTitle
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
const getRedirectLabel = ( title, matchedTitle ) => {
|
|
||||||
/**
|
|
||||||
* Check if the redirect is useful (T303013)
|
|
||||||
*
|
|
||||||
* @return {boolean}
|
|
||||||
*/
|
|
||||||
const isRedirectUseful = () => {
|
|
||||||
// Change to lowercase then remove space and dashes
|
|
||||||
const cleanup = ( text ) => {
|
|
||||||
return text.toLowerCase().replace( /[-\s]/g, '' );
|
|
||||||
};
|
|
||||||
const
|
|
||||||
cleanTitle = cleanup( title ),
|
|
||||||
cleanMatchedTitle = cleanup( matchedTitle );
|
|
||||||
|
|
||||||
return !(
|
|
||||||
cleanTitle.includes( cleanMatchedTitle ) ||
|
|
||||||
cleanMatchedTitle.includes( cleanTitle )
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
let html = '';
|
|
||||||
// Result is a redirect
|
|
||||||
// Show the redirect title and highlight it
|
|
||||||
if ( matchedTitle && isRedirectUseful() ) {
|
|
||||||
html = `<div class="${ PREFIX }__labelItem" title="${ mw.message( 'search-redirect', matchedTitle ).plain() }">
|
|
||||||
<span class="citizen-ui-icon mw-ui-icon-wikimedia-articleRedirect"></span>
|
|
||||||
<span>${ highlightTitle( matchedTitle ) }</span>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return html;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create suggestion items
|
// Create suggestion items
|
||||||
const itemGroupData = {
|
const itemGroupData = {
|
||||||
id: 'suggestion',
|
id: 'suggestion',
|
||||||
|
@ -405,10 +354,10 @@ async function getSuggestions() {
|
||||||
type: 'page',
|
type: 'page',
|
||||||
size: 'md',
|
size: 'md',
|
||||||
link: result.url,
|
link: result.url,
|
||||||
title: highlightTitle( result.title ),
|
title: searchResults.highlightTitle( result.title, searchQuery.valueHtml ),
|
||||||
desc: result.description
|
desc: result.description
|
||||||
};
|
};
|
||||||
data.label = getRedirectLabel( result.title, result.label );
|
data.label = searchResults.getRedirectLabel( result.title, result.label );
|
||||||
if ( result.thumbnail ) {
|
if ( result.thumbnail ) {
|
||||||
data.thumbnail = result.thumbnail.url;
|
data.thumbnail = result.thumbnail.url;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue