improve: Extracted original LaTeX when quoting and replying.

This commit implemented logic to retrieve the original LaTeX code from .katex-mathml when the user only highlights some part when quote and replying.

Fixes #31608.
This commit is contained in:
aditya.chaudhary1558@gmail.com 2024-10-02 04:47:50 +05:30
parent c032bd9e78
commit dd88651615
2 changed files with 72 additions and 2 deletions

View File

@ -362,7 +362,7 @@ function image_to_zulip_markdown(
const src = node.getAttribute("src") ?? node.getAttribute("href") ?? "";
const title = deduplicate_newlines(node.getAttribute("title") ?? "");
// Using Zulip's link like syntax for images
return src ? "[" + title + "](" + src + ")" : (node.getAttribute("alt") ?? "");
return src ? "[" + title + "](" + src + ")" : node.getAttribute("alt") ?? "";
}
function within_single_element(html_fragment: HTMLElement): boolean {
@ -436,6 +436,36 @@ export function paste_handler_converter(paste_html: string): string {
return "~~" + content + "~~";
},
});
turndownService.addRule("latexMath", {
filter(node: Node) {
if (!(node instanceof Element)) {
return false;
}
const closest_display = node.closest(".katex-display");
const has_mathml = node.querySelector(".katex-mathml") !== null;
return closest_display !== null && has_mathml;
},
replacement(content: string, node: Node) {
if (!(node instanceof Element)) {
return content;
}
const display_element = node.closest(".katex-display") ?? node;
const mathml_element = display_element.querySelector(".katex-mathml");
assert(mathml_element, "Expected .katex-mathml element not found.");
const annotation = mathml_element.querySelector(
'annotation[encoding="application/x-tex"]',
);
assert(annotation?.textContent, "Expected LaTeX annotation not found.");
const latex_content = annotation.textContent.trim();
return latex_content.includes("\n")
? `\`\`\`math\n${latex_content}\n\`\`\`\n`
: `$$${latex_content}$$`;
},
});
turndownService.addRule("links", {
filter: ["a"],
replacement(content, node) {
@ -570,7 +600,7 @@ export function paste_handler_converter(paste_html: string): string {
const className = codeElement.getAttribute("class") ?? "";
const language = node.parentElement?.classList.contains("zulip-code-block")
? (node.closest<HTMLElement>(".codehilite")?.dataset?.codeLanguage ?? "")
? node.closest<HTMLElement>(".codehilite")?.dataset?.codeLanguage ?? ""
: (/language-(\S+)/.exec(className) ?? [null, ""])[1];
assert(options.fence !== undefined);

View File

@ -2,6 +2,8 @@
const assert = require("node:assert/strict");
const {JSDOM} = require("jsdom");
const {zrequire} = require("./lib/namespace.cjs");
const {run_test} = require("./lib/test.cjs");
@ -83,6 +85,44 @@ run_test("try_stream_topic_syntax_text", () => {
}
});
run_test("latex_math_conversion", () => {
const {window} = new JSDOM(`<!DOCTYPE html><html><body></body></html>`);
global.document = window.document;
global.Element = window.Element;
// Test case for inline LaTeX math
let input = `
<span class="katex-mathml">
<annotation encoding="application/x-tex">$$x^2 + y^2 = z^2$$</annotation>
</span>`;
assert.equal(copy_and_paste.paste_handler_converter(input), "$$x^2 + y^2 = z^2$$");
// Test case for multiline LaTeX math
input = `
<span class="katex-display">
<span class="katex-mathml">
<annotation encoding="application/x-tex">\\begin{align}
x + y &= z \\\\
a + b &= c
\\end{align}</annotation>
</span>
</span>`;
assert.equal(
copy_and_paste.paste_handler_converter(input),
"\\begin{align} x + y &= z \\\\ a + b &= c \\end{align}",
);
// Test case where no math content exists
input = `<div><p>No math here</p></div>`;
assert.equal(copy_and_paste.paste_handler_converter(input), "No math here");
// Test case where closest display exists but no annotation
input = `
<span class="katex-display">
<span class="katex-mathml"></span>
</span`;
assert.equal(copy_and_paste.paste_handler_converter(input), "");
});
run_test("maybe_transform_html", () => {
// Copied HTML from VS Code
let paste_html = `<div style="color: #cccccc;background-color: #1f1f1f;font-family: 'Droid Sans Mono', 'monospace', monospace;font-weight: normal;font-size: 14px;line-height: 19px;white-space: pre;"><div><span style="color: #c586c0;">if</span><span style="color: #cccccc;"> (</span><span style="color: #9cdcfe;">$preview_src</span><span style="color: #cccccc;">.</span><span style="color: #dcdcaa;">endsWith</span><span style="color: #cccccc;">(</span><span style="color: #ce9178;">"&amp;size=full"</span><span style="color: #cccccc;">))</span></div></div>`;