text.ts 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import { TextMatch } from 'app/types/explore';
  2. import xss from 'xss';
  3. /**
  4. * Adapt findMatchesInText for react-highlight-words findChunks handler.
  5. * See https://github.com/bvaughn/react-highlight-words#props
  6. */
  7. export function findHighlightChunksInText({ searchWords, textToHighlight }) {
  8. return findMatchesInText(textToHighlight, searchWords.join(' '));
  9. }
  10. const cleanNeedle = (needle: string): string => {
  11. return needle.replace(/[[{(][\w,.-?:*+]+$/, '');
  12. };
  13. /**
  14. * Returns a list of substring regexp matches.
  15. */
  16. export function findMatchesInText(haystack: string, needle: string): TextMatch[] {
  17. // Empty search can send re.exec() into infinite loop, exit early
  18. if (!haystack || !needle) {
  19. return [];
  20. }
  21. const matches = [];
  22. const cleaned = cleanNeedle(needle);
  23. let regexp: RegExp;
  24. try {
  25. regexp = new RegExp(`(?:${cleaned})`, 'g');
  26. } catch (error) {
  27. return matches;
  28. }
  29. haystack.replace(regexp, (substring, ...rest) => {
  30. if (substring) {
  31. const offset = rest[rest.length - 2];
  32. matches.push({
  33. text: substring,
  34. start: offset,
  35. length: substring.length,
  36. end: offset + substring.length,
  37. });
  38. }
  39. return '';
  40. });
  41. return matches;
  42. }
  43. const XSSWL = Object.keys(xss.whiteList).reduce((acc, element) => {
  44. acc[element] = xss.whiteList[element].concat(['class', 'style']);
  45. return acc;
  46. }, {});
  47. const sanitizeXSS = new xss.FilterXSS({
  48. whiteList: XSSWL,
  49. });
  50. /**
  51. * Returns string safe from XSS attacks.
  52. *
  53. * Even though we allow the style-attribute, there's still default filtering applied to it
  54. * Info: https://github.com/leizongmin/js-xss#customize-css-filter
  55. * Whitelist: https://github.com/leizongmin/js-css-filter/blob/master/lib/default.js
  56. */
  57. export function sanitize(unsanitizedString: string): string {
  58. try {
  59. return sanitizeXSS.process(unsanitizedString);
  60. } catch (error) {
  61. console.log('String could not be sanitized', unsanitizedString);
  62. return unsanitizedString;
  63. }
  64. }
  65. export function hasAnsiCodes(input: string): boolean {
  66. return /\u001b\[\d{1,2}m/.test(input);
  67. }