// import the necessary packages import octicons from '@primer/octicons'; import * as cheerio from 'cheerio'; // markdown-it-regexp type definitions are undefined // @ts-ignore import markdownItRegExp from 'markdown-it-regexp'; // regular expression to match the icon patterns const ICON_REGEXP = /:(fa[brs]|fa-brands|fa-solid|glyphicon|octicon|octiconlight|mi[forst]|bi)-([a-z0-9-]+)~?([a-z0-9-]+)?:/; // function to get the octicon icons function getOcticonIcon(iconName: string) { // Indexing octicons varies based on @types/primer__octicons version // @ts-ignore return octicons[iconName] ?? null; } // handler function for glyphicon icons const handleGlyphicon = (iconFontName: string) => ``; // handler function for octicon icons const handleOcticon = (iconFontName: string, iconClass?: string) => { const octiconIcon = getOcticonIcon(iconFontName); // ensure octicons are valid if (octiconIcon === null) { return ''; } return iconClass ? octiconIcon.toSVG({ class: iconClass }) : octiconIcon.toSVG(); }; // handler function for light octicon icons const handleOcticonLight = (iconFontName: string, iconClass?: string) => { const octiconIcon = getOcticonIcon(iconFontName); // ensure octicons are valid if (octiconIcon === null) { return ''; } const octiconIconHtml = iconClass ? octiconIcon.toSVG({ class: iconClass }) : octiconIcon.toSVG(); const $ = cheerio.load(octiconIconHtml); $('svg').attr('style', 'color: #fff'); return $.html(); }; // handler function for material icons const handleMaterialIcon = (iconFontType: string, iconFontName: string) => { let materialIconsClass = 'material-icons'; switch (iconFontType) { case 'mio': materialIconsClass += '-outlined'; break; case 'mir': materialIconsClass += '-round'; break; case 'mis': materialIconsClass += '-sharp'; break; case 'mit': materialIconsClass += '-two-tone'; break; default: // .material-icons generates 'Filled' style icons; hence, no suffix is needed for 'mif'. } // Use .align-middle by default to vertically-align the icon with its surrounding text (if any). // Also, replace dashes (-) with underscores (_) to format the icon name properly. return ``; }; // handler function for font awesome icons const handleFontAwesome = (iconFontType: string, iconFontName: string) => ``; // Handler function for Bootstrap Icons const handleBootstrapIcon = (iconFontName: string) => ``; // function to get the respective icon html based on the icon font type const getIconHtml = (match: string[]) => { const iconFontType = match[1]; const iconFontName = match[2]; const iconClass = match[3]; if (iconFontType === 'glyphicon') { return handleGlyphicon(iconFontName); } else if (iconFontType === 'octicon') { return handleOcticon(iconFontName, iconClass); } else if (iconFontType === 'octiconlight') { return handleOcticonLight(iconFontName, iconClass); } else if (iconFontType.startsWith('mi')) { return handleMaterialIcon(iconFontType, iconFontName); } else if (iconFontType === 'bi') { return handleBootstrapIcon(iconFontName); } return handleFontAwesome(iconFontType, iconFontName); }; // function to process the icon string and get the icon html const processIconString = (iconStr: string) => { let icon = iconStr; if (!iconStr.startsWith(':') && !iconStr.endsWith(':')) { icon = `:${iconStr}:`; } const match = icon.match(ICON_REGEXP); return match ? getIconHtml(match) : null; }; // create a markdown-it plugin to process the icon strings in the markdown /** * A Markdown-It plugin that replaces icon syntax matching `ICON_REGEXP` with corresponding HTML. * * This plugin uses a regular expression to detect icon patterns in Markdown content, * and transforms them into HTML using the `getIconHtml` function. */ const markdownItIconsPlugin = markdownItRegExp( ICON_REGEXP, (match: string[]) => getIconHtml(match), ); export { markdownItIconsPlugin, processIconString };