react-type-snob
Version:
Encourages good typographic details in your React app
135 lines (96 loc) • 12.3 kB
JavaScript
;
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==