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
JavaScript
;
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