Skip to content

Commit

Permalink
feat: search ignore diacritical marks (#1434)
Browse files Browse the repository at this point in the history
* feat: search ignore diacritical marks

* Check if normalize is supported

* Update docs

* Fix escape

* remove escapeHtml

Co-authored-by: John Hildenbiddle <jhildenbiddle@users.noreply.github.com>
  • Loading branch information
sy-records and jhildenbiddle committed Feb 5, 2021
1 parent c7f4c7c commit 8968a74
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 5 deletions.
6 changes: 6 additions & 0 deletions docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ By default, the hyperlink on the current page is recognized and the content is s
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
```

This plugin ignores diacritical marks when performing a full text search (e.g., "cafe" will also match "café"). Legacy browsers like IE11 require the following [String.normalize()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize) polyfill to ignore diacritical marks:

```html
<script src="//polyfill.io/v3/polyfill.min.js?features=String.prototype.normalize"></script>
```

## Google Analytics

Install the plugin and configure the track id.
Expand Down
28 changes: 23 additions & 5 deletions src/plugins/search/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,13 @@ export function genIndex(path, content = '', router, depth) {
return index;
}

export function ignoreDiacriticalMarks(keyword) {
if (keyword && keyword.normalize) {
return keyword.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}
return keyword;
}

/**
* @param {String} query Search query
* @returns {Array} Array of results
Expand All @@ -152,6 +159,8 @@ export function search(query) {
const post = data[i];
let matchesScore = 0;
let resultStr = '';
let handlePostTitle = '';
let handlePostContent = '';
const postTitle = post.title && post.title.trim();
const postContent = post.body && post.body.trim();
const postUrl = post.slug || '';
Expand All @@ -160,14 +169,23 @@ export function search(query) {
keywords.forEach(keyword => {
// From https://github.com/sindresorhus/escape-string-regexp
const regEx = new RegExp(
keyword.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'),
ignoreDiacriticalMarks(keyword).replace(
/[|\\{}()[\]^$+*?.]/g,
'\\$&'
),
'gi'
);
let indexTitle = -1;
let indexContent = -1;
handlePostTitle = postTitle
? ignoreDiacriticalMarks(postTitle)
: postTitle;
handlePostContent = postContent
? ignoreDiacriticalMarks(postContent)
: postContent;

indexTitle = postTitle ? postTitle.search(regEx) : -1;
indexContent = postContent ? postContent.search(regEx) : -1;
indexTitle = postTitle ? handlePostTitle.search(regEx) : -1;
indexContent = postContent ? handlePostContent.search(regEx) : -1;

if (indexTitle >= 0 || indexContent >= 0) {
matchesScore += indexTitle >= 0 ? 3 : indexContent >= 0 ? 2 : 0;
Expand All @@ -187,7 +205,7 @@ export function search(query) {

const matchContent =
'...' +
escapeHtml(postContent)
handlePostContent
.substring(start, end)
.replace(
regEx,
Expand All @@ -201,7 +219,7 @@ export function search(query) {

if (matchesScore > 0) {
const matchingPost = {
title: escapeHtml(postTitle),
title: handlePostTitle,
content: postContent ? resultStr : '',
url: postUrl,
score: matchesScore,
Expand Down
19 changes: 19 additions & 0 deletions test/e2e/search.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,23 @@ describe('Search Plugin Tests', function() {
await page.fill('input[type=search]', 'test');
await expect(page).toEqualText('.results-panel h2', 'Test Page');
});

test('search ignore diacritical marks', async () => {
const docsifyInitConfig = {
markdown: {
homepage: `
# Qué es
docsify genera su sitio web de documentación sobre la marcha. A diferencia de GitBook, no genera archivos estáticos html. En cambio, carga y analiza de forma inteligente sus archivos de Markdown y los muestra como sitio web. Todo lo que necesita hacer es crear un index.html para comenzar y desplegarlo en GitHub Pages.
`,
},
scriptURLs: ['/lib/plugins/search.min.js'],
};
await docsifyInit(docsifyInitConfig);
await page.fill('input[type=search]', 'documentacion');
await expect(page).toEqualText('.results-panel h2', 'Que es');
await page.click('.clear-button');
await page.fill('input[type=search]', 'estáticos');
await expect(page).toEqualText('.results-panel h2', 'Que es');
});
});

1 comment on commit 8968a74

@vercel
Copy link

@vercel vercel bot commented on 8968a74 Feb 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.