Latex Rendering Fix (#8822)

* latex

* add changeset

* delimiters fix

* change

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
Dawood Khan 2024-07-18 21:15:43 -04:00 committed by GitHub
parent e75f2ca2da
commit 3a81fb2578
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 92 additions and 5 deletions

View File

@ -0,0 +1,6 @@
---
"@gradio/markdown": patch
"gradio": patch
---
fix:Latex Rendering Fix

View File

@ -24,7 +24,8 @@
const marked = create_marked({
header_links,
line_breaks
line_breaks,
latex_delimiters
});
const is_external_url = (link: string | null): boolean => {
@ -44,14 +45,41 @@
}
});
function escapeRegExp(string: string): string {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function process_message(value: string): string {
let parsedValue = value;
if (render_markdown) {
value = marked.parse(value) as string;
const latexBlocks: string[] = [];
latex_delimiters.forEach((delimiter, index) => {
const leftDelimiter = escapeRegExp(delimiter.left);
const rightDelimiter = escapeRegExp(delimiter.right);
const regex = new RegExp(
`${leftDelimiter}([\\s\\S]+?)${rightDelimiter}`,
"g"
);
parsedValue = parsedValue.replace(regex, (match, p1) => {
latexBlocks.push(match);
return `%%%LATEX_BLOCK_${latexBlocks.length - 1}%%%`;
});
});
parsedValue = marked.parse(parsedValue) as string;
parsedValue = parsedValue.replace(
/%%%LATEX_BLOCK_(\d+)%%%/g,
(match, p1) => latexBlocks[parseInt(p1, 10)]
);
}
if (sanitize_html) {
value = DOMPurify.sanitize(value);
parsedValue = DOMPurify.sanitize(parsedValue);
}
return value;
return parsedValue;
}
$: if (message && message.trim()) {

View File

@ -66,6 +66,53 @@ function escape(html: string, encode?: boolean): string {
return html;
}
interface LatexTokenizer {
name: string;
level: string;
start: (src: string) => number | undefined;
tokenizer: (src: string, tokens: any) => any;
renderer: (token: any) => string;
}
function createLatexTokenizer(
delimiters: { left: string; right: string; display: boolean }[]
): LatexTokenizer {
const delimiterPatterns = delimiters.map((delimiter) => ({
start: new RegExp(delimiter.left.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&")),
end: new RegExp(delimiter.right.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&"))
}));
return {
name: "latex",
level: "block",
start(src: string) {
for (const pattern of delimiterPatterns) {
const match = src.match(pattern.start);
if (match) {
return match.index;
}
}
return -1;
},
tokenizer(src: string, tokens: any) {
for (const pattern of delimiterPatterns) {
const match = new RegExp(
`${pattern.start.source}([\\s\\S]+?)${pattern.end.source}`
).exec(src);
if (match) {
return {
type: "latex",
raw: match[0],
text: match[1].trim()
};
}
}
},
renderer(token: any) {
return `<div class="latex-block">${token.text}</div>`;
}
};
}
const renderer: Partial<Omit<Renderer, "constructor" | "options">> = {
code(
@ -102,10 +149,12 @@ const slugger = new GithubSlugger();
export function create_marked({
header_links,
line_breaks
line_breaks,
latex_delimiters
}: {
header_links: boolean;
line_breaks: boolean;
latex_delimiters: { left: string; right: string; display: boolean }[];
}): typeof marked {
const marked = new Marked();
@ -148,6 +197,10 @@ export function create_marked({
]
});
}
const latexTokenizer = createLatexTokenizer(latex_delimiters);
marked.use({
extensions: [latexTokenizer]
});
return marked;
}