Commit 3aebfb4a authored by Jacques Erasmus's avatar Jacques Erasmus

Merge branch '338274-inline-katex' into 'master'

Render math expressions in the Content Editor

See merge request gitlab-org/gitlab!72153
parents adc351f5 3e60388d
import { Mark, markInputRule } from '@tiptap/core';
import { __ } from '~/locale';
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
export const inputRegex = /(?:^|\s)\$`([^`]+)`\$$/gm;
export default Mark.create({
name: 'mathInline',
parseHTML() {
return [
{
tag: 'code.math[data-math-style=inline]',
priority: PARSE_HTML_PRIORITY_HIGHEST,
},
];
},
renderHTML({ HTMLAttributes }) {
return [
'code',
{
title: __('Inline math'),
'data-toggle': 'tooltip',
class: 'gl-inset-border-1-gray-400',
...HTMLAttributes,
},
0,
];
},
addInputRules() {
return [markInputRule(inputRegex, this.type)];
},
});
...@@ -32,6 +32,7 @@ import Italic from '../extensions/italic'; ...@@ -32,6 +32,7 @@ import Italic from '../extensions/italic';
import Link from '../extensions/link'; import Link from '../extensions/link';
import ListItem from '../extensions/list_item'; import ListItem from '../extensions/list_item';
import Loading from '../extensions/loading'; import Loading from '../extensions/loading';
import MathInline from '../extensions/math_inline';
import OrderedList from '../extensions/ordered_list'; import OrderedList from '../extensions/ordered_list';
import Paragraph from '../extensions/paragraph'; import Paragraph from '../extensions/paragraph';
import Reference from '../extensions/reference'; import Reference from '../extensions/reference';
...@@ -106,6 +107,7 @@ export const createContentEditor = ({ ...@@ -106,6 +107,7 @@ export const createContentEditor = ({
Link, Link,
ListItem, ListItem,
Loading, Loading,
MathInline,
OrderedList, OrderedList,
Paragraph, Paragraph,
Reference, Reference,
......
...@@ -27,6 +27,7 @@ import InlineDiff from '../extensions/inline_diff'; ...@@ -27,6 +27,7 @@ import InlineDiff from '../extensions/inline_diff';
import Italic from '../extensions/italic'; import Italic from '../extensions/italic';
import Link from '../extensions/link'; import Link from '../extensions/link';
import ListItem from '../extensions/list_item'; import ListItem from '../extensions/list_item';
import MathInline from '../extensions/math_inline';
import OrderedList from '../extensions/ordered_list'; import OrderedList from '../extensions/ordered_list';
import Paragraph from '../extensions/paragraph'; import Paragraph from '../extensions/paragraph';
import Reference from '../extensions/reference'; import Reference from '../extensions/reference';
...@@ -86,6 +87,11 @@ const defaultSerializerConfig = { ...@@ -86,6 +87,11 @@ const defaultSerializerConfig = {
: `](${state.esc(href)}${mark.attrs.title ? ` ${state.quote(mark.attrs.title)}` : ''})`; : `](${state.esc(href)}${mark.attrs.title ? ` ${state.quote(mark.attrs.title)}` : ''})`;
}, },
}, },
[MathInline.name]: {
open: (...args) => `$${defaultMarkdownSerializer.marks.code.open(...args)}`,
close: (...args) => `${defaultMarkdownSerializer.marks.code.close(...args)}$`,
escape: false,
},
[Strike.name]: { [Strike.name]: {
open: '~~', open: '~~',
close: '~~', close: '~~',
......
...@@ -18185,6 +18185,9 @@ msgstr "" ...@@ -18185,6 +18185,9 @@ msgstr ""
msgid "Inline" msgid "Inline"
msgstr "" msgstr ""
msgid "Inline math"
msgstr ""
msgid "Input host keys manually" msgid "Input host keys manually"
msgstr "" msgstr ""
......
import MathInline from '~/content_editor/extensions/math_inline';
import { createTestEditor, createDocBuilder } from '../test_utils';
describe('content_editor/extensions/math_inline', () => {
let tiptapEditor;
let doc;
let p;
let mathInline;
beforeEach(() => {
tiptapEditor = createTestEditor({ extensions: [MathInline] });
({
builders: { doc, p, mathInline },
} = createDocBuilder({
tiptapEditor,
names: {
details: { markType: MathInline.name },
},
}));
});
it.each`
input | insertedNode
${'$`a^2`$'} | ${() => p(mathInline('a^2'))}
${'$`a^2`'} | ${() => p('$`a^2`')}
${'`a^2`$'} | ${() => p('`a^2`$')}
`('with input=$input, then should insert a $insertedNode', ({ input, insertedNode }) => {
const { view } = tiptapEditor;
const expectedDoc = doc(insertedNode());
tiptapEditor.chain().setContent(input).setTextSelection(0).run();
const { state } = tiptapEditor;
const { selection } = state;
// Triggers the event handler that input rules listen to
view.someProp('handleTextInput', (f) => f(view, selection.from, input.length + 1, input));
expect(tiptapEditor.getJSON()).toEqual(expectedDoc.toJSON());
});
});
...@@ -278,3 +278,12 @@ ...@@ -278,3 +278,12 @@
- `RGBA(0,255,0,0.3)` - `RGBA(0,255,0,0.3)`
- `HSL(540,70%,50%)` - `HSL(540,70%,50%)`
- `HSLA(540,70%,50%,0.3)` - `HSLA(540,70%,50%,0.3)`
- name: math
markdown: |-
This math is inline $`a^2+b^2=c^2`$.
This is on a separate line:
```math
a^2+b^2=c^2
```
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment