Discourse Math was heavily upgraded in January 2026 to a new official core-bundled version, with MathJax 4.1 as default and KaTeX as an alternative. The plugin docs also note that KaTeX includes the CopyTex extension for copying LaTeX source.
Would it be worthwhile adding a small theme-component patch that improves quote selection for math-heavy posts?
For MathJax-heavy sites like Physics with Ethan, the most practical idea is:
1. intercept the selected HTML before Discourse turns it back into Markdown,
2. find math wrapper elements,
3. replace them with their original TeX source wrapped in $...$ or $$...$$,
4. then let Discourse continue building the quote.
Here is a potential theme-component script i would start off with, if it’s worthwhile modifying the Horizon (or Default) theme’s </head> or JS area.
<script type="text/discourse-plugin" version="1.0">
apiInitializer("1.34.0", (api) => {
function texFromMathElement(el) {
// MathJax v3/v4 commonly stores the source in an annotation child.
const annotation =
el.querySelector('annotation[encoding="application/x-tex"]') ||
el.querySelector('annotation');
if (annotation?.textContent?.trim()) {
const tex = annotation.textContent.trim();
// Heuristic: block math wrappers are often display containers.
const isBlock =
el.tagName === "MJX-CONTAINER" &&
(el.getAttribute("display") === "true" ||
el.getAttribute("display") === "block");
return isBlock ? `$$\n${tex}\n$$` : `$${tex}$`;
}
return null;
}
function patchMathInFragment(fragment) {
const candidates = fragment.querySelectorAll(
"mjx-container, .math, .katex, .MathJax"
);
candidates.forEach((node) => {
const replacement = texFromMathElement(node);
if (!replacement) {
return;
}
const textNode = document.createTextNode(replacement);
node.replaceWith(textNode);
});
return fragment;
}
api.modifyClass("component:quote-button", {
pluginId: "ethan-math-quote-fix",
_selectionChanged() {
this._super(...arguments);
try {
const selection = window.getSelection();
if (!selection || selection.rangeCount === 0) {
return;
}
const range = selection.getRangeAt(0);
const fragment = range.cloneContents();
patchMathInFragment(fragment);
const container = document.createElement("div");
container.appendChild(fragment);
// Replace the buffer that Discourse later converts into quote markdown.
if (this.quoteState) {
this.quoteState.buffer = container.innerHTML;
}
} catch (e) {
// Fail quietly so normal quoting still works.
console.warn("Math quote patch failed:", e);
}
},
});
});
</script>
A few important caveats:
• This is a practical patch, not something I found already published by Meta. The underlying strategy is inferred from the quote path going through the selected HTML and toMarkdown.
• It is most likely to help when i’m using the MathJax provider, which is the current default in Discourse Math, and the option i usually use.
• The script may need small selector tweaks depending on whether my rendered math ends up as mjx-container, .MathJax, or another wrapper. I would test on a staging site, that would be a new standard install.
• It is unlikely to be perfect for every edge case, especially mixed inline/block selections or nested quoted material.
Because Discourse now officially supports KaTeX with CopyTex, another route is to switch provider if my main pain point is copying LaTeX source rather than rendering fidelity. That would not automatically solve quote-selection, but it does mean the rendered math already has a more copy-friendly path built in.
For my MathJax heavy site, Physics with Ethan, i’m currently thinking:
• keep MathJax unless someone suggests i could change to KaTex? ,
• maybe add a quote-selection patch to the Horizon theme, from the above (using a staging site).
• and treat it as a local quality-of-life fix until there is a proper upstream solution. This 2020 feature topic still being open in 2026 suggests upstream may remain slow here.