Skip to content

Commit

Permalink
Merge pull request #3870 from rtibbles/assessment_tweaks
Browse files Browse the repository at this point in the history
Fix markdown conversion for assessments
  • Loading branch information
bjester authored Dec 7, 2022
2 parents 7517281 + 6e25862 commit 88d7008
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,19 @@
import '../mathquill/mathquill.js';
import 'codemirror/lib/codemirror.css';
import '@toast-ui/editor/dist/toastui-editor.css';
import * as Showdown from 'showdown';
import Editor from '@toast-ui/editor';
import { stripHtml } from 'string-strip-html';
import imageUpload, { paramsToImageFieldHTML } from '../plugins/image-upload';
import formulas from '../plugins/formulas';
import minimize from '../plugins/minimize';
import formulaHtmlToMd from '../plugins/formulas/formula-html-to-md';
import formulaMdToHtml from '../plugins/formulas/formula-md-to-html';
import imagesHtmlToMd from '../plugins/image-upload/image-html-to-md';
import imagesMdToHtml from '../plugins/image-upload/image-md-to-html';
import { CLASS_MATH_FIELD_ACTIVE } from '../constants';
import { registerMarkdownFormulaField } from '../plugins/formulas/MarkdownFormulaField';
import { registerMarkdownImageField } from '../plugins/image-upload/MarkdownImageField';
import { clearNodeFormat, getExtensionMenuPosition } from './utils';
import { clearNodeFormat, generateCustomConverter, getExtensionMenuPosition } from './utils';
import FormulasMenu from './FormulasMenu/FormulasMenu';
import ImagesMenu from './ImagesMenu/ImagesMenu';
import ClickOutside from 'shared/directives/click-outside';
Expand Down Expand Up @@ -167,38 +163,7 @@
mounted() {
this.mathQuill = MathQuill.getInterface(2);
// This is currently the only way of inheriting and adjusting
// default TUI's convertor methods
// see https://github.com/nhn/tui.editor/issues/615
const tmpEditor = new Editor({
el: this.$refs.editor,
});
const showdown = new Showdown.Converter();
const Convertor = tmpEditor.convertor.constructor;
class CustomConvertor extends Convertor {
toMarkdown(content) {
content = imagesHtmlToMd(content);
content = formulaHtmlToMd(content);
content = showdown.makeMarkdown(content);
// TUI.editor sprinkles in extra `<br>` tags that Kolibri renders literally
// When showdown has already added linebreaks to render these in markdown
// so we just remove these here.
content = content.replaceAll('<br>', '');
// any copy pasted rich text that renders as HTML but does not get converted
// will linger here, so remove it as Kolibri will render it literally also.
content = stripHtml(content).result;
return content;
}
toHTML(content) {
// Kolibri and showdown assume double newlines for a single line break,
// wheras TUI.editor prefers single newline characters.
content = content.replaceAll('\n\n', '\n');
content = super.toHTML(content);
return content;
}
}
tmpEditor.remove();
const CustomConvertor = generateCustomConverter(this.$refs.editor);
const createBoldButton = () => {
{
Expand Down Expand Up @@ -268,8 +233,8 @@
// https://github.com/nhn/tui.editor/blob/master/apps/editor/docs/custom-html-renderer.md
customHTMLRenderer: {
text(node) {
let content = formulaMdToHtml(node.literal);
content = imagesMdToHtml(content);
let content = formulaMdToHtml(node.literal, true);
content = imagesMdToHtml(content, true);
return {
type: 'html',
content,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
import * as Showdown from 'showdown';
import Editor from '@toast-ui/editor';
import { stripHtml } from 'string-strip-html';

import imagesHtmlToMd from '../plugins/image-upload/image-html-to-md';
import formulaHtmlToMd from '../plugins/formulas/formula-html-to-md';

/**
* Clear DOM node by keeping only its text content.
*
Expand Down Expand Up @@ -74,3 +81,37 @@ export const getExtensionMenuPosition = ({ editorEl, targetX, targetY }) => {
right: menuRight,
};
};

export const generateCustomConverter = el => {
// This is currently the only way of inheriting and adjusting
// default TUI's convertor methods
// see https://github.com/nhn/tui.editor/issues/615
const tmpEditor = new Editor({ el });
const showdown = new Showdown.Converter();
const Convertor = tmpEditor.convertor.constructor;
class CustomConvertor extends Convertor {
toMarkdown(content) {
content = showdown.makeMarkdown(content);
content = imagesHtmlToMd(content);
content = formulaHtmlToMd(content);
// TUI.editor sprinkles in extra `<br>` tags that Kolibri renders literally
// When showdown has already added linebreaks to render these in markdown
// so we just remove these here.
content = content.replaceAll('<br>', '');

// any copy pasted rich text that renders as HTML but does not get converted
// will linger here, so remove it as Kolibri will render it literally also.
content = stripHtml(content).result;
return content;
}
toHTML(content) {
// Kolibri and showdown assume double newlines for a single line break,
// wheras TUI.editor prefers single newline characters.
content = content.replaceAll('\n\n', '\n');
content = super.toHTML(content);
return content;
}
}
tmpEditor.remove();
return CustomConvertor;
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { clearNodeFormat } from '../MarkdownEditor/utils';
/**
* @jest-environment jest-environment-jsdom-sixteen
*/
// Jsdom@^16 is required to test toast UI, as it relies on the Range API.

import { clearNodeFormat, generateCustomConverter } from '../MarkdownEditor/utils';

const htmlStringToFragment = htmlString => {
const template = document.createElement('template');
Expand Down Expand Up @@ -56,3 +61,17 @@ describe('clearNodeFormat', () => {
);
});
});

describe('markdown conversion', () => {
it('converts image tags to markdown without escaping them', () => {
const el = document.createElement('div');
const CustomConvertor = generateCustomConverter(el);
const converter = new CustomConvertor();
const html =
'<span is="markdown-image-field" vce-ready="" contenteditable="false" class="markdown-field-753aa86a-8159-403b-8b1c-d2b8f9504408 markdown-field-34843d46-79b8-40b4-866c-b83dc8916a47" editing="true" markdown="![](${☣ CONTENTSTORAGE}/bc1c5a86e1e46f20a6b4ee2c1bb6d6ff.png =485.453125x394)">![](${☣ CONTENTSTORAGE}/bc1c5a86e1e46f20a6b4ee2c1bb6d6ff.png =485.453125x394)</span>';

expect(converter.toMarkdown(html)).toBe(
'![](${☣ CONTENTSTORAGE}/bc1c5a86e1e46f20a6b4ee2c1bb6d6ff.png =485.453125x394)'
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
*
*/

export default markdown => {
return markdown.replace(/\$\$(.*?)\$\$/g, '<span is="markdown-formula-field">$1</span>');
export default (markdown, editing) => {
const editAttr = editing ? ' editing="true"' : '';
return markdown.replace(
/\$\$(.*?)\$\$/g,
`<span is="markdown-formula-field"${editAttr}>$1</span>`
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ import { IMAGE_REGEX, imageMdToImageFieldHTML } from './index';

// convert markdown images to image editor field custom elements

export default markdown => {
return markdown.replace(IMAGE_REGEX, imageMd => imageMdToImageFieldHTML(imageMd));
export default (markdown, editing) => {
return markdown.replace(IMAGE_REGEX, imageMd => imageMdToImageFieldHTML(imageMd, editing));
};
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ export const paramsToImageMd = ({ src, alt, width, height }) => {
}
};

export const imageMdToImageFieldHTML = imageMd =>
`<span is='markdown-image-field'>${imageMd}</span>`;
export const imageMdToImageFieldHTML = (imageMd, editing) => {
const editAttr = editing ? ' editing="true"' : '';
return `<span is='markdown-image-field'${editAttr}>${imageMd}</span>`;
};
export const paramsToImageFieldHTML = params => imageMdToImageFieldHTML(paramsToImageMd(params));

export default imageUploadExtension;
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ export default VueComponent => {
''
);
}
this.parentNode.removeChild(this);
if (this.parentNode) {
this.parentNode.removeChild(this);
}
});

this.editing = true;

if (!hasLeftwardSpace(this)) {
this.insertAdjacentText('beforebegin', '\xa0');
}
Expand Down

0 comments on commit 88d7008

Please sign in to comment.