Compare commits
3 commits
1e7d2cf54c
...
2fcea24817
Author | SHA1 | Date | |
---|---|---|---|
2fcea24817 | |||
5bb10de1e0 | |||
f6c3d44265 |
5 changed files with 68 additions and 14 deletions
|
@ -60,6 +60,7 @@
|
|||
"json5-loader": "4.0.1",
|
||||
"jsonld": "6.0.0",
|
||||
"jsrsasign": "10.5.25",
|
||||
"katex": "^0.16.0",
|
||||
"koa": "2.13.4",
|
||||
"koa-bodyparser": "4.3.0",
|
||||
"koa-favicon": "2.1.0",
|
||||
|
|
|
@ -176,6 +176,53 @@ export function fromHtml(html: string, quoteUri?: string | null): string {
|
|||
break;
|
||||
}
|
||||
|
||||
// inline or block KaTeX
|
||||
case 'math': {
|
||||
// This node should contain <semantics>[...]<annotation/>[...]</semantics> 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) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { JSDOM } from 'jsdom';
|
||||
import katex from 'katex';
|
||||
import * as mfm from 'mfm-js';
|
||||
import config from '@/config/index.js';
|
||||
import { UserProfiles } from '@/models/index.js';
|
||||
|
@ -6,6 +7,14 @@ import { extractMentions } from '@/misc/extract-mentions.js';
|
|||
import { intersperse } from '@/prelude/array.js';
|
||||
import { toPunyNullable } from '@/misc/convert-host.js';
|
||||
|
||||
function toMathMl(code: string): HTMLElement {
|
||||
const rendered = katex.renderToString(code, {
|
||||
throwOnError: false,
|
||||
output: 'mathml',
|
||||
});
|
||||
return JSDOM.fragment(rendered).querySelector('math');
|
||||
}
|
||||
|
||||
// Transforms MFM to HTML, given the MFM text and a list of user IDs that are
|
||||
// mentioned in the text. If the list of mentions is not given, all mentions
|
||||
// from the text will be extracted.
|
||||
|
@ -98,15 +107,11 @@ export async function toHtml(mfmText: string, mentions?: string[]): Promise<stri
|
|||
},
|
||||
|
||||
async mathInline(node) {
|
||||
const el = doc.createElement('code');
|
||||
el.textContent = node.props.formula;
|
||||
return el;
|
||||
return toMathMl(node.props.formula);
|
||||
},
|
||||
|
||||
async mathBlock(node) {
|
||||
const el = doc.createElement('code');
|
||||
el.textContent = node.props.formula;
|
||||
return el;
|
||||
return toMathMl(node.props.formula);
|
||||
},
|
||||
|
||||
async link(node) {
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
"idb-keyval": "6.2.0",
|
||||
"insert-text-at-cursor": "0.3.0",
|
||||
"json5": "2.2.1",
|
||||
"katex": "0.16.0",
|
||||
"katex": "^0.16.0",
|
||||
"matter-js": "0.18.0",
|
||||
"mfm-js": "0.23.3",
|
||||
"photoswipe": "5.2.8",
|
||||
|
|
15
yarn.lock
15
yarn.lock
|
@ -3742,6 +3742,7 @@ __metadata:
|
|||
json5-loader: 4.0.1
|
||||
jsonld: 6.0.0
|
||||
jsrsasign: 10.5.25
|
||||
katex: ^0.16.0
|
||||
koa: 2.13.4
|
||||
koa-bodyparser: 4.3.0
|
||||
koa-favicon: 2.1.0
|
||||
|
@ -4705,7 +4706,7 @@ __metadata:
|
|||
idb-keyval: 6.2.0
|
||||
insert-text-at-cursor: 0.3.0
|
||||
json5: 2.2.1
|
||||
katex: 0.16.0
|
||||
katex: ^0.16.0
|
||||
matter-js: 0.18.0
|
||||
mfm-js: 0.23.3
|
||||
photoswipe: 5.2.8
|
||||
|
@ -5043,7 +5044,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"commander@npm:^8.0.0":
|
||||
"commander@npm:^8.3.0":
|
||||
version: 8.3.0
|
||||
resolution: "commander@npm:8.3.0"
|
||||
checksum: 0f82321821fc27b83bd409510bb9deeebcfa799ff0bf5d102128b500b7af22872c0c92cb6a0ebc5a4cf19c6b550fba9cedfa7329d18c6442a625f851377bacf0
|
||||
|
@ -10895,14 +10896,14 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"katex@npm:0.16.0":
|
||||
version: 0.16.0
|
||||
resolution: "katex@npm:0.16.0"
|
||||
"katex@npm:^0.16.0":
|
||||
version: 0.16.8
|
||||
resolution: "katex@npm:0.16.8"
|
||||
dependencies:
|
||||
commander: ^8.0.0
|
||||
commander: ^8.3.0
|
||||
bin:
|
||||
katex: cli.js
|
||||
checksum: 0e094523544b3c921e55da8cf1a9ea2718213c621af508af9fc03859b97dc73280f478fbfede5a8b32948210c3596c5a637dd64e0e28e31d6c617b5d50c29762
|
||||
checksum: 4e75b4786101cc5eca0404bb814b2985bec506846f9015e9bf00207a3af14215e341ee62b6e7af2455a1032f8244e47a754642f250eea43d7b8007146ac01fae
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue