Skip to content
This repository has been archived by the owner on Dec 30, 2022. It is now read-only.

Commit

Permalink
feat(store): allow to use custom highlight tags
Browse files Browse the repository at this point in the history
  • Loading branch information
rayrutjes committed Jul 21, 2017
1 parent 62858b2 commit c77f336
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 37 deletions.
15 changes: 6 additions & 9 deletions src/__tests__/sanitize-results.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,20 @@ test('it ensures results are provided in the correct format', () => {
});

test('it ensures tags are provided in the correct format', () => {
const expectedException = new TypeError(
'safePreTag and safePostTag should be provided as strings.'
);
expect(() => {
sanitizeResults([]);
}).toThrow(
new TypeError('preTag and postTag should be provided as strings.')
);
}).toThrow(expectedException);

expect(() => {
sanitizeResults([], 'pre');
}).toThrow(
new TypeError('preTag and postTag should be provided as strings.')
);
}).toThrow(expectedException);

expect(() => {
sanitizeResults([], {}, 'post');
}).toThrow(
new TypeError('preTag and postTag should be provided as strings.')
);
}).toThrow(expectedException);
});

test('it should escape HTML of highlighted values', () => {
Expand Down
53 changes: 40 additions & 13 deletions src/__tests__/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import {
FACET_AND,
FACET_OR,
FACET_TREE,
HIGHLIGHT_PRE_TAG,
HIGHLIGHT_POST_TAG,
assertValidFacetType,
createFromAlgoliaCredentials,
createFromAlgoliaClient,
Expand All @@ -32,14 +30,6 @@ test('FACET_TREE should be "tree"', () => {
expect(FACET_TREE).toBe('tree');
});

test('HIGHLIGHT_PRE_TAG should be "__ais-highlight__"', () => {
expect(HIGHLIGHT_PRE_TAG).toBe('__ais-highlight__');
});

test('HIGHLIGHT_POST_TAG should be "__/ais-highlight__"', () => {
expect(HIGHLIGHT_POST_TAG).toBe('__/ais-highlight__');
});

test('can assert that a facet type is valid', () => {
expect(() => {
assertValidFacetType(FACET_AND);
Expand Down Expand Up @@ -86,11 +76,11 @@ describe('Store', () => {
);
});

test('should always use custom highlighting tags', () => {
test('should use "em" as default default highlighting tag', () => {
const store = createStore();

expect(store.highlightPreTag).toEqual(HIGHLIGHT_PRE_TAG);
expect(store.highlightPostTag).toEqual(HIGHLIGHT_POST_TAG);
expect(store.highlightPreTag).toEqual('<em>');
expect(store.highlightPostTag).toEqual('</em>');
});

test('can retrieve index name', () => {
Expand Down Expand Up @@ -368,4 +358,41 @@ describe('Store', () => {
},
]);
});

test('should accept custom highlighting tags', () => {
const store = createStore();
store.highlightPreTag = '<mark class="hl">';
store.highlightPostTag = '</mark>';
const response = {
hits: [
{
objectID: '1',
name: 'test',
_highlightResult: {
name: {
value:
"__ais-highlight__te__/ais-highlight__st<script>alert('test')</script>",
matchLevel: 'full',
},
},
},
],
};

store._helper.emit('result', response);

expect(store.results).toEqual([
{
objectID: '1',
name: 'test',
_highlightResult: {
name: {
value:
'<mark class="hl">te</mark>st&lt;script&gt;alert(&#39;test&#39;)&lt;/script&gt;',
matchLevel: 'full',
},
},
},
]);
});
});
48 changes: 36 additions & 12 deletions src/sanitize-results.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,41 @@
import escapeHtml from 'escape-html';

export default function(results, preTag, postTag, tagName = 'em') {
export default function(
results,
safePreTag,
safePostTag,
preTag = '<em>',
postTag = '</em>'
) {
if (!Array.isArray(results)) {
throw new TypeError('Results should be provided as an array.');
}

if (typeof preTag !== 'string' || typeof postTag !== 'string') {
throw new TypeError('preTag and postTag should be provided as strings.');
if (typeof safePreTag !== 'string' || typeof safePostTag !== 'string') {
throw new TypeError(
'safePreTag and safePostTag should be provided as strings.'
);
}

const sanitized = [];
for (const result of results) {
if ('_highlightResult' in result) {
result._highlightResult = sanitizeHighlights(
result._highlightResult,
safePreTag,
safePostTag,
preTag,
postTag,
tagName
postTag
);
}

if ('_snippetResult' in result) {
result._snippetResult = sanitizeHighlights(
result._snippetResult,
safePreTag,
safePostTag,
preTag,
postTag,
tagName
postTag
);
}

Expand All @@ -35,12 +45,18 @@ export default function(results, preTag, postTag, tagName = 'em') {
return sanitized;
}

const sanitizeHighlights = function(data, preTag, postTag, tagName) {
const sanitizeHighlights = function(
data,
safePreTag,
safePostTag,
preTag,
postTag
) {
if (containsValue(data)) {
const sanitized = Object.assign({}, data, {
value: escapeHtml(data.value)
.replace(new RegExp(preTag, 'g'), `<${tagName}>`)
.replace(new RegExp(postTag, 'g'), `</${tagName}>`),
.replace(new RegExp(safePreTag, 'g'), preTag)
.replace(new RegExp(safePostTag, 'g'), postTag),
});

return sanitized;
Expand All @@ -49,7 +65,9 @@ const sanitizeHighlights = function(data, preTag, postTag, tagName) {
if (Array.isArray(data)) {
const child = [];
data.forEach(item => {
child.push(sanitizeHighlights(item, preTag, postTag, tagName));
child.push(
sanitizeHighlights(item, safePreTag, safePostTag, preTag, postTag)
);
});

return child;
Expand All @@ -59,7 +77,13 @@ const sanitizeHighlights = function(data, preTag, postTag, tagName) {
const keys = Object.keys(data);
const child = {};
keys.forEach(key => {
child[key] = sanitizeHighlights(data[key], preTag, postTag, tagName);
child[key] = sanitizeHighlights(
data[key],
safePreTag,
safePostTag,
preTag,
postTag
);
});

return child;
Expand Down
17 changes: 14 additions & 3 deletions src/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ const onHelperResult = function(response) {
response.hits,
HIGHLIGHT_PRE_TAG,
HIGHLIGHT_POST_TAG,
'em'
this.highlightPreTag,
this.highlightPostTag
);
};

Expand All @@ -51,6 +52,8 @@ export class Store {
this._stoppedCounter = 1;

this.algoliaHelper = helper;
this._highlightPreTag = '<em>';
this._highlightPostTag = '</em>';
}

set algoliaHelper(helper) {
Expand Down Expand Up @@ -85,11 +88,19 @@ export class Store {
}

get highlightPreTag() {
return this._helper.getQueryParameter('highlightPreTag');
return this._highlightPreTag;
}

set highlightPreTag(tag) {
this._highlightPreTag = tag;
}

get highlightPostTag() {
return this._helper.getQueryParameter('highlightPostTag');
return this._highlightPostTag;
}

set highlightPostTag(tag) {
this._highlightPostTag = tag;
}

set algoliaClient(algoliaClient) {
Expand Down

0 comments on commit c77f336

Please sign in to comment.