UNPKG

react-type-snob

Version:

Encourages good typographic details in your React app

135 lines (96 loc) 12.3 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _templateObject = _taggedTemplateLiteral(['\n [React Type Snob] Problems detected in text content of `', '`', ';\n ', ''], ['\n [React Type Snob] Problems detected in text content of \\`', '\\`', ';\n ', '']); exports.default = typeSnob; var _docChomp = require('doc-chomp'); var _docChomp2 = _interopRequireDefault(_docChomp); var _getDisplayName = require('./get-display-name'); var _getDisplayName2 = _interopRequireDefault(_getDisplayName); var _consoleReporter = require('./console-reporter'); var _consoleReporter2 = _interopRequireDefault(_consoleReporter); var _verifyReact = require('./verify-react'); var _verifyReact2 = _interopRequireDefault(_verifyReact); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); } var SNOBBY_TESTS = [{ name: 'ugly double quotes', regexp: /"/g, suggestion: '`“` or `”`' }, { name: 'ugly single quotes', regexp: /'/g, suggestion: '`‘` or `’`' }, { name: 'full-stops as ellipses', regexp: /\.{2,}/g, suggestion: '`…`' }, { name: 'space preceding ellipses', regexp: /\s(?:\.{2,}|…)/g }]; var CONTEXT_LENGTH = 20; function typeSnob(React) { var reporter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _consoleReporter2.default; (0, _verifyReact2.default)(React); // keep original `createElement` method, as we intend to proxy it! var createElement = React.createElement; React.createElement = function typeSnobCreateElement(type, rawProps) { var props = rawProps || {}; var children = void 0; for (var _len = arguments.length, rawChildren = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { rawChildren[_key - 2] = arguments[_key]; } if (rawChildren.length === 0) { children = props.children || []; } else { children = rawChildren; } // proxy out to the real `createElement` early so we don't try to test any invalid states! var reactElement = createElement.call.apply(createElement, [this, type, rawProps].concat(rawChildren)); var textContent = ''; React.Children.forEach(children, function (child) { textContent += React.isValidElement(child) ? '[React Element]' : child; }); var errors = SNOBBY_TESTS.map(function (test) { var contexts = []; textContent.replace(test.regexp, function (match) { for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { args[_key2 - 1] = arguments[_key2]; } var fullText = args.pop(); var startOffset = args.pop(); var endOffset = startOffset + match.length; var contextStartOffset = Math.max(startOffset - CONTEXT_LENGTH, 0); var contextEndOffset = Math.min(endOffset + CONTEXT_LENGTH, fullText.length); contexts.push(fullText.slice(contextStartOffset, contextEndOffset).replace(/\n/g, ' ')); // *do not* replace, as we may need to do further processing return match; }); if (contexts.length === 0) { return; } return Object.assign({ contexts: contexts }, test); }).filter(function (returnedThing) { return returnedThing; }); if (errors.length > 0) { reporter((0, _docChomp2.default)(_templateObject, (0, _getDisplayName2.default)(type, rawProps), reactElement._owner && reactElement._owner.getName ? '. Please check the render method of `' + reactElement._owner.getName() + '`' : '', errors.map(function (_ref) { var name = _ref.name, suggestion = _ref.suggestion, contexts = _ref.contexts; var report = '* Found ' + name + ';'; contexts.forEach(function (context) { return report += '\n * `' + context + '`'; }); if (suggestion) { report += '\n Suggested replacements: ' + suggestion; } return report; }).join('\n\n'))); } return reactElement; }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC5qcyJdLCJuYW1lcyI6WyJ0eXBlU25vYiIsIlNOT0JCWV9URVNUUyIsIm5hbWUiLCJyZWdleHAiLCJzdWdnZXN0aW9uIiwiQ09OVEVYVF9MRU5HVEgiLCJSZWFjdCIsInJlcG9ydGVyIiwiY3JlYXRlRWxlbWVudCIsInR5cGVTbm9iQ3JlYXRlRWxlbWVudCIsInR5cGUiLCJyYXdQcm9wcyIsInByb3BzIiwiY2hpbGRyZW4iLCJyYXdDaGlsZHJlbiIsImxlbmd0aCIsInJlYWN0RWxlbWVudCIsImNhbGwiLCJ0ZXh0Q29udGVudCIsIkNoaWxkcmVuIiwiZm9yRWFjaCIsImNoaWxkIiwiaXNWYWxpZEVsZW1lbnQiLCJlcnJvcnMiLCJtYXAiLCJ0ZXN0IiwiY29udGV4dHMiLCJyZXBsYWNlIiwibWF0Y2giLCJhcmdzIiwiZnVsbFRleHQiLCJwb3AiLCJzdGFydE9mZnNldCIsImVuZE9mZnNldCIsImNvbnRleHRTdGFydE9mZnNldCIsIk1hdGgiLCJtYXgiLCJjb250ZXh0RW5kT2Zmc2V0IiwibWluIiwicHVzaCIsInNsaWNlIiwiT2JqZWN0IiwiYXNzaWduIiwiZmlsdGVyIiwicmV0dXJuZWRUaGluZyIsIl9vd25lciIsImdldE5hbWUiLCJyZXBvcnQiLCJjb250ZXh0Iiwiam9pbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7a0JBOEJ3QkEsUTs7QUE5QnhCOzs7O0FBRUE7Ozs7QUFDQTs7OztBQUNBOzs7Ozs7OztBQUVBLElBQU1DLGVBQWUsQ0FDbkI7QUFDRUMsUUFBTSxvQkFEUjtBQUVFQyxVQUFRLElBRlY7QUFHRUMsY0FBWTtBQUhkLENBRG1CLEVBTW5CO0FBQ0VGLFFBQU0sb0JBRFI7QUFFRUMsVUFBUSxJQUZWO0FBR0VDLGNBQVk7QUFIZCxDQU5tQixFQVduQjtBQUNFRixRQUFNLHdCQURSO0FBRUVDLFVBQVEsU0FGVjtBQUdFQyxjQUFZO0FBSGQsQ0FYbUIsRUFnQm5CO0FBQ0VGLFFBQU0sMEJBRFI7QUFFRUMsVUFBUTtBQUZWLENB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QUQ7QUFBQSxpQkFBYUQsdUJBQXNCQyxPQUF0QixNQUFiO0FBQUEsU0FBakI7O0FBRUEsWUFBSTVDLFVBQUosRUFBZ0I7QUFDZDJDLHFEQUF5QzNDLFVBQXpDO0FBQ0Q7O0FBRUQsZUFBTzJDLE1BQVA7QUFDRCxPQVZDLEVBVUNFLElBVkQsQ0FVTSxNQVZOLENBRko7QUFlRDs7QUFFRCxXQUFPakMsWUFBUDtBQUNELEdBakVEO0FBa0VEIiwiZmlsZSI6ImluZGV4LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IERvY0Nob21wIGZyb20gJ2RvYy1jaG9tcCc7XG5cbmltcG9ydCBnZXREaXNwbGF5TmFtZSBmcm9tICcuL2dldC1kaXNwbGF5LW5hbWUnO1xuaW1wb3J0IGNvbnNvbGVSZXBvcnRlciBmcm9tICcuL2NvbnNvbGUtcmVwb3J0ZXInO1xuaW1wb3J0IHZlcmlmeVJlYWN0IGZyb20gJy4vdmVyaWZ5LXJlYWN0JztcblxuY29uc3QgU05PQkJZX1RFU1RTID0gW1xuICB7XG4gICAgbmFtZTogJ3VnbHkgZG91YmxlIHF1b3RlcycsXG4gICAgcmVnZXhwOiAvXCIvZyxcbiAgICBzdWdnZXN0aW9uOiAnYOKAnGAgb3IgYOKAnWAnXG4gIH0sXG4gIHtcbiAgICBuYW1lOiAndWdseSBzaW5nbGUgcXVvdGVzJyxcbiAgICByZWdleHA6IC8nL2csXG4gICAgc3VnZ2VzdGlvbjogJ2DigJhgIG9yIGDigJlgJ1xuICB9LFxuICB7XG4gICAgbmFtZTogJ2Z1bGwtc3RvcHMgYXMgZWxsaXBzZXMnLFxuICAgIHJlZ2V4cDogL1xcLnsyLH0vZyxcbiAgICBzdWdnZXN0aW9uOiAnYOKApmAnXG4gIH0sXG4gIHtcbiAgICBuYW1lOiAnc3BhY2UgcHJlY2VkaW5nIGVsbGlwc2VzJyxcbiAgICByZWdleHA6IC9cXHMoPzpcXC57Mix9fOKApikvZ1xuICB9XG5dO1xuXG5jb25zdCBDT05URVhUX0xFTkdUSCA9IDIwO1xuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiB0eXBlU25vYihSZWFjdCwgcmVwb3J0ZXIgPSBjb25zb2xlUmVwb3J0ZXIpIHtcbiAgdmVyaWZ5UmVhY3QoUmVhY3QpO1xuXG4gIC8vIGtlZXAgb3JpZ2luYWwgYGNyZWF0ZUVsZW1lbnRgIG1ldGhvZCwgYXMgd2UgaW50ZW5kIHRvIHByb3h5IGl0IVxuICBjb25zdCBjcmVhdGVFbGVtZW50ID0gUmVhY3QuY3JlYXRlRWxlbWVudDtcblxuICBSZWFjdC5jcmVhdGVFbGVtZW50ID0gZnVuY3Rpb24gdHlwZVNub2JDcmVhdGVFbGVtZW50KHR5cGUsIHJhd1Byb3BzLCAuLi5yYXdDaGlsZHJlbikge1xuICAgIGNvbnN0IHByb3BzID0gcmF3UHJvcHMgfHwge307XG4gICAgbGV0IGNoaWxkcmVuO1xuXG4gICAgaWYgKHJhd0NoaWxkcmVuLmxlbmd0aCA9PT0gMCkge1xuICAgICAgY2hpbGRyZW4gPSBwcm9wcy5jaGlsZHJlbiB8fCBbXTtcbiAgICB9IGVsc2Uge1xuICAgICAgY2hpbGRyZW4gPSByYXdDaGlsZHJlbjtcbiAgICB9XG5cbiAgICAvLyBwcm94eSBvdXQgdG8gdGhlIHJlYWwgYGNyZWF0ZUVsZW1lbnRgIGVhcmx5IHNvIHdlIGRvbid0IHRyeSB0byB0ZXN0IGFueSBpbnZhbGlkIHN0YXRlcyFcbiAgICBjb25zdCByZWFjdEVsZW1lbnQgPSBjcmVhdGVFbGVtZW50LmNhbGwodGhpcywgdHlwZSwgcmF3UHJvcHMsIC4uLnJhd0NoaWxkcmVuKTtcblxuICAgIGxldCB0ZXh0Q29udGVudCA9ICcnO1xuXG4gICAgUmVhY3QuQ2hpbGRyZW4uZm9yRWFjaChjaGlsZHJlbiwgKGNoaWxkKSA9PiB7XG4gICAgICB0ZXh0Q29udGVudCArPSBSZWFjdC5pc1ZhbGlkRWxlbWVudChjaGlsZCkgPyAnW1JlYWN0IEVsZW1lbnRdJyA6IGNoaWxkO1xuICAgIH0pO1xuXG4gICAgY29uc3QgZXJyb3JzID0gU05PQkJZX1RFU1RTXG4gICAgICAubWFwKCh0ZXN0KSA9PiB7XG4gICAgICAgIGNvbnN0IGNvbnRleHRzID0gW107XG5cbiAgICAgICAgdGV4dENvbnRlbnQucmVwbGFjZSh0ZXN0LnJlZ2V4cCwgKG1hdGNoLCAuLi5hcmdzKSA9PiB7XG4gICAgICAgICAgY29uc3QgZnVsbFRleHQgPSBhcmdzLnBvcCgpO1xuXG4gICAgICAgICAgY29uc3Qgc3RhcnRPZmZzZXQgPSBhcmdzLnBvcCgpO1xuICAgICAgICAgIGNvbnN0IGVuZE9mZnNldCA9IHN0YXJ0T2Zmc2V0ICsgbWF0Y2gubGVuZ3RoO1xuXG4gICAgICAgICAgY29uc3QgY29udGV4dFN0YXJ0T2Zmc2V0ID0gTWF0aC5tYXgoc3RhcnRPZmZzZXQgLSBDT05URVhUX0xFTkdUSCwgMCk7XG4gICAgICAgICAgY29uc3QgY29udGV4dEVuZE9mZnNldCA9IE1hdGgubWluKGVuZE9mZnNldCArIENPTlRFWFRfTEVOR1RILCBmdWxsVGV4dC5sZW5ndGgpO1xuXG4gICAgICAgICAgY29udGV4dHMucHVzaChmdWxsVGV4dC5zbGljZShjb250ZXh0U3RhcnRPZmZzZXQsIGNvbnRleHRFbmRPZmZzZXQpLnJlcGxhY2UoL1xcbi9nLCAnICcpKTtcblxuICAgICAgICAgIC8vICpkbyBub3QqIHJlcGxhY2UsIGFzIHdlIG1heSBuZWVkIHRvIGRvIGZ1cnRoZXIgcHJvY2Vzc2luZ1xuICAgICAgICAgIHJldHVybiBtYXRjaDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKGNvbnRleHRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHsgY29udGV4dHMgfSwgdGVzdCk7XG4gICAgICB9KVxuICAgICAgLmZpbHRlcigocmV0dXJuZWRUaGluZykgPT4gcmV0dXJuZWRUaGluZyk7XG5cbiAgICBpZiAoZXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgIHJlcG9ydGVyKERvY0Nob21wYFxuICAgICAgICBbUmVhY3QgVHlwZSBTbm9iXSBQcm9ibGVtcyBkZXRlY3RlZCBpbiB0ZXh0IGNvbnRlbnQgb2YgXFxgJHtnZXREaXNwbGF5TmFtZSh0eXBlLCByYXdQcm9wcyl9XFxgJHsocmVhY3RFbGVtZW50Ll9vd25lciAmJiByZWFjdEVsZW1lbnQuX293bmVyLmdldE5hbWUpID8gYC4gUGxlYXNlIGNoZWNrIHRoZSByZW5kZXIgbWV0aG9kIG9mIFxcYCR7cmVhY3RFbGVtZW50Ll9vd25lci5nZXROYW1lKCl9XFxgYCA6ICcnfTtcbiAgICAgICAgJHtlcnJvcnMubWFwKCh7IG5hbWUsIHN1Z2dlc3Rpb24sIGNvbnRleHRzIH0pID0+IHtcbiAgICAgICAgICBsZXQgcmVwb3J0ID0gYCogRm91bmQgJHtuYW1lfTtgO1xuXG4gICAgICAgICAgY29udGV4dHMuZm9yRWFjaCgoY29udGV4dCkgPT4gcmVwb3J0ICs9IGBcXG4gICAqIFxcYCR7Y29udGV4dH1cXGBgKTtcblxuICAgICAgICAgIGlmIChzdWdnZXN0aW9uKSB7XG4gICAgICAgICAgICByZXBvcnQgKz0gYFxcbiAgU3VnZ2VzdGVkIHJlcGxhY2VtZW50czogJHtzdWdnZXN0aW9ufWA7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIHJlcG9ydDtcbiAgICAgICAgfSkuam9pbignXFxuXFxuJylcbiAgICAgICAgfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlYWN0RWxlbWVudDtcbiAgfTtcbn1cbiJdfQ==