Update search text highlighting to escape HTML (#16760)

refs: https://github.com/TryGhost/Team/issues/2390

Escapes each matched and non-matched segment of the post title in the
admin search field, to make sure they're displayed in plain text but
still have matches highlighted.
This commit is contained in:
Jono M 2023-05-11 09:53:05 +12:00 committed by GitHub
parent 7f254a0143
commit 62f7600aa4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 1 deletions

View File

@ -1,11 +1,28 @@
import Ember from 'ember';
import {helper} from '@ember/component/helper';
import {htmlSafe} from '@ember/template';
const {Handlebars} = Ember;
export function highlightedText([text, termToHighlight]) {
// replace any non-word character with an escaped character
let sanitisedTerm = termToHighlight.replace(new RegExp(/\W/ig), '\\$&');
let termMatcher = new RegExp(sanitisedTerm, 'ig');
return htmlSafe(text.replace(new RegExp(sanitisedTerm, 'ig'), '<span class="highlight">$&</span>'));
let matches = text.match(termMatcher) || [];
let nonMatches = text.split(termMatcher);
let htmlSafeResult = '';
nonMatches.forEach((nonMatch, index) => {
htmlSafeResult += Handlebars.Utils.escapeExpression(nonMatch);
if (matches[index]) {
htmlSafeResult += `<span class="highlight">${Handlebars.Utils.escapeExpression(matches[index])}</span>`;
}
});
return htmlSafe(htmlSafeResult);
}
export default helper(highlightedText);

View File

@ -13,4 +13,10 @@ describe('Unit: Helper: highlighted-text', function () {
expect(result).to.be.an('object');
expect(result.string).to.equal('T<span class="highlight">e</span>st');
});
it('escapes html', function () {
let result = highlightedText(['<script>alert("oops")</script>', 'oops']);
expect(result).to.be.an('object');
expect(result.string).to.equal('&lt;script&gt;alert(&quot;<span class="highlight">oops</span>&quot;)&lt;/script&gt;');
});
});