@tanstack/highlight
Version:
Tiny class-based syntax highlighting for documentation.
31 lines (30 loc) • 1.71 kB
JavaScript
import { simpleLanguage, wordCategories } from './simple-language.js';
export { simpleLanguage as simpleWordLanguage, simpleLanguage as nativeCompiledWordLanguage } from './simple-language.js';
export function canCombineWords(options) {
const categories = wordCategories(options).filter((entry) => Boolean(entry[1]));
const terms = categories.flatMap(([, words]) => words.split(/\s+/));
const characters = options.wordCharacters || '\\w$';
const wholeWord = new RegExp(`^[${characters}]+$`, options.insensitive ? 'i' : '');
return categories.length > 1 && terms.every(word => word.length && wholeWord.test(word) && (!options.insensitive || /^[\x00-\x7f]+$/.test(word)));
}
export function compiledWordLanguage(options) {
return simpleLanguage(options, options.insensitive ? undefined : mapWordPatterns, true);
}
function mapWordPatterns(options, flags, wordCharacters) {
// These definitions satisfy canCombineWords, each match is a complete word.
const known = new Set();
const classes = new Map();
for (const [className, words] of wordCategories(options)) {
if (words)
for (const word of words.split(/\s+/)) {
if (known.has(word))
continue;
known.add(word);
if (className !== 'keyword')
classes.set(word, className);
}
}
// The regex admits only known terms, missing class entries are keywords.
const regex = new RegExp(`(?<![${wordCharacters}])(?:${[...known].map((word) => word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|')})(?![${wordCharacters}])`, flags);
return [[regex, (match) => classes.get(match[0]) || 'keyword']];
}