UNPKG

react-highlight-words

Version:

React component to highlight words within a larger body of text

530 lines (451 loc) 18.5 kB
module.exports = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { module.exports = __webpack_require__(1); /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var _Highlighter = __webpack_require__(2); var _Highlighter2 = _interopRequireDefault(_Highlighter); exports['default'] = _Highlighter2['default']; module.exports = exports['default']; /***/ }), /* 2 */ /***/ (function(module, exports, __webpack_require__) { 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; exports['default'] = Highlighter; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } var _highlightWordsCore = __webpack_require__(3); var _react = __webpack_require__(4); var _memoizeOne = __webpack_require__(5); var _memoizeOne2 = _interopRequireDefault(_memoizeOne); /** * Highlighter component * @param {object} props - Component properties * @param {string} [props.activeClassName] - The class name to be applied to an active match. Use along with `activeIndex`. * @param {number} [props.activeIndex] - Specify the match index that should be actively highlighted. Use along with `activeClassName`. * @param {object} [props.activeStyle] - The inline style to be applied to an active match. Use along with `activeIndex`. * @param {boolean} [props.autoEscape] - Escape characters in searchWords which are meaningful in regular expressions. * @param {string} [props.className] - CSS class name applied to the outer/wrapper `<span>`. * @param {(options: object) => Array<{start: number, end: number}>} [props.findChunks] - Use a custom function to search for matching chunks. See the default `findChunks` function in `highlight-words-core` for signature. * @param {string|object} [props.highlightClassName] - CSS class name applied to highlighted text or object mapping search term matches to class names. * @param {object} [props.highlightStyle] - Inline styles applied to highlighted text. * @param {React.ComponentType|string} [props.highlightTag] - Type of tag to wrap around highlighted matches. Defaults to `mark` but can also be a React component (class or functional). * @param {(text: string) => string} [props.sanitize] - Process each search word and text to highlight before comparing. * @param {Array<string|RegExp>} props.searchWords - Array of search words. String search terms are automatically cast to RegExps unless `autoEscape` is true. * @param {string} props.textToHighlight - The text to highlight matches in. * @param {React.ComponentType|string} [props.unhighlightTag] - Type of tag applied to unhighlighted parts. Defaults to `span` but can also be a React component (class or functional). * @param {string} [props.unhighlightClassName] - CSS class name applied to unhighlighted text. * @param {object} [props.unhighlightStyle] - Inline styles applied to the unhighlighted text. * @param {object} [props.rest] - Additional attributes passed to the outer `<span>` element. */ function Highlighter(_ref) { var _ref$activeClassName = _ref.activeClassName; var activeClassName = _ref$activeClassName === undefined ? '' : _ref$activeClassName; var _ref$activeIndex = _ref.activeIndex; var activeIndex = _ref$activeIndex === undefined ? -1 : _ref$activeIndex; var activeStyle = _ref.activeStyle; var autoEscape = _ref.autoEscape; var _ref$caseSensitive = _ref.caseSensitive; var caseSensitive = _ref$caseSensitive === undefined ? false : _ref$caseSensitive; var className = _ref.className; var findChunks = _ref.findChunks; var _ref$highlightClassName = _ref.highlightClassName; var highlightClassName = _ref$highlightClassName === undefined ? '' : _ref$highlightClassName; var _ref$highlightStyle = _ref.highlightStyle; var highlightStyle = _ref$highlightStyle === undefined ? {} : _ref$highlightStyle; var _ref$highlightTag = _ref.highlightTag; var highlightTag = _ref$highlightTag === undefined ? 'mark' : _ref$highlightTag; var sanitize = _ref.sanitize; var searchWords = _ref.searchWords; var textToHighlight = _ref.textToHighlight; var _ref$unhighlightTag = _ref.unhighlightTag; var unhighlightTag = _ref$unhighlightTag === undefined ? 'span' : _ref$unhighlightTag; var _ref$unhighlightClassName = _ref.unhighlightClassName; var unhighlightClassName = _ref$unhighlightClassName === undefined ? '' : _ref$unhighlightClassName; var unhighlightStyle = _ref.unhighlightStyle; var rest = _objectWithoutProperties(_ref, ['activeClassName', 'activeIndex', 'activeStyle', 'autoEscape', 'caseSensitive', 'className', 'findChunks', 'highlightClassName', 'highlightStyle', 'highlightTag', 'sanitize', 'searchWords', 'textToHighlight', 'unhighlightTag', 'unhighlightClassName', 'unhighlightStyle']); var chunks = (0, _highlightWordsCore.findAll)({ autoEscape: autoEscape, caseSensitive: caseSensitive, findChunks: findChunks, sanitize: sanitize, searchWords: searchWords, textToHighlight: textToHighlight }); var HighlightTag = highlightTag; var highlightIndex = -1; var highlightClassNames = ''; var highlightStyles = undefined; var lowercaseProps = function lowercaseProps(object) { var mapped = {}; for (var key in object) { mapped[key.toLowerCase()] = object[key]; } return mapped; }; var memoizedLowercaseProps = (0, _memoizeOne2['default'])(lowercaseProps); return (0, _react.createElement)('span', _extends({ className: className }, rest, { children: chunks.map(function (chunk, index) { var text = textToHighlight.substr(chunk.start, chunk.end - chunk.start); if (chunk.highlight) { highlightIndex++; var highlightClass = undefined; if (typeof highlightClassName === 'object') { if (!caseSensitive) { highlightClassName = memoizedLowercaseProps(highlightClassName); highlightClass = highlightClassName[text.toLowerCase()]; } else { highlightClass = highlightClassName[text]; } } else { highlightClass = highlightClassName; } var isActive = highlightIndex === +activeIndex; highlightClassNames = highlightClass + ' ' + (isActive ? activeClassName : ''); highlightStyles = isActive === true && activeStyle != null ? Object.assign({}, highlightStyle, activeStyle) : highlightStyle; var props = { children: text, className: highlightClassNames, key: index, style: highlightStyles }; // Don't attach arbitrary props to DOM elements; this triggers React DEV warnings (https://fb.me/react-unknown-prop) // Only pass through the highlightIndex attribute for custom components. if (typeof HighlightTag !== 'string') { props.highlightIndex = highlightIndex; } return (0, _react.createElement)(HighlightTag, props); } else { return (0, _react.createElement)(unhighlightTag, { children: text, className: unhighlightClassName, key: index, style: unhighlightStyle }); } }) })); } module.exports = exports['default']; /***/ }), /* 3 */ /***/ (function(module, exports) { module.exports = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { module.exports = __webpack_require__(1); /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _utils = __webpack_require__(2); Object.defineProperty(exports, 'combineChunks', { enumerable: true, get: function get() { return _utils.combineChunks; } }); Object.defineProperty(exports, 'fillInChunks', { enumerable: true, get: function get() { return _utils.fillInChunks; } }); Object.defineProperty(exports, 'findAll', { enumerable: true, get: function get() { return _utils.findAll; } }); Object.defineProperty(exports, 'findChunks', { enumerable: true, get: function get() { return _utils.findChunks; } }); /***/ }), /* 2 */ /***/ (function(module, exports) { 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); /** * Creates an array of chunk objects representing both higlightable and non highlightable pieces of text that match each search word. * @return Array of "chunks" (where a Chunk is { start:number, end:number, highlight:boolean }) */ var findAll = exports.findAll = function findAll(_ref) { var autoEscape = _ref.autoEscape, _ref$caseSensitive = _ref.caseSensitive, caseSensitive = _ref$caseSensitive === undefined ? false : _ref$caseSensitive, _ref$findChunks = _ref.findChunks, findChunks = _ref$findChunks === undefined ? defaultFindChunks : _ref$findChunks, sanitize = _ref.sanitize, searchWords = _ref.searchWords, textToHighlight = _ref.textToHighlight; return fillInChunks({ chunksToHighlight: combineChunks({ chunks: findChunks({ autoEscape: autoEscape, caseSensitive: caseSensitive, sanitize: sanitize, searchWords: searchWords, textToHighlight: textToHighlight }) }), totalLength: textToHighlight ? textToHighlight.length : 0 }); }; /** * Takes an array of {start:number, end:number} objects and combines chunks that overlap into single chunks. * @return {start:number, end:number}[] */ var combineChunks = exports.combineChunks = function combineChunks(_ref2) { var chunks = _ref2.chunks; chunks = chunks.sort(function (first, second) { return first.start - second.start; }).reduce(function (processedChunks, nextChunk) { // First chunk just goes straight in the array... if (processedChunks.length === 0) { return [nextChunk]; } else { // ... subsequent chunks get checked to see if they overlap... var prevChunk = processedChunks.pop(); if (nextChunk.start <= prevChunk.end) { // It may be the case that prevChunk completely surrounds nextChunk, so take the // largest of the end indeces. var endIndex = Math.max(prevChunk.end, nextChunk.end); processedChunks.push({ start: prevChunk.start, end: endIndex }); } else { processedChunks.push(prevChunk, nextChunk); } return processedChunks; } }, []); return chunks; }; /** * Examine text for any matches. * If we find matches, add them to the returned array as a "chunk" object ({start:number, end:number}). * @return {start:number, end:number}[] */ var defaultFindChunks = function defaultFindChunks(_ref3) { var autoEscape = _ref3.autoEscape, caseSensitive = _ref3.caseSensitive, _ref3$sanitize = _ref3.sanitize, sanitize = _ref3$sanitize === undefined ? identity : _ref3$sanitize, searchWords = _ref3.searchWords, textToHighlight = _ref3.textToHighlight; textToHighlight = sanitize(textToHighlight); return searchWords.filter(function (searchWord) { return searchWord; }) // Remove empty words .reduce(function (chunks, searchWord) { searchWord = sanitize(searchWord); if (autoEscape) { searchWord = escapeRegExpFn(searchWord); } var regex = new RegExp(searchWord, caseSensitive ? 'g' : 'gi'); var match = void 0; while (match = regex.exec(textToHighlight)) { var start = match.index; var end = regex.lastIndex; // We do not return zero-length matches if (end > start) { chunks.push({ start: start, end: end }); } // Prevent browsers like Firefox from getting stuck in an infinite loop // See http://www.regexguru.com/2008/04/watch-out-for-zero-length-matches/ if (match.index == regex.lastIndex) { regex.lastIndex++; } } return chunks; }, []); }; // Allow the findChunks to be overridden in findAll, // but for backwards compatibility we export as the old name exports.findChunks = defaultFindChunks; /** * Given a set of chunks to highlight, create an additional set of chunks * to represent the bits of text between the highlighted text. * @param chunksToHighlight {start:number, end:number}[] * @param totalLength number * @return {start:number, end:number, highlight:boolean}[] */ var fillInChunks = exports.fillInChunks = function fillInChunks(_ref4) { var chunksToHighlight = _ref4.chunksToHighlight, totalLength = _ref4.totalLength; var allChunks = []; var append = function append(start, end, highlight) { if (end - start > 0) { allChunks.push({ start: start, end: end, highlight: highlight }); } }; if (chunksToHighlight.length === 0) { append(0, totalLength, false); } else { var lastIndex = 0; chunksToHighlight.forEach(function (chunk) { append(lastIndex, chunk.start, false); append(chunk.start, chunk.end, true); lastIndex = chunk.end; }); append(lastIndex, totalLength, false); } return allChunks; }; function identity(value) { return value; } function escapeRegExpFn(str) { return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'); } /***/ }) /******/ ]); //# sourceMappingURL=index.js.map /***/ }), /* 4 */ /***/ (function(module, exports) { module.exports = require("react"); /***/ }), /* 5 */ /***/ (function(module, exports) { 'use strict'; var simpleIsEqual = function simpleIsEqual(a, b) { return a === b; }; function index (resultFn) { var isEqual = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : simpleIsEqual; var lastThis = void 0; var lastArgs = []; var lastResult = void 0; var calledOnce = false; var isNewArgEqualToLast = function isNewArgEqualToLast(newArg, index) { return isEqual(newArg, lastArgs[index]); }; var result = function result() { for (var _len = arguments.length, newArgs = Array(_len), _key = 0; _key < _len; _key++) { newArgs[_key] = arguments[_key]; } if (calledOnce && lastThis === this && newArgs.length === lastArgs.length && newArgs.every(isNewArgEqualToLast)) { return lastResult; } calledOnce = true; lastThis = this; lastArgs = newArgs; lastResult = resultFn.apply(this, newArgs); return lastResult; }; return result; } module.exports = index; /***/ }) /******/ ]); //# sourceMappingURL=main.js.map