UNPKG

@babel/code-frame

Version:

Generate errors that contain a code frame that point to source locations.

154 lines (149 loc) 4.07 kB
import { _codeFrameColumns } from './common-shared.js'; import { styleText } from 'node:util'; import jsTokens from 'js-tokens'; import { isKeyword, isStrictReservedWord } from '@babel/helper-validator-identifier'; function isColorSupported() { return styleText("red", "-") !== "-"; } function createFormatter(format) { return input => styleText(format, String(input ?? ""), { validateStream: false }); } const defs = { keyword: createFormatter("cyan"), capitalized: createFormatter("yellow"), jsxIdentifier: createFormatter("yellow"), punctuator: createFormatter("yellow"), number: createFormatter("magenta"), string: createFormatter("green"), regex: createFormatter("magenta"), comment: createFormatter("gray"), invalid: createFormatter(["white", "bgRed", "bold"]), gutter: createFormatter("gray"), marker: createFormatter(["red", "bold"]), message: createFormatter(["red", "bold"]), reset: createFormatter("reset") }; const sometimesKeywords = new Set(["as", "async", "from", "get", "of", "set"]); const NEWLINE = /\r\n|[\n\r\u2028\u2029]/; const BRACKET = /^[()[\]{}]$/; const getTokenType = function (token) { if (token.type === "IdentifierName") { const tokenValue = token.value; if (isKeyword(tokenValue) || isStrictReservedWord(tokenValue, true) || sometimesKeywords.has(tokenValue)) { return "keyword"; } const firstChar = tokenValue.charCodeAt(0); if (firstChar < 128) { if (firstChar >= 65 && firstChar <= 90) { return "capitalized"; } } else { const firstChar = String.fromCodePoint(tokenValue.codePointAt(0)); if (firstChar !== firstChar.toLowerCase()) { return "capitalized"; } } } if (token.type === "Punctuator" && BRACKET.test(token.value)) { return "uncolored"; } if (token.type === "Invalid" && token.value === "@") { return "punctuator"; } switch (token.type) { case "NumericLiteral": return "number"; case "StringLiteral": case "JSXString": case "NoSubstitutionTemplate": return "string"; case "RegularExpressionLiteral": return "regex"; case "Punctuator": case "JSXPunctuator": return "punctuator"; case "MultiLineComment": case "SingleLineComment": return "comment"; case "Invalid": case "JSXInvalid": return "invalid"; case "JSXIdentifier": return "jsxIdentifier"; default: return "uncolored"; } }; function* tokenize(text) { for (const token of jsTokens(text, { jsx: true })) { switch (token.type) { case "TemplateHead": yield { type: "string", value: token.value.slice(0, -2) }; yield { type: "punctuator", value: "${" }; break; case "TemplateMiddle": yield { type: "punctuator", value: "}" }; yield { type: "string", value: token.value.slice(1, -2) }; yield { type: "punctuator", value: "${" }; break; case "TemplateTail": yield { type: "punctuator", value: "}" }; yield { type: "string", value: token.value.slice(1) }; break; default: yield { type: getTokenType(token), value: token.value }; } } } function highlight(text) { if (text === "") return ""; let highlighted = ""; for (const { type, value } of tokenize(text)) { if (type in defs) { highlighted += value.split(NEWLINE).map(str => defs[type](str)).join("\n"); } else { highlighted += value; } } return highlighted; } function codeFrameColumns(rawLines, loc, opts = {}) { const shouldHighlight = opts.forceColor || isColorSupported() && opts.highlightCode; return _codeFrameColumns(rawLines, loc, opts, shouldHighlight ? { defs, highlight } : undefined); } export { codeFrameColumns, highlight }; //# sourceMappingURL=index.js.map