From 2fcea248179a4fa2a387cf6e523f7a9fc1a56dd5 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Sun, 24 Sep 2023 19:28:55 +0200 Subject: [PATCH] activitypub: parse MathML to MFM Ref: FEP-dc88 Changelog: Changed --- packages/backend/src/mfm/from-html.ts | 47 +++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/packages/backend/src/mfm/from-html.ts b/packages/backend/src/mfm/from-html.ts index 0ec5b962e..e745777bf 100644 --- a/packages/backend/src/mfm/from-html.ts +++ b/packages/backend/src/mfm/from-html.ts @@ -176,6 +176,53 @@ export function fromHtml(html: string, quoteUri?: string | null): string { break; } + // inline or block KaTeX + case 'math': { + // This node should contain [...][...] tag with the "source code". + if (node.childNodes.length !== 1 || node.childNodes[0].nodeName !== 'semantics') + break; + const semantics = node.childNodes[0]; + + // only select well formed annotations + const annotations = semantics.childNodes + .filter(node => + node.nodeName === 'annotation' + && node.childNodes.length === 1 + && node.childNodes[0].nodeName === '#text' + ); + if (annotations.length === 0) + break; + + let annotation = annotations[0]; + // try to prefer a TeX annotation if there are multiple annotations + const filteredAnnotations = annotations.filter(node => node.attrs.some(attribute => attribute.name === 'encoding' && attribute.value === 'application/x-tex')); + if (filteredAnnotations.length > 0) { + annotation = filteredAnnotations[0]; + } + + const formula = annotation.childNodes[0].value; + if (annotation.attrs.some(attribute => attribute.name === 'encoding' && attribute.value === 'application/x-tex')) { + // can be rendered as KaTeX, now decide if it is possible to render as inline or not + if (/[\r\n]/.test(formula)) { + // line break, this must be rendered as a block + text += '\n\\[' + formula + '\\]\n'; + } else { + // render as inline + text += '\\(' + formula + '\\)'; + } + } else { + // not KaTeX, but if there is a plaintext annotation it can still be rendered as code + if (/[\r\n]/.test(formula)) { + // line break, this must be rendered as a block + text += '\n```\n' + formula + '\n```\n'; + } else { + // render as inline + text += '`' + formula + '`'; + } + } + break; + } + case 'blockquote': { const t = getText(node); if (t) {