/
githubmirror
/
babel
Обзор
Документация
Войти
/
githubmirror
/
babel
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/babel-code-frame/src/highlight.ts
159 строк
4 KB
Huáng Jùnliàng
chore: add custom no-extraneous-dependencies rule (#17971)
06 май 2026, 15:30
Не верифицирован
06 май 2026, 15:30
7f2dda1
Код
Авторство
О чём код?
import type { Token as JSToken, JSXToken } from "js-tokens"; import jsTokens from "js-tokens"; import * as charCodes from "charcodes"; import { isStrictReservedWord, isKeyword, } from "@babel/helper-validator-identifier"; import { defs, type InternalTokenType } from "./defs.ts"; /** * Names that are always allowed as identifiers, but also appear as keywords * within certain syntactic productions. * * https://tc39.es/ecma262/#sec-keywords-and-reserved-words * * `target` has been omitted since it is very likely going to be a false * positive. */ const sometimesKeywords = new Set(["as", "async", "from", "get", "of", "set"]); type Token = { type: InternalTokenType | "uncolored"; value: string; }; /** * RegExp to test for newlines in terminal. */ const NEWLINE = /\r\n|[\n\r\u2028\u2029]/; /** * RegExp to test for the three types of brackets. */ const BRACKET = /^[()[\]{}]$/; /** * Get the type of token, specifying punctuator type. */ const getTokenType = function ( token: JSToken | JSXToken, ): InternalTokenType | "uncolored" { 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) { // ASCII characters if ( firstChar >= charCodes.uppercaseA && firstChar <= charCodes.uppercaseZ ) { 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"; } }; /** * Turn a string of JS into an array of objects. */ function* tokenize(text: string): Generator<Token> { 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, }; } } } export function highlight(text: string) { if (text === "") return ""; let highlighted = ""; for (const { type, value } of tokenize(text)) { if (type in defs) { highlighted += value .split(NEWLINE) .map(str => defs[type as InternalTokenType](str)) .join("\n"); } else { highlighted += value; } } return highlighted; }