From 52c888f6b8764af4e213a32f8214c92ca49cf9f4 Mon Sep 17 00:00:00 2001 From: Rian Date: Mon, 12 Aug 2024 19:08:35 +0100 Subject: [PATCH 1/5] Improve latex rendering --- fasthtml/js.py | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/fasthtml/js.py b/fasthtml/js.py index d379e435..43bdafc5 100644 --- a/fasthtml/js.py +++ b/fasthtml/js.py @@ -1,3 +1,4 @@ +import re from fastcore.utils import * from fasthtml.xtend import Script,jsd,Style,Link @@ -12,16 +13,41 @@ def MarkdownJS(sel='.marked'): src = "proc_htmx('%s', e => e.innerHTML = marked.parse(e.textContent));" % sel return Script(marked_imp+src, type='module') -def KatexMarkdownJS(sel='.marked', katex_tags='$'): - right_tags = '\\$' if katex_tags=='$' else '\\]' +def KatexMarkdownJS(sel='.marked', inline_delim='$', display_delim='$$', math_envs=None): + math_envs = math_envs or ['equation', 'align', 'gather', 'multline'] + env_list = ','.join(f"'{env}'" for env in math_envs) + src = """ import katex from "https://cdn.jsdelivr.net/npm/katex/dist/katex.mjs"; - const renderMath = tex => katex.renderToString(tex, {throwOnError: false, displayMode: false}); - + const renderMath = (tex, displayMode) => { + return katex.renderToString(tex, { + throwOnError: false, + displayMode: displayMode, + output: 'html', + trust: true + }); + }; + const processLatexEnvironments = (content) => { + return content.replace(/\\\\begin{(\\w+)}([\\s\\S]*?)\\\\end{\\1}/g, (match, env, innerContent) => { + if ([%s].includes(env)) { + return `%s${match}%s`; + } + return match; + }); + }; proc_htmx('%s', e => { - e.innerHTML = marked.parse(e.textContent).replace(/%s{1,2}\\n*(.+?)\\n*%s{1,2}/g, (_, tex) => renderMath(tex)); + let content = processLatexEnvironments(e.textContent); + // Handle display math (including environments) + content = content.replace(/%s([\\s\\S]+?)%s/gm, (_, tex) => renderMath(tex.trim(), true)); + // Handle inline math + content = content.replace(/(? renderMath(tex.trim(), false)); + e.innerHTML = marked.parse(content); }); - """ % (sel, "\\"+katex_tags, right_tags) + """ % (env_list, re.escape(display_delim), re.escape(display_delim), + sel, re.escape(display_delim), re.escape(display_delim), + re.escape(inline_delim), re.escape(inline_delim), re.escape(inline_delim), + re.escape(inline_delim), re.escape(inline_delim)) + return (Script(marked_imp+src, type='module'), Link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css")) From f2ec64bf8d637c37a6fe16ca1ac3e6f138ba71b4 Mon Sep 17 00:00:00 2001 From: Rian Date: Mon, 12 Aug 2024 20:54:53 +0100 Subject: [PATCH 2/5] change to raw string and remove double back slashes --- fasthtml/js.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fasthtml/js.py b/fasthtml/js.py index 43bdafc5..4ecb1b02 100644 --- a/fasthtml/js.py +++ b/fasthtml/js.py @@ -17,7 +17,7 @@ def KatexMarkdownJS(sel='.marked', inline_delim='$', display_delim='$$', math_en math_envs = math_envs or ['equation', 'align', 'gather', 'multline'] env_list = ','.join(f"'{env}'" for env in math_envs) - src = """ + src = r""" import katex from "https://cdn.jsdelivr.net/npm/katex/dist/katex.mjs"; const renderMath = (tex, displayMode) => { return katex.renderToString(tex, { @@ -28,7 +28,7 @@ def KatexMarkdownJS(sel='.marked', inline_delim='$', display_delim='$$', math_en }); }; const processLatexEnvironments = (content) => { - return content.replace(/\\\\begin{(\\w+)}([\\s\\S]*?)\\\\end{\\1}/g, (match, env, innerContent) => { + return content.replace(/\\begin{(\w+)}([\s\S]*?)\\end{\1}/g, (match, env, innerContent) => { if ([%s].includes(env)) { return `%s${match}%s`; } @@ -38,9 +38,9 @@ def KatexMarkdownJS(sel='.marked', inline_delim='$', display_delim='$$', math_en proc_htmx('%s', e => { let content = processLatexEnvironments(e.textContent); // Handle display math (including environments) - content = content.replace(/%s([\\s\\S]+?)%s/gm, (_, tex) => renderMath(tex.trim(), true)); + content = content.replace(/%s([\s\S]+?)%s/gm, (_, tex) => renderMath(tex.trim(), true)); // Handle inline math - content = content.replace(/(? renderMath(tex.trim(), false)); + content = content.replace(/(? renderMath(tex.trim(), false)); e.innerHTML = marked.parse(content); }); """ % (env_list, re.escape(display_delim), re.escape(display_delim), From 87e6cfa15376ab43cf5ed93e6c87bc62d5496410 Mon Sep 17 00:00:00 2001 From: Rian Date: Mon, 12 Aug 2024 20:55:55 +0100 Subject: [PATCH 3/5] Move to one line --- fasthtml/js.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fasthtml/js.py b/fasthtml/js.py index 4ecb1b02..698bb6d0 100644 --- a/fasthtml/js.py +++ b/fasthtml/js.py @@ -19,8 +19,7 @@ def KatexMarkdownJS(sel='.marked', inline_delim='$', display_delim='$$', math_en src = r""" import katex from "https://cdn.jsdelivr.net/npm/katex/dist/katex.mjs"; - const renderMath = (tex, displayMode) => { - return katex.renderToString(tex, { + const renderMath = (tex, displayMode) => { return katex.renderToString(tex, { throwOnError: false, displayMode: displayMode, output: 'html', From 66238efe73b31a1cbc3edde0fc1cd23bfcafb013 Mon Sep 17 00:00:00 2001 From: Rian Date: Mon, 12 Aug 2024 20:57:54 +0100 Subject: [PATCH 4/5] Move to same line --- fasthtml/js.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fasthtml/js.py b/fasthtml/js.py index 698bb6d0..1b13a78b 100644 --- a/fasthtml/js.py +++ b/fasthtml/js.py @@ -28,9 +28,7 @@ def KatexMarkdownJS(sel='.marked', inline_delim='$', display_delim='$$', math_en }; const processLatexEnvironments = (content) => { return content.replace(/\\begin{(\w+)}([\s\S]*?)\\end{\1}/g, (match, env, innerContent) => { - if ([%s].includes(env)) { - return `%s${match}%s`; - } + if ([%s].includes(env)) { return `%s${match}%s`; } return match; }); }; From fce9800e1782bcdcf0f3cf4eec326765a6202093 Mon Sep 17 00:00:00 2001 From: Rian Date: Mon, 12 Aug 2024 21:03:39 +0100 Subject: [PATCH 5/5] update code to use named format params and passing a format dict --- fasthtml/js.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/fasthtml/js.py b/fasthtml/js.py index 1b13a78b..4b5d54e0 100644 --- a/fasthtml/js.py +++ b/fasthtml/js.py @@ -28,24 +28,27 @@ def KatexMarkdownJS(sel='.marked', inline_delim='$', display_delim='$$', math_en }; const processLatexEnvironments = (content) => { return content.replace(/\\begin{(\w+)}([\s\S]*?)\\end{\1}/g, (match, env, innerContent) => { - if ([%s].includes(env)) { return `%s${match}%s`; } + if ([%(env_list)s].includes(env)) { return `%(display_delim)s${match}%(display_delim)s`; } return match; }); }; - proc_htmx('%s', e => { + proc_htmx('%(sel)s', e => { let content = processLatexEnvironments(e.textContent); // Handle display math (including environments) - content = content.replace(/%s([\s\S]+?)%s/gm, (_, tex) => renderMath(tex.trim(), true)); + content = content.replace(/%(display_delim)s([\s\S]+?)%(display_delim)s/gm, (_, tex) => renderMath(tex.trim(), true)); // Handle inline math - content = content.replace(/(? renderMath(tex.trim(), false)); + content = content.replace(/(? renderMath(tex.trim(), false)); e.innerHTML = marked.parse(content); }); - """ % (env_list, re.escape(display_delim), re.escape(display_delim), - sel, re.escape(display_delim), re.escape(display_delim), - re.escape(inline_delim), re.escape(inline_delim), re.escape(inline_delim), - re.escape(inline_delim), re.escape(inline_delim)) - - return (Script(marked_imp+src, type='module'), + """ + format_dict = { + 'env_list': env_list, + 'sel': sel, + 'display_delim': re.escape(display_delim), + 'inline_delim': re.escape(inline_delim) + } + formatted_src = src % format_dict + return (Script(marked_imp + formatted_src, type='module'), Link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css"))