Commit 568571cf authored by Phil Hughes's avatar Phil Hughes

Merge branch 'sh-jupyter-fix-images' into 'master'

Fix images not showing in Jupyter Markdown tables

See merge request gitlab-org/gitlab!59551
parents 585fab33 94ad0af7
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
import katex from 'katex'; import katex from 'katex';
import marked from 'marked'; import marked from 'marked';
import { sanitize } from '~/lib/dompurify'; import { sanitize } from '~/lib/dompurify';
import { hasContent } from '~/lib/utils/text_utility';
import Prompt from './prompt.vue'; import Prompt from './prompt.vue';
const renderer = new marked.Renderer(); const renderer = new marked.Renderer();
...@@ -88,6 +89,38 @@ renderer.listitem = (t) => { ...@@ -88,6 +89,38 @@ renderer.listitem = (t) => {
const [text, inline] = renderKatex(t); const [text, inline] = renderKatex(t);
return `<li class="${inline ? 'inline-katex' : ''}">${text}</li>`; 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({ marked.setOptions({
renderer, renderer,
...@@ -105,6 +138,8 @@ export default { ...@@ -105,6 +138,8 @@ export default {
}, },
computed: { computed: {
markdown() { markdown() {
renderer.attachments = this.cell.attachments;
return sanitize(marked(this.cell.source.join('').replace(/\\/g, '\\\\')), { return sanitize(marked(this.cell.source.join('').replace(/\\/g, '\\\\')), {
// allowedTags from GitLab's inline HTML guidelines // allowedTags from GitLab's inline HTML guidelines
// https://docs.gitlab.com/ee/user/markdown.html#inline-html // 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 ...@@ -25,6 +25,10 @@ RSpec.describe 'Raw files', '(JavaScript fixtures)' do
@blob = project.repository.blob_at('6d85bb69', 'files/ipython/basic.ipynb') @blob = project.repository.blob_at('6d85bb69', 'files/ipython/basic.ipynb')
end end
it 'blob/notebook/markdown-table.json' do
@blob = project.repository.blob_at('f6b7a707', 'files/ipython/markdown-table.ipynb')
end
it 'blob/notebook/worksheets.json' do it 'blob/notebook/worksheets.json' do
@blob = project.repository.blob_at('6d85bb69', 'files/ipython/worksheets.ipynb') @blob = project.repository.blob_at('6d85bb69', 'files/ipython/worksheets.ipynb')
end end
......
...@@ -27,7 +27,7 @@ describe('Markdown component', () => { ...@@ -27,7 +27,7 @@ describe('Markdown component', () => {
return vm.$nextTick(); return vm.$nextTick();
}); });
it('does not render promot', () => { it('does not render prompt', () => {
expect(vm.$el.querySelector('.prompt span')).toBeNull(); expect(vm.$el.querySelector('.prompt span')).toBeNull();
}); });
...@@ -50,6 +50,41 @@ describe('Markdown component', () => { ...@@ -50,6 +50,41 @@ describe('Markdown component', () => {
expect(vm.$el.querySelector('a').getAttribute('href')).toBeNull(); expect(vm.$el.querySelector('a').getAttribute('href')).toBeNull();
}); });
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(5);
const columns = vm.$el.querySelectorAll('td');
expect(columns.length).toBe(6);
expect(columns[0].textContent).toEqual('Hello ');
expect(columns[1].textContent).toEqual('Test ');
expect(columns[2].textContent).toEqual('World ');
expect(columns[3].textContent).toEqual('Fake ');
expect(columns[4].textContent).toEqual('External image: ');
expect(columns[5].textContent).toEqual('Empty');
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');
expect(columns[3].innerHTML).toContain('<img>');
expect(columns[4].innerHTML).toContain('<img src="https://www.google.com/');
});
});
});
describe('katex', () => { describe('katex', () => {
beforeEach(() => { beforeEach(() => {
json = getJSONFixture('blob/notebook/math.json'); json = getJSONFixture('blob/notebook/math.json');
......
...@@ -52,7 +52,7 @@ module TestEnv ...@@ -52,7 +52,7 @@ module TestEnv
'wip' => 'b9238ee', 'wip' => 'b9238ee',
'csv' => '3dd0896', 'csv' => '3dd0896',
'v1.1.0' => 'b83d6e3', 'v1.1.0' => 'b83d6e3',
'add-ipython-files' => '93ee732', 'add-ipython-files' => 'f6b7a70',
'add-pdf-file' => 'e774ebd', 'add-pdf-file' => 'e774ebd',
'squash-large-files' => '54cec52', 'squash-large-files' => '54cec52',
'add-pdf-text-binary' => '79faa7b', '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