Skip to content

Commit

Permalink
Use highlighted response from content search to highlight, remove glo…
Browse files Browse the repository at this point in the history
…bal matching for JS search
  • Loading branch information
Dananji committed Jun 26, 2024
1 parent 3e24639 commit 08ae4d3
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/services/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { markMatchedParts, getMatchedTranscriptLines, parseContentSearchResponse
export const defaultMatcherFactory = (items) => {
const mappedItems = items.map(item => item.text.toLocaleLowerCase());
return (query, abortController) => {
const queryRegex = buildQueryRegex(query);
const queryRegex = new RegExp(String.raw`\b${query}\b`, 'i');
const qStr = query.trim().toLocaleLowerCase();
const matchedItems = mappedItems.reduce((results, mappedText, idx) => {
const matchOffset = mappedText.search(queryRegex);
Expand Down
22 changes: 14 additions & 8 deletions src/services/search.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ describe('useFilteredTranscripts', () => {
};
const { resultRef, Component } = createTest({ matcherFactory, query: 'Gatsby' });
render(Component);
await waitFor(() => expect(resultRef.current.matchingIds).toEqual([5, 7]));
await waitFor(() => expect(resultRef.current.matchingIds).toEqual([1, 4, 5, 7]));
});
});

Expand All @@ -106,8 +106,8 @@ describe('useFilteredTranscripts', () => {
matchesOnly: true
});
render(Component);
await waitFor(() => expect(resultRef.current.ids).toEqual([5, 7]));
expect(resultRef.current.matchingIds).toEqual([5, 7]);
await waitFor(() => expect(resultRef.current.ids).toEqual([4, 1, 5, 7]));
expect(resultRef.current.matchingIds).toEqual([4, 1, 5, 7]);
});
test('without matchesOnly, ids will also be sorted', async () => {
const { resultRef, Component } = createTest({
Expand Down Expand Up @@ -136,7 +136,7 @@ describe('useFilteredTranscripts', () => {
});
render(Component);
await waitFor(() => expect(resultRef.current.ids).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8]));
expect(resultRef.current.matchingIds).toEqual([5, 7]);
expect(resultRef.current.matchingIds).toEqual([4, 1, 5, 7]);
});

});
Expand All @@ -156,21 +156,27 @@ describe('useFilteredTranscripts', () => {
test('when the search query is set, matchingIds will contain ids of matches', async () => {
const { resultRef, Component } = createTest({ query: 'Gatsby' });
render(Component);
await waitFor(() => expect(resultRef.current.matchingIds).toEqual([5, 7]));
await waitFor(() => expect(resultRef.current.matchingIds).toEqual([1, 4, 5, 7]));
});
test('when matchesOnly is true, only matching results are returned', async () => {
const { resultRef, Component } = createTest({ query: 'Gatsby', matchesOnly: true });
render(Component);
await waitFor(() => expect(resultRef.current.ids).toEqual([5, 7]));
await waitFor(() => expect(resultRef.current.ids).toEqual([1, 4, 5, 7]));
});
test('results included in the match set will include a match property for highlighting matches', async () => {
const { resultRef, Component } = createTest({ query: 'Gatsby' });
render(Component);
await waitFor(() => {
expect(resultRef.current.results[5].match).toEqual(
'Once there they were introduced by somebody who knew <span class="ramp--transcript_highlight">Gatsby</span>,'
expect(resultRef.current.results[1].match).toEqual(
'I believe that on the first night I went to <span class="ramp--transcript_highlight">Gatsby</span>\'s house'
);
});
expect(resultRef.current.results[4].match).toEqual(
'and somehow they ended up at <span class="ramp--transcript_highlight">Gatsby</span>\'s door.'
);
expect(resultRef.current.results[5].match).toEqual(
'Once there they were introduced by somebody who knew <span class="ramp--transcript_highlight">Gatsby</span>,'
);
expect(resultRef.current.results[7].match).toEqual(
'Sometimes they came and went without having met <span class="ramp--transcript_highlight">Gatsby</span> at all,'
);
Expand Down
41 changes: 25 additions & 16 deletions src/services/transcript-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@ export const getMatchedTranscriptLines = (searchHits, query, transcripts) => {
}
const matchOffset = mappedText.toLocaleLowerCase().indexOf(qStr);
if (matchOffset !== -1 && transcirptId != undefined) {
const match = markMatchedParts(mappedText, qStr);
const match = markMatchedParts(value, qStr, true);

transcriptLines.push({
...hit,
Expand All @@ -854,11 +854,32 @@ export const getMatchedTranscriptLines = (searchHits, query, transcripts) => {
* within the cue.
* @param {String} text matched transcript text/cue
* @param {String} query current search query
* @param {Boolean} hasHighlight boolean flag to indicate text has <em> tags
* @returns matched cue with HTML tags added for marking the hightlight
*/
export const markMatchedParts = (text, query) => {
const queryRegex = buildQueryRegex(query);
return text.replace(queryRegex, `<span class="ramp--transcript_highlight">$&</span>`);
export const markMatchedParts = (text, query, hasHighlight = false) => {
let replacerFn = (match) => {
const cleanedMatch = match.replace(/<\/?[^>]+>/gi, '');
return `<span class="ramp--transcript_highlight">${cleanedMatch}</span>`;
};
let queryFormatted = query;
/**
* Content search response for a phrase search like 'Mr. Bungle' gives the response
* with highlights in the matched text as <em>Mr</em>. <em>Bungle</em>.
* So reconstruct the search query in the UI to match this phrase in the response.
*/
if (hasHighlight) {
queryFormatted = query.split(' ').map(t => {
if (t.match(/[.,!?;:]$/)) {
const m = t.match(/[.,!?;:]/);
return `<em>${t.slice(0, m.index)}</em>${t.slice(m.index)}`;
} else {
return `<em>${t}</em>`;
}
}).join(' ');
}
const queryRegex = new RegExp(String.raw`${queryFormatted}`, 'gi');
return text.replace(queryRegex, replacerFn); //`<span class="ramp--transcript_highlight">$&</span>`);
};

/**
Expand All @@ -883,18 +904,6 @@ export const getHitCountForCue = (text, query, hasHighlight = false) => {
return hitCount;
};

/**
* Build a regular expression to omit matches including;
* - succeeding characters to the entered query
* - word contractions when query is used with auxiliary verbs
* @param {String} query search query entered by user
* @returns a regular expression
*/
export const buildQueryRegex = (query) => {
const queryRegex = new RegExp(String.raw`\b${query}\b(?=[\s.,!?;:]|$)`, 'gi');
return queryRegex;
};

// TODO:: Could be used for marking search hits in Word Doc transcripts?
// export const splitIntoElements = (htmlContent) => {
// // Create a temporary DOM element to parse the HTML
Expand Down

0 comments on commit 08ae4d3

Please sign in to comment.