diff --git a/modules/markdown/code/CodeBlock.tsx b/modules/markdown/code/CodeBlock.tsx index 48f2e381..7047be65 100644 --- a/modules/markdown/code/CodeBlock.tsx +++ b/modules/markdown/code/CodeBlock.tsx @@ -1,4 +1,5 @@ import hljs from "highlight.js/lib/core" +import AnsiToHtml from "./ansiToHtml" import React, { useEffect, useState } from "react" import { CodeBlockContainer } from "../styles/CodeBlockContainer" import { getLanguageFromAlias } from "./getLanguageFromAlias" @@ -25,7 +26,9 @@ export function CodeBlock(props: CodeBlockProps) { return ( ) diff --git a/modules/markdown/code/ansiToHtml.ts b/modules/markdown/code/ansiToHtml.ts new file mode 100644 index 00000000..23500cc1 --- /dev/null +++ b/modules/markdown/code/ansiToHtml.ts @@ -0,0 +1,84 @@ +interface ColorMap { + [key: number]: string; +} + + export default function ansiToHtml(text: string): string { + const fgColorMap: ColorMap = { + 30: '#4f545c', + 31: '#dc322f', + 32: '#859900', + 33: '#b58900', + 34: '#268bd2', + 35: '#d33682', + 36: '#2aa198', + 37: '#ffffff', + }; + + const bgColorMap: ColorMap = { + 40: '#002b36', + 41: '#cb4b16', + 42: '#586e75', + 43: '#657b83', + 44: '#839496', + 45: '#6c71c4', + 46: '#93a1a1', + 47: '#fdf6e3', + }; + + let html = ''; + let currentFgColor: string | null = null; + let currentBgColor: string | null = null; + let isBold = false; + let isUnderline = false; + + for (let i = 0; i < text.length; i++) { + const char = text[i]; + + if (char === '\x1b' && text[i + 1] === '[') { + const codesEndIndex = text.indexOf('m', i); + const codes = text.slice(i + 2, codesEndIndex).split(';').map(code => parseInt(code, 10)); + + for (const code of codes) { + if (code === 0) { + currentFgColor = null; + currentBgColor = null; + isBold = false; + isUnderline = false; + } else if (code === 1) { + isBold = true; + } else if (code === 4) { + isUnderline = true; + } else if (code in fgColorMap) { + currentFgColor = fgColorMap[code]; + } else if (code in bgColorMap) { + currentBgColor = bgColorMap[code]; + } + } + + i = codesEndIndex; + continue; + } + + let style = ''; + if (currentFgColor) { + style += `color: ${currentFgColor};`; + } + if (currentBgColor) { + style += `background-color: ${currentBgColor};`; + } + if (isBold) { + style += 'font-weight: bold;'; + } + if (isUnderline) { + style += 'text-decoration: underline;'; + } + + if (style) { + html += `${char}`; + } else { + html += char; + } + } + + return html; +} \ No newline at end of file diff --git a/modules/markdown/code/highlightCode.ts b/modules/markdown/code/highlightCode.ts index f2c7125a..b4d14ec3 100644 --- a/modules/markdown/code/highlightCode.ts +++ b/modules/markdown/code/highlightCode.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-unnecessary-condition */ import hljs from "highlight.js/lib/core" +import AnsiToHtml from "./ansiToHtml" import { getLanguageFromAlias } from "./getLanguageFromAlias" import { importLanguage } from "./importLanguage" @@ -8,6 +9,10 @@ export const highlightCode = async (languageAlias: string, content: string) => { const language = getLanguageFromAlias(languageAlias) if (!language) return + if(language.name == "ansi"){ + return AnsiToHtml(content) + } + if (!hljs.getLanguage(language.name)) { await importLanguage(language.name) } diff --git a/modules/markdown/code/languages.ts b/modules/markdown/code/languages.ts index 6167500a..8c3ec929 100644 --- a/modules/markdown/code/languages.ts +++ b/modules/markdown/code/languages.ts @@ -7,6 +7,7 @@ export const LANGUAGES: Language[] = [ { name: "actionscript", aliases: ["as"] }, { name: "ada" }, { name: "angelscript", aliases: ["asc"] }, + { name: "ansi" }, { name: "apache", aliases: ["apacheconf"] }, { name: "applescript", aliases: ["osascript"] }, { name: "arcade" },