Commit b8452bf3 authored by Stan Hu's avatar Stan Hu

Fix images not showing in Jupyter Markdown tables

Previously cell attachments were ignored by the iPython notebook parser.
As described in
https://nbformat.readthedocs.io/en/latest/format_description.html, we
need to support the `attachments` dictionary and use that to render
images.

Closes https://gitlab.com/gitlab-org/gitlab/-/issues/18540
parent 71709028
......@@ -3,6 +3,7 @@
import katex from 'katex';
import marked from 'marked';
import { sanitize } from '~/lib/dompurify';
import { hasContent } from '~/lib/utils/text_utility';
import Prompt from './prompt.vue';
const renderer = new marked.Renderer();
......@@ -85,6 +86,38 @@ renderer.listitem = (t) => {
const [text, inline] = renderKatex(t);
return `<li class="${inline ? 'inline-katex' : ''}">${text}</li>`;
};
renderer.originalImage = renderer.image;
renderer.image = function image(href, title, text) {
const attachmentHeader = `attachment:`; // eslint-disable-line @gitlab/require-i18n-strings
if (!this.attachments || !href.startsWith(attachmentHeader)) {
return this.originalImage(href, title, text);
}
let img = ``;
const filename = href.substring(attachmentHeader.length);
if (hasContent(filename)) {
const attachment = this.attachments[filename];
if (attachment) {
const imageType = Object.keys(attachment)[0];
if (hasContent(imageType)) {
const data = attachment[imageType];
const inlined = `data:${imageType};base64,${data}"`; // eslint-disable-line @gitlab/require-i18n-strings
img = this.originalImage(inlined, title, text);
}
}
}
if (!hasContent(img)) {
return this.originalImage(href, title, text);
}
return sanitize(img);
};
marked.setOptions({
renderer,
......@@ -102,6 +135,8 @@ export default {
},
computed: {
markdown() {
renderer.attachments = this.cell.attachments;
return sanitize(marked(this.cell.source.join('').replace(/\\/g, '\\\\')), {
// allowedTags from GitLab's inline HTML guidelines
// https://docs.gitlab.com/ee/user/markdown.html#inline-html
......
---
title: Fix images not showing in Jupyter Markdown tables
merge_request: 59551
author:
type: fixed
......@@ -25,6 +25,10 @@ RSpec.describe 'Raw files', '(JavaScript fixtures)' do
@blob = project.repository.blob_at('6d85bb69', 'files/ipython/basic.ipynb')
end
it 'blob/notebook/markdown-table.json' do
@blob = project.repository.blob_at('b0316785', 'files/ipython/markdown-table.ipynb')
end
it 'blob/notebook/worksheets.json' do
@blob = project.repository.blob_at('6d85bb69', 'files/ipython/worksheets.ipynb')
end
......
......@@ -27,7 +27,7 @@ describe('Markdown component', () => {
return vm.$nextTick();
});
it('does not render promot', () => {
it('does not render prompt', () => {
expect(vm.$el.querySelector('.prompt span')).toBeNull();
});
......@@ -51,6 +51,36 @@ describe('Markdown component', () => {
});
});
describe('tables', () => {
beforeEach(() => {
json = getJSONFixture('blob/notebook/markdown-table.json');
});
it('renders images and text', () => {
vm = new Component({
propsData: {
cell: json.cells[0],
},
}).$mount();
return vm.$nextTick().then(() => {
const images = vm.$el.querySelectorAll('img');
expect(images.length).toBe(3);
const columns = vm.$el.querySelectorAll('td');
expect(images.length).toBe(3);
expect(columns[0].textContent).toEqual('Hello ');
expect(columns[1].textContent).toEqual('Test ');
expect(columns[2].textContent).toEqual('World ');
expect(columns[0].innerHTML).toContain('<img src="data:image/jpeg;base64');
expect(columns[1].innerHTML).toContain('<img src="data:image/png;base64');
expect(columns[2].innerHTML).toContain('<img src="data:image/jpeg;base64');
});
});
});
describe('katex', () => {
beforeEach(() => {
json = getJSONFixture('blob/notebook/math.json');
......
......@@ -52,7 +52,7 @@ module TestEnv
'wip' => 'b9238ee',
'csv' => '3dd0896',
'v1.1.0' => 'b83d6e3',
'add-ipython-files' => '93ee732',
'add-ipython-files' => 'b031678',
'add-pdf-file' => 'e774ebd',
'squash-large-files' => '54cec52',
'add-pdf-text-binary' => '79faa7b',
......
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