"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _lodash = _interopRequireDefault(require("lodash")); var _eslint = require("eslint"); var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } var zeroBasedLineIndexAdjust = -1; var likelyNestedJSDocIndentSpace = 1; var preTagSpaceLength = 1; var hasCaptionRegex = /^\s*.*?<\/caption>/; var escapeStringRegexp = function escapeStringRegexp(str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }; var countChars = function countChars(str, ch) { return (str.match(new RegExp(escapeStringRegexp(ch), 'g')) || []).length; }; var _default = (0, _iterateJsdoc.default)(function (_ref) { var jsdoc = _ref.jsdoc, report = _ref.report, utils = _ref.utils; var exampleCodeRegex = utils.getExampleCodeRegex(); var rejectExampleCodeRegex = utils.getRejectExampleCodeRegex(); var noDefaultExampleRules = utils.hasNoDefaultExampleRules(); var eslintrcForExamples = utils.useEslintrcForExamples(); var filename = utils.getMatchingFileName(); var baseConfig = utils.getBaseConfig(); var configFile = utils.getConfigFile(); var allowInlineConfig = utils.allowInlineConfig(); var reportUnusedDisableDirectives = utils.reportUnusedDisableDirectives(); // Make this configurable? var rulePaths = []; var rules = noDefaultExampleRules ? undefined : { // "always" newline rule at end unlikely in sample code 'eol-last': 0, // Wouldn't generally expect example paths to resolve relative to JS file 'import/no-unresolved': 0, // Snippets likely too short to always include import/export info 'import/unambiguous': 0, // Unlikely to have inadvertent debugging within examples 'no-console': 0, // Many variables in examples will be `undefined` 'no-undef': 0, // Common to define variables for clarity without always using them 'no-unused-vars': 0, // See import/no-unresolved 'node/no-missing-import': 0, 'node/no-missing-require': 0, // Can generally look nicer to pad a little even if code imposes more stringency 'padded-blocks': 0 }; exampleCodeRegex = exampleCodeRegex && new RegExp(exampleCodeRegex, ''); rejectExampleCodeRegex = rejectExampleCodeRegex && new RegExp(rejectExampleCodeRegex, ''); _lodash.default.forEach(jsdoc.tags, function (tag) { if (tag.tag !== 'example') { return; } // If a space is present, we should ignore it var initialTag = tag.source.match(/^@example ?/); var initialTagLength = initialTag[0].length; var firstLinePrefixLength = preTagSpaceLength + initialTagLength; var source = tag.source.slice(initialTagLength); var match = source.match(hasCaptionRegex); if (utils.isCaptionRequired() && !match) { report('Caption is expected for examples.', null, tag); } // If we allow newlines in hasCaptionRegex, we should add to line count source = source.replace(hasCaptionRegex, ''); if (exampleCodeRegex && !exampleCodeRegex.test(source) || rejectExampleCodeRegex && rejectExampleCodeRegex.test(source)) { return; } var nonJSPrefacingLines = 0; var nonJSPrefacingCols = 0; if (exampleCodeRegex) { var idx = source.search(exampleCodeRegex); // Strip out anything preceding user regex match (can affect line numbering) var preMatchLines = 0; var preMatch = source.slice(0, idx); preMatchLines = countChars(preMatch, '\n'); nonJSPrefacingLines = preMatchLines; var colDelta = preMatchLines ? preMatch.slice(preMatch.lastIndexOf('\n') + 1).length - initialTagLength : preMatch.length; // Get rid of text preceding user regex match (even if it leaves valid JS, it // could cause us to count newlines twice) source = source.slice(idx); source = source.replace(exampleCodeRegex, function (n0, n1) { if (!n1) { return n0; } var index = n0.indexOf(n1); var nonJSPreface = n0.slice(0, index); var nonJSPrefaceLineCount = countChars(nonJSPreface, '\n'); nonJSPrefacingLines += nonJSPrefaceLineCount; // Ignore `preMatch` delta if newlines here if (nonJSPrefaceLineCount) { var charsInLastLine = nonJSPreface.slice(nonJSPreface.lastIndexOf('\n') + 1).length; nonJSPrefacingCols += charsInLastLine - initialTagLength; } else { nonJSPrefacingCols += colDelta + nonJSPreface.length; } return n1; }); } // Programmatic ESLint API: https://eslint.org/docs/developer-guide/nodejs-api var cli = new _eslint.CLIEngine({ allowInlineConfig, baseConfig, configFile, reportUnusedDisableDirectives, rulePaths, rules, useEslintrc: eslintrcForExamples }); var messages; if (filename) { var config = cli.getConfigForFile(filename); var linter = new _eslint.Linter(); var linterRules = _toConsumableArray(cli.getRules().entries()).reduce(function (obj, _ref2) { var _ref3 = _slicedToArray(_ref2, 2), key = _ref3[0], val = _ref3[1]; obj[key] = val; return obj; }, {}); linter.defineRules(linterRules); messages = linter.verify(source, config, { filename, reportUnusedDisableDirectives }); } else { var _cli$executeOnText = cli.executeOnText(source); var _cli$executeOnText$re = _slicedToArray(_cli$executeOnText.results, 1); messages = _cli$executeOnText$re[0].messages; } // NOTE: `tag.line` can be 0 if of form `/** @tag ... */` var codeStartLine = tag.line + nonJSPrefacingLines; var codeStartCol = likelyNestedJSDocIndentSpace; messages.forEach(function (_ref4) { var message = _ref4.message, line = _ref4.line, column = _ref4.column, severity = _ref4.severity, ruleId = _ref4.ruleId; var startLine = codeStartLine + line + zeroBasedLineIndexAdjust; var startCol = codeStartCol + ( // This might not work for line 0, but line 0 is unlikely for examples line <= 1 ? nonJSPrefacingCols + firstLinePrefixLength : preTagSpaceLength) + column; // Could perhaps make fixable report('@example ' + (severity === 2 ? 'error' : 'warning') + (ruleId ? ' (' + ruleId + ')' : '') + ': ' + message, null, { column: startCol, line: startLine }); }); }); }); exports.default = _default; module.exports = exports.default; //# sourceMappingURL=checkExamples.js.map