index.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import React, { PureComponent } from 'react';
  2. import cls from 'classnames';
  3. import PropTypes, { string } from 'prop-types';
  4. import { cssClasses } from '@douyinfe/semi-foundation/highlight/constants';
  5. import HighlightFoundation from '@douyinfe/semi-foundation/highlight/foundation';
  6. import type { SearchWords, Chunk } from '@douyinfe/semi-foundation/highlight/foundation';
  7. import '@douyinfe/semi-foundation/highlight/highlight.scss';
  8. interface GetHighLightTextHTMLProps {
  9. sourceString?: string;
  10. searchWords?: SearchWords;
  11. option: HighLightTextHTMLOption
  12. }
  13. interface HighLightTextHTMLOption {
  14. highlightTag?: string;
  15. highlightClassName?: string;
  16. highlightStyle?: React.CSSProperties;
  17. caseSensitive: boolean;
  18. autoEscape: boolean
  19. }
  20. interface HighLightTextHTMLChunk extends Chunk { }
  21. export interface HighlightProps {
  22. autoEscape?: boolean;
  23. caseSensitive?: boolean;
  24. sourceString?: string;
  25. searchWords?: SearchWords;
  26. highlightStyle?: React.CSSProperties;
  27. highlightClassName?: string;
  28. component?: string
  29. }
  30. const prefixCls = cssClasses.PREFIX;
  31. class Highlight extends PureComponent<HighlightProps> {
  32. static propTypes = {
  33. style: PropTypes.object,
  34. className: PropTypes.string,
  35. autoEscape: PropTypes.bool,
  36. caseSensitive: PropTypes.bool,
  37. sourceString: PropTypes.string,
  38. searchWords: PropTypes.arrayOf(PropTypes.string),
  39. highlightStyle: PropTypes.object,
  40. highlightClassName: PropTypes.string,
  41. component: PropTypes.string
  42. };
  43. static defaultProps = {
  44. component: 'mark',
  45. autoEscape: true,
  46. caseSensitive: false,
  47. sourceString: '',
  48. };
  49. getHighLightTextHTML = ({
  50. sourceString = '',
  51. searchWords = [],
  52. option = { autoEscape: true, caseSensitive: false }
  53. }: GetHighLightTextHTMLProps) => {
  54. const chunks: HighLightTextHTMLChunk[] = new HighlightFoundation().findAll({ sourceString, searchWords, ...option });
  55. const markEle = option.highlightTag || 'mark';
  56. const highlightClassName = option.highlightClassName || '';
  57. const highlightStyle = option.highlightStyle || {};
  58. return chunks.map((chunk: HighLightTextHTMLChunk, index: number) => {
  59. const { end, start, highlight, style, className } = chunk;
  60. const text = sourceString.substr(start, end - start);
  61. if (highlight) {
  62. return React.createElement(
  63. markEle,
  64. {
  65. style: { ...highlightStyle, ...style },
  66. className: `${highlightClassName} ${className || ''}`.trim(),
  67. key: text + index
  68. },
  69. text
  70. );
  71. } else {
  72. return text;
  73. }
  74. });
  75. };
  76. render() {
  77. const {
  78. searchWords,
  79. sourceString,
  80. component,
  81. highlightClassName,
  82. highlightStyle,
  83. caseSensitive,
  84. autoEscape,
  85. } = this.props;
  86. const tagCls = cls({
  87. [`${prefixCls}-tag`]: true,
  88. }, highlightClassName);
  89. const option = {
  90. highlightTag: component,
  91. highlightClassName: tagCls,
  92. highlightStyle,
  93. caseSensitive,
  94. autoEscape,
  95. };
  96. return (
  97. this.getHighLightTextHTML({ sourceString, searchWords, option })
  98. );
  99. }
  100. }
  101. export default Highlight;