Skip to content

Commit

Permalink
Reverted to edit 8b3959ef-92d3-4cfe-a9ed-1d26d2244f9d: "feat: add dyn…
Browse files Browse the repository at this point in the history
…amic page titles based on selected conversation"
  • Loading branch information
lovable-dev[bot] committed Jan 30, 2025
1 parent f544d3c commit 1e35120
Showing 1 changed file with 106 additions and 61 deletions.
167 changes: 106 additions & 61 deletions src/utils/markdownUtils.ts
Original file line number Diff line number Diff line change
@@ -1,75 +1,120 @@
import { marked } from "marked";
import hljs from "highlight.js";
import { markedHighlight } from "marked-highlight";
import type { Link } from "marked";

marked.use(markedHighlight({
highlight: (code, lang) => {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(code, { language: lang }).value;
} catch (err) {
console.error("Error highlighting code:", err);
}
}
return code; // Use the original code if language isn't found
}
}));

const renderer = new marked.Renderer();

// Store the original link renderer
const originalLinkRenderer = renderer.link.bind(renderer);

// Customize the link renderer to add icons
renderer.link = ({ href, title, text }: Link) => {
if (!href) return text;

const linkHtml = originalLinkRenderer({ href, title, text });

let iconSvg = '';

if (href.includes('github.com')) {
// GitHub icon
iconSvg = '<svg class="inline-block ml-1 w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>';
} else if (href.includes('wikipedia.org')) {
// Simple "W" icon for Wikipedia
iconSvg = '<span class="inline-flex items-center justify-center ml-1 w-4 h-4 text-xs font-bold bg-gray-200 dark:bg-gray-700 rounded-full">W</span>';
} else {
// Generic external link icon for other links
iconSvg = '<svg class="inline-block ml-1 w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>';
import hljs from "highlight.js";

marked.setOptions({
gfm: true,
breaks: true,
silent: true,
});

marked.use(
markedHighlight({
langPrefix: "hljs language-",
highlight(code, lang, info) {
lang = info.split(".").pop() || lang;
if (lang == "shell") lang = "bash";
if (lang == "result") lang = "markdown";
const language = hljs.getLanguage(lang) ? lang : "plaintext";
return hljs.highlight(code, { language }).value;
},
})
);

export function processNestedCodeBlocks(content: string) {
// If no code blocks or only one code block, return as-is
if (content.split('```').length < 3) {
const match = content.match(/```(\S*)/);
return {
processedContent: content,
langtags: match ? [match[1]] : []
};
}

// Insert the icon after the link
return linkHtml.slice(0, -4) + iconSvg + '</a>';
};

export function processNestedCodeBlocks(content: string): { processedContent: string; langtags: string[] } {
const lines = content.split('\n');
const langtags: string[] = [];
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
let match;
let lastIndex = 0;
let processedContent = '';

while ((match = codeBlockRegex.exec(content)) !== null) {
const [fullMatch, lang] = match;
if (lang) langtags.push(lang);
processedContent += content.slice(lastIndex, match.index) + fullMatch;
lastIndex = match.index + fullMatch.length;
const result: string[] = [];

for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const strippedLine = line.trim();

if (strippedLine.startsWith('```')) {
if (strippedLine !== '```') {
// Start of a code block with a language
const lang = strippedLine.slice(3);
langtags.push(lang);
}
result.push(line);
} else {
result.push(line);
}
}

processedContent += content.slice(lastIndex);
return { processedContent, langtags };
return {
processedContent: result.join('\n'),
langtags: langtags.filter(Boolean)
};
}

export function transformThinkingTags(content: string): string {
export function transformThinkingTags(content: string) {
if (content.startsWith('`') && content.endsWith('`')) {
return content;
}

return content.replace(
/<thinking>([\s\S]*?)<\/thinking>/g,
'<details><summary>💭 Thinking</summary>\n\n$1\n\n</details>'
(_match: string, thinkingContent: string) =>
`<details><summary>💭 Thinking</summary>\n\n${thinkingContent}\n\n</details>`
);
}

export function parseMarkdownContent(content: string) {
const processedContent = transformThinkingTags(content);
const { processedContent: transformedContent, langtags } = processNestedCodeBlocks(processedContent);

let parsedResult = marked.parse(transformedContent, {
async: false,
});

parsedResult = parsedResult.replace(
/<pre><code(?:\s+class="([^"]+)")?>([^]*?)<\/code><\/pre>/g,
(_, classes = "", code) => {
const langtag_fallback = ((classes || "").split(" ")[1] || "Code").replace("language-", "");
const langtag = langtags?.shift() || langtag_fallback;
const emoji = getCodeBlockEmoji(langtag);
return `
<details>
<summary>${emoji} ${langtag}</summary>
<pre><code class="${classes}">${code}</code></pre>
</details>
`;
}
);

return parsedResult;
}

function getCodeBlockEmoji(langtag: string): string {
if (isPath(langtag)) return "📄";
if (isTool(langtag)) return "🛠️";
if (isOutput(langtag)) return "📤";
if (isWrite(langtag)) return "📝";
return "💻";
}

export function parseMarkdownContent(content: string): string {
const transformedContent = transformThinkingTags(content);
return marked(transformedContent, { renderer });
}
function isPath(langtag: string): boolean {
return (langtag.includes("/") || langtag.includes("\\") || langtag.includes(".")) && langtag.split(" ").length === 1;
}

function isTool(langtag: string): boolean {
return ["ipython", "shell", "tmux"].includes(langtag.split(" ")[0].toLowerCase());
}

function isOutput(langtag: string): boolean {
return ["stdout", "stderr", "result"].includes(langtag.toLowerCase());
}

function isWrite(langtag: string): boolean {
return ["save", "patch", "append"].includes(langtag.split(" ")[0].toLowerCase());
}

0 comments on commit 1e35120

Please sign in to comment.