Commit 4d98851a authored by Phil Hughes's avatar Phil Hughes

Merge branch 'ipython_katex_fixes' into 'master'

Jupyter/IPython katex math fixes

Closes #216741, #216744, and #212837

See merge request gitlab-org/gitlab!31433
parents 96adae97 a7d9d536
......@@ -36,9 +36,9 @@ const katexRegexString = `(
.replace(/\s/g, '')
.trim();
renderer.paragraph = t => {
function renderKatex(t) {
let text = t;
let inline = false;
let numInline = 0; // number of successfull converted math formulas
if (typeof katex !== 'undefined') {
const katexString = text
......@@ -50,24 +50,40 @@ renderer.paragraph = t => {
const numberOfMatches = katexString.match(regex);
if (numberOfMatches && numberOfMatches.length !== 0) {
let matches = regex.exec(katexString);
if (matchLocation > 0) {
let matches = regex.exec(katexString);
inline = true;
numInline += 1;
while (matches !== null) {
const renderedKatex = katex.renderToString(matches[0].replace(/\$/g, ''));
text = `${text.replace(matches[0], ` ${renderedKatex}`)}`;
try {
const renderedKatex = katex.renderToString(
matches[0].replace(/\$/g, '').replace(/'/g, "'"),
); // get the tick ' back again from HTMLified string
text = `${text.replace(matches[0], ` ${renderedKatex}`)}`;
} catch {
numInline -= 1;
}
matches = regex.exec(katexString);
}
} else {
const matches = regex.exec(katexString);
text = katex.renderToString(matches[2]);
try {
text = katex.renderToString(matches[2].replace(/'/g, "'"));
} catch (error) {
numInline -= 1;
}
}
}
}
return [text, numInline > 0];
}
renderer.paragraph = t => {
const [text, inline] = renderKatex(t);
return `<p class="${inline ? 'inline-katex' : ''}">${text}</p>`;
};
renderer.listitem = t => {
const [text, inline] = renderKatex(t);
return `<li class="${inline ? 'inline-katex' : ''}">${text}</li>`;
};
marked.setOptions({
renderer,
......
......@@ -63,6 +63,9 @@ export default {
},
rawCode(output) {
if (output.text) {
if (typeof output.text === 'string') {
return output.text;
}
return output.text.join('');
}
......
---
title: Katex render and vscode output improvements for markdown
merge_request: 31433
author: Reinhold Gschweicher <pyro4hell@gmail.com>
type: fixed
......@@ -53,16 +53,32 @@ describe('Code component', () => {
});
});
describe('with string for output', () => {
// NBFormat Version 4.1 allows outputs.text to be a string
beforeEach(() => {
const cell = json.cells[2];
cell.outputs[0].text = cell.outputs[0].text.join('');
vm = setupComponent(cell);
return vm.$nextTick();
});
it('does not render output prompt', () => {
expect(vm.$el.querySelectorAll('.prompt').length).toBe(2);
});
it('renders output cell', () => {
expect(vm.$el.querySelector('.output')).toBeDefined();
});
});
describe('with string for cell.source', () => {
beforeEach(done => {
beforeEach(() => {
const cell = json.cells[0];
cell.source = cell.source.join('');
vm = setupComponent(cell);
setImmediate(() => {
done();
});
return vm.$nextTick();
});
it('renders the same input as when cell.source is an array', () => {
......
......@@ -11,7 +11,7 @@ describe('Markdown component', () => {
let cell;
let json;
beforeEach(done => {
beforeEach(() => {
json = getJSONFixture('blob/notebook/basic.json');
// eslint-disable-next-line prefer-destructuring
......@@ -24,9 +24,7 @@ describe('Markdown component', () => {
});
vm.$mount();
setImmediate(() => {
done();
});
return vm.$nextTick();
});
it('does not render promot', () => {
......@@ -41,17 +39,15 @@ describe('Markdown component', () => {
expect(vm.$el.querySelector('.markdown h1')).not.toBeNull();
});
it('sanitizes output', done => {
it('sanitizes output', () => {
Object.assign(cell, {
source: [
'[XSS](data:text/html;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pPC9zY3JpcHQ+Cg==)\n',
],
});
Vue.nextTick(() => {
return vm.$nextTick().then(() => {
expect(vm.$el.querySelector('a').getAttribute('href')).toBeNull();
done();
});
});
......@@ -60,45 +56,111 @@ describe('Markdown component', () => {
json = getJSONFixture('blob/notebook/math.json');
});
it('renders multi-line katex', done => {
it('renders multi-line katex', () => {
vm = new Component({
propsData: {
cell: json.cells[0],
},
}).$mount();
Vue.nextTick(() => {
return vm.$nextTick().then(() => {
expect(vm.$el.querySelector('.katex')).not.toBeNull();
done();
});
});
it('renders inline katex', done => {
it('renders inline katex', () => {
vm = new Component({
propsData: {
cell: json.cells[1],
},
}).$mount();
Vue.nextTick(() => {
return vm.$nextTick().then(() => {
expect(vm.$el.querySelector('p:first-child .katex')).not.toBeNull();
done();
});
});
it('renders multiple inline katex', done => {
it('renders multiple inline katex', () => {
vm = new Component({
propsData: {
cell: json.cells[1],
},
}).$mount();
Vue.nextTick(() => {
return vm.$nextTick().then(() => {
expect(vm.$el.querySelectorAll('p:nth-child(2) .katex').length).toBe(4);
});
});
it('output cell in case of katex error', () => {
vm = new Component({
propsData: {
cell: {
cell_type: 'markdown',
metadata: {},
source: ['Some invalid $a & b$ inline formula $b & c$\n', '\n'],
},
},
}).$mount();
return vm.$nextTick().then(() => {
// expect one paragraph with no katex formula in it
expect(vm.$el.querySelectorAll('p').length).toBe(1);
expect(vm.$el.querySelectorAll('p .katex').length).toBe(0);
});
});
it('output cell and render remaining formula in case of katex error', () => {
vm = new Component({
propsData: {
cell: {
cell_type: 'markdown',
metadata: {},
source: ['An invalid $a & b$ inline formula and a vaild one $b = c$\n', '\n'],
},
},
}).$mount();
return vm.$nextTick().then(() => {
// expect one paragraph with no katex formula in it
expect(vm.$el.querySelectorAll('p').length).toBe(1);
expect(vm.$el.querySelectorAll('p .katex').length).toBe(1);
});
});
it('renders math formula in list object', () => {
vm = new Component({
propsData: {
cell: {
cell_type: 'markdown',
metadata: {},
source: ["- list with inline $a=2$ inline formula $a' + b = c$\n", '\n'],
},
},
}).$mount();
return vm.$nextTick().then(() => {
// expect one list with a katex formula in it
expect(vm.$el.querySelectorAll('li').length).toBe(1);
expect(vm.$el.querySelectorAll('li .katex').length).toBe(2);
});
});
it("renders math formula with tick ' in it", () => {
vm = new Component({
propsData: {
cell: {
cell_type: 'markdown',
metadata: {},
source: ["- list with inline $a=2$ inline formula $a' + b = c$\n", '\n'],
},
},
}).$mount();
done();
return vm.$nextTick().then(() => {
// expect one list with a katex formula in it
expect(vm.$el.querySelectorAll('li').length).toBe(1);
expect(vm.$el.querySelectorAll('li .katex').length).toBe(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