From 5591e59680725a957bf4acd198578abce3089e61 Mon Sep 17 00:00:00 2001
From: end-4 <97237370+end-4@users.noreply.github.com>
Date: Thu, 3 Apr 2025 23:19:13 +0200
Subject: [PATCH] ai: turn inline latex into latex code blocks for proper
rendering
it looks poopy sometimes but still better than copilot failing all the time
---
.config/ags/modules/.miscutils/md2pango.js | 18 ++++++++++++++++++
.../modules/sideleft/apis/ai_chatmessage.js | 9 ++++-----
2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/.config/ags/modules/.miscutils/md2pango.js b/.config/ags/modules/.miscutils/md2pango.js
index 19999bd3a..e0eb4d4f6 100644
--- a/.config/ags/modules/.miscutils/md2pango.js
+++ b/.config/ags/modules/.miscutils/md2pango.js
@@ -4,6 +4,7 @@
const monospaceFonts = 'JetBrains Mono NF, JetBrains Mono Nerd Font, JetBrains Mono NL, SpaceMono NF, SpaceMono Nerd Font, monospace';
+const codeBlockRegex = /^\s*```([a-zA-Z0-9]+)?\n?/;
const replacements = {
'indents': [
{ name: 'BULLET', re: /^(\s*)([\*\-]\s)(.*)(\s*)$/, sub: ' $1- $3' },
@@ -31,6 +32,11 @@ const replacements = {
{ name: 'INLCODE', re: /(`)([^`]*)(`)/g, sub: '$2' },
// { name: 'UND', re: /(__|\*\*)(\S[\s\S]*?\S)(__|\*\*)/g, sub: "$2" },
],
+ 'forceLatex': [
+ { name: 'LATEX_INLINE_SQUARE', re: /\\\[(.*?)\\\]/g, sub: '\n```latex\n$1\n```' },
+ { name: 'LATEX_INLINE_ROUND', re: /\\\((.*?)\\\)/g, sub: '\n```latex\n$1\n```' },
+ { name: 'LATEX_INLINE_DOLLAR', re: /\$(.*?)\$/g, sub: '\n```latex\n$1\n```' }
+ ]
}
const replaceCategory = (text, replaces) => {
@@ -42,12 +48,22 @@ const replaceCategory = (text, replaces) => {
// Main function
+export function replaceInlineLatexWithCodeBlocks(text) {
+ return text.replace(/\\\[(.*?)\\\]|\\\((.*?)\\\)|\$(.*?)\$/gs, (match, square, round, dollar) => {
+ const latex = square || round || dollar;
+ return `\n\`\`\`latex\n${latex}\n\`\`\`\n`;
+ });
+}
+
export default (text) => {
let lines = text.split('\n')
let output = [];
+ let inCode = false;
// Replace
for (const line of lines) {
let result = line;
+ if (codeBlockRegex.test(line)) inCode = !inCode;
+ if (inCode) continue;
result = replaceCategory(result, replacements.indents);
result = replaceCategory(result, replacements.escapes);
result = replaceCategory(result, replacements.sections);
@@ -74,6 +90,8 @@ int main(int argc, char* argv[]) {
}
\`\`\`
## LaTeX
+- Inline LaTeX: \\[ \\frac{d}{dx} \\left( \\frac{x-438}{x^2+23x-7} \\right) = \\frac{-x^2 + 869}{(x^2+23x-7)^2} \\]
+- Block LaTeX:
\`\`\`latex
\\frac{d}{dx} \\left( \\frac{x-438}{x^2+23x-7} \\right) = \\frac{-x^2 + 869}{(x^2+23x-7)^2} \\\\ → \\\\ cos(2x) = 2cos^2(x) - 1 = 1 - 2sin^2(x) = cos^2(x) - sin^2(x)
\`\`\`
diff --git a/.config/ags/modules/sideleft/apis/ai_chatmessage.js b/.config/ags/modules/sideleft/apis/ai_chatmessage.js
index e0047657e..9f9627ff6 100644
--- a/.config/ags/modules/sideleft/apis/ai_chatmessage.js
+++ b/.config/ags/modules/sideleft/apis/ai_chatmessage.js
@@ -6,7 +6,7 @@ import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
const { Box, Button, Label, Icon, Scrollable, Stack } = Widget;
const { execAsync, exec } = Utils;
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
-import md2pango from '../../.miscutils/md2pango.js';
+import md2pango, { replaceInlineLatexWithCodeBlocks } from '../../.miscutils/md2pango.js';
import { darkMode } from "../../.miscutils/system.js";
const LATEX_DIR = `${GLib.get_user_cache_dir()}/ags/media/latex`;
@@ -216,12 +216,11 @@ const MessageContent = (content) => {
child.destroy();
}
contentBox.add(TextBlock())
- // Loop lines. Put normal text in markdown parser
- // and put code into code highlighter (TODO)
- let lines = content.split('\n');
+
+ let lines = replaceInlineLatexWithCodeBlocks(content).split('\n');
let lastProcessed = 0;
let inCode = false;
- for (const [index, line] of lines.entries()) {
+ for (let [index, line] of lines.entries()) {
// Code blocks
const codeBlockRegex = /^\s*```([a-zA-Z0-9]+)?\n?/;
if (codeBlockRegex.test(line)) {