UNPKG

react-transform-words

Version:

A React component that transforms individual words in a block of text with css classes and actions.

254 lines (215 loc) 8 kB
'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var React = require('react'); var React__default = _interopDefault(React); var PropTypes = _interopDefault(require('prop-types')); function styleInject(css, ref) { if ( ref === void 0 ) ref = {}; var insertAt = ref.insertAt; if (!css || typeof document === 'undefined') { return; } var head = document.head || document.getElementsByTagName('head')[0]; var style = document.createElement('style'); style.type = 'text/css'; if (insertAt === 'top') { if (head.firstChild) { head.insertBefore(style, head.firstChild); } else { head.appendChild(style); } } else { head.appendChild(style); } if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } } var css = "\n.Transformer_highlighter__ssJFc {\n background-color: #D4FF00;\n}\n \n.Transformer_error__3Hggt {\n color: red;\n font-weight: bold;\n}\n "; var styles = { "highlighter": "Transformer_highlighter__ssJFc", "error": "Transformer_error__3Hggt" }; styleInject(css); var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 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; }; var inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; var toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; var buildMatches = function buildMatches(words, text) { var allMatches = []; // for each word to transform, find all instances in the provided displayText words.filter(function (hw) { return hw !== ''; }).forEach(function (w) { // if there was no start and end provided, search for th word instead if (w.start === undefined && w.end === undefined) { var searchWord = w.word; var modifiers = w.caseSensitive ? 'g' : 'gi'; // if sent in as string(default), escape for regex if (w.format !== 'regex') { searchWord = searchWord.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } try { var regex = new RegExp(searchWord, modifiers); var match = []; // eslint-disable-next-line no-cond-assign while (match = regex.exec(text)) { if (match.index === regex.lastIndex) { regex.lastIndex++; } var matchObj = { start: match.index, end: regex.lastIndex }; allMatches.push(Object.assign({}, w, matchObj)); } } catch (err) { return; } } else { allMatches.push(w); } }); return allMatches; }; var Transformer = function (_Component) { inherits(Transformer, _Component); function Transformer() { var _ref; var _temp, _this, _ret; classCallCheck(this, Transformer); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = possibleConstructorReturn(this, (_ref = Transformer.__proto__ || Object.getPrototypeOf(Transformer)).call.apply(_ref, [this].concat(args))), _this), _this.buildElement = function (text, key) { var match = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var elm = React__default.createElement( 'span', { key: 'nomatch-' + key }, text ); if (match) { if (match.action === 'click' && !match.actionCallback) { match.actionCallback = null; } elm = React__default.createElement( 'span', _extends({ key: 'match' + key, className: match.className !== undefined ? match.className : _this.props.defaultClass, onClick: match.action === 'click' ? match.actionCallback : null, onDoubleClick: match.action === 'doubleclick' ? match.actionCallback : null, onMouseOver: match.action === 'mouseover' ? match.actionCallback : null }, match.extraProps), match.action === 'change' ? match.replaceText : text ); } return elm; }, _this.renderWordTransforms = function () { var txt = _this.props.displayText; var matchList = buildMatches(_this.props.matchWords, txt); var prevEnd = 0; var elements = matchList.sort(function (m1, m2) { return m1.start - m2.start; }).map(function (m, idx) { // record previous end spot var workingEnd = prevEnd; // if this part of the text has already been handled if (m.start < prevEnd) { return null; } prevEnd = m.end; // if the start of the found word is the next index if (workingEnd === m.start) { return _this.buildElement(txt.substring(workingEnd, m.end), idx, m); } // current bit of text isn't transformed, // so wrap a span around text up to the current transform word // from workingEnd to m.start var nomatch = _this.buildElement(txt.substring(workingEnd, m.start), idx); var transformed = _this.buildElement(txt.substring(m.start, m.end), idx, m); return [nomatch, transformed]; }); // check to see if prevEnd is the end of the total length if (prevEnd < txt.length) { elements = [].concat(toConsumableArray(elements), [txt.substring(prevEnd, txt.length)]); } return elements; }, _temp), possibleConstructorReturn(_this, _ret); } createClass(Transformer, [{ key: 'render', value: function render() { return React__default.createElement( React__default.Fragment, null, this.props.matchWords.length > 0 ? this.renderWordTransforms() : this.props.displayText ); } }]); return Transformer; }(React.Component); Transformer.propTypes = { matchWords: PropTypes.array, displayText: PropTypes.string.isRequired, defaultClass: PropTypes.string }; Transformer.defaultProps = { defaultClass: styles.highlighter, matchWords: [] }; module.exports = Transformer; //# sourceMappingURL=index.js.map