Merge pull request #5488 from toonijn/refactor-markdown

Refactor code duplication of markdown renderers
This commit is contained in:
Kevin Bates 2020-10-07 11:33:08 -07:00 committed by GitHub
commit 2ba296039a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 139 additions and 87 deletions

View File

@ -0,0 +1,117 @@
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
define([
'jquery',
'base/js/utils',
'base/js/mathjaxutils',
'base/js/security',
'components/marked/lib/marked',
'codemirror/lib/codemirror',
], function($, utils, mathjaxutils, security, marked, CodeMirror){
"use strict";
marked.setOptions({
gfm : true,
tables: true,
langPrefix: "cm-s-ipython language-",
highlight: function(code, lang, callback) {
if (!lang) {
// no language, no highlight
if (callback) {
callback(null, code);
return;
} else {
return code;
}
}
utils.requireCodeMirrorMode(lang, function (spec) {
var el = document.createElement("div");
var mode = CodeMirror.getMode({}, spec);
if (!mode) {
console.log("No CodeMirror mode: " + lang);
callback(null, code);
return;
}
try {
CodeMirror.runMode(code, spec, el);
callback(null, el.innerHTML);
} catch (err) {
console.log("Failed to highlight " + lang + " code", err);
callback(err, code);
}
}, function (err) {
console.log("No CodeMirror mode: " + lang);
console.log("Require CodeMirror mode error: " + err);
callback(null, code);
});
}
});
var mathjax_init_done = false;
function ensure_mathjax_init() {
if(!mathjax_init_done) {
mathjax_init_done = true;
mathjaxutils.init();
}
}
function render(markdown, options, callback) {
/**
* Find a readme in the current directory. Look for files with
* a name like 'readme.md' (case insensitive) or similar and
* mimetype 'text/markdown'.
*
* @param markdown: the markdown text to parse
* @param options
* Object with parameters:
* with_math: the markdown can contain mathematics
* clean_tables: prevent default inline styles for table cells
* sanitize: remove dangerous html (like <script>)
* @param callback
* A function with two arguments (err, html)
* err: null or the error if there was one
* html: the rendered html string, or if {sanitize: true} was used
* a sanitized jQuery object
*/
options = $.extend({
// Apply mathjax transformation
with_math: false,
// Prevent marked from returning inline styles for table cells
clean_tables: false,
// Apply sanitation, this will return a jQuery object.
sanitize: false,
}, options);
var renderer = new marked.Renderer();
if(options.clean_tables) {
renderer.tablecell = function (content, flags) {
var type = flags.header ? 'th' : 'td';
var style = flags.align == null ? '': ' style="text-align: ' + flags.align + '"';
var start_tag = '<' + type + style + '>';
var end_tag = '</' + type + '>\n';
return start_tag + content + end_tag;
};
}
var text = markdown;
var math = null;
if(options.with_math) {
ensure_mathjax_init();
var text_and_math = mathjaxutils.remove_math(markdown);
text = text_and_math[0];
math = text_and_math[1];
}
marked(text, { renderer: renderer }, function (err, html) {
if(!err) {
if(options.with_math) {
html = mathjaxutils.replace_math(html, math);
}
if(options.sanitize) {
html = $(security.sanitize_html_and_parse(html));
}
}
callback(err, html);
});
}
return {'render': render};
});

View File

@ -32,13 +32,13 @@ define(function(){
// expose modules
jprop('utils','base/js/utils')
jprop('mathjaxutils','base/js/mathjaxutils');
//Jupyter.load_extensions = Jupyter.utils.load_extensions;
//
jprop('security','base/js/security');
jprop('keyboard','base/js/keyboard');
jprop('dialog','base/js/dialog');
jprop('mathjaxutils','notebook/js/mathjaxutils');
//// exposed constructors

View File

@ -12,6 +12,7 @@ define([
'base/js/utils',
'base/js/i18n',
'base/js/dialog',
'base/js/markdown',
'./cell',
'./textcell',
'./codecell',
@ -19,10 +20,9 @@ define([
'services/config',
'services/sessions/session',
'./celltoolbar',
'components/marked/lib/marked',
'codemirror/lib/codemirror',
'codemirror/addon/runmode/runmode',
'./mathjaxutils',
'base/js/mathjaxutils',
'base/js/keyboard',
'./tooltip',
'./celltoolbarpresets/default',
@ -40,6 +40,7 @@ define([
utils,
i18n,
dialog,
markdown,
cellmod,
textcell,
codecell,
@ -47,7 +48,6 @@ define([
configmod,
session,
celltoolbar,
marked,
CodeMirror,
runMode,
mathjaxutils,
@ -116,46 +116,6 @@ define([
mathjaxutils.init();
if (marked) {
marked.setOptions({
gfm : true,
tables: true,
// FIXME: probably want central config for CodeMirror theme when we have js config
langPrefix: "cm-s-ipython language-",
highlight: function(code, lang, callback) {
if (!lang) {
// no language, no highlight
if (callback) {
callback(null, code);
return;
} else {
return code;
}
}
utils.requireCodeMirrorMode(lang, function (spec) {
var el = document.createElement("div");
var mode = CodeMirror.getMode({}, spec);
if (!mode) {
console.log("No CodeMirror mode: " + lang);
callback(null, code);
return;
}
try {
CodeMirror.runMode(code, spec, el);
callback(null, el.innerHTML);
} catch (err) {
console.log("Failed to highlight " + lang + " code", err);
callback(err, code);
}
}, function (err) {
console.log("No CodeMirror mode: " + lang);
console.log("Require CodeMirror mode error: " + err);
callback(null, code);
});
}
});
}
this.element = $(selector);
this.element.scroll();
this.element.data("notebook", this);

View File

@ -7,10 +7,9 @@ define([
'base/js/i18n',
'base/js/security',
'base/js/keyboard',
'base/js/markdown',
'services/config',
'notebook/js/mathjaxutils',
'components/marked/lib/marked',
], function($, utils, i18n, security, keyboard, configmod, mathjaxutils, marked) {
], function($, utils, i18n, security, keyboard, markdown, configmod) {
"use strict";
/**
@ -728,23 +727,13 @@ define([
};
var append_markdown = function(markdown, md, element) {
var append_markdown = function(text, md, element) {
var type = MIME_MARKDOWN;
var toinsert = this.create_output_subarea(md, "output_markdown rendered_html", type);
var text_and_math = mathjaxutils.remove_math(markdown);
var text = text_and_math[0];
var math = text_and_math[1];
// Prevent marked from returning inline styles for table cells
var renderer = new marked.Renderer();
renderer.tablecell = function (content, flags) {
var type = flags.header ? 'th' : 'td';
var style = flags.align == null ? '': ' style="text-align: ' + flags.align + '"';
var start_tag = '<' + type + style + '>';
var end_tag = '</' + type + '>\n';
return start_tag + content + end_tag;
};
marked(text, { renderer: renderer }, function (err, html) {
html = mathjaxutils.replace_math(html, math);
markdown.render(text, {
with_math: true,
clean_tables: true
}, function (err, html) {
toinsert.append(html);
});
dblclick_to_reset_size(toinsert.find('img'));

View File

@ -6,11 +6,9 @@ define([
'base/js/utils',
'base/js/i18n',
'notebook/js/cell',
'base/js/security',
'base/js/markdown',
'services/config',
'notebook/js/mathjaxutils',
'notebook/js/celltoolbar',
'components/marked/lib/marked',
'codemirror/lib/codemirror',
'codemirror/mode/gfm/gfm',
'notebook/js/codemirror-ipythongfm',
@ -20,11 +18,9 @@ define([
utils,
i18n,
cell,
security,
markdown,
configmod,
mathjaxutils,
celltoolbar,
marked,
CodeMirror,
gfm,
ipgfm,
@ -119,7 +115,6 @@ define([
events: this.events}]);
this.cell_type = this.cell_type || 'text';
mathjaxutils = mathjaxutils;
this.rendered = false;
};
@ -301,8 +296,9 @@ define([
// can reference an image in markdown (using []() or a
// HTML <img>)
var text = this.get_text();
marked(text, function (err, html) {
html = $(security.sanitize_html_and_parse(html));
markdown.render(text, {
sanitize: true,
}, function (err, html) {
html.find('img[src^="attachment:"]').each(function (i, h) {
h = $(h);
var key = h.attr('src').replace(/^attachment:/, '');
@ -461,21 +457,11 @@ define([
var text = this.get_text();
var math = null;
if (text === "") { text = this.placeholder; }
var text_and_math = mathjaxutils.remove_math(text);
text = text_and_math[0];
math = text_and_math[1];
// Prevent marked from returning inline styles for table cells
var renderer = new marked.Renderer();
renderer.tablecell = function (content, flags) {
var type = flags.header ? 'th' : 'td';
var style = flags.align == null ? '': ' style="text-align: ' + flags.align + '"';
var start_tag = '<' + type + style + '>';
var end_tag = '</' + type + '>\n';
return start_tag + content + end_tag;
};
marked(text, { renderer: renderer }, function (err, html) {
html = mathjaxutils.replace_math(html, math);
html = $(security.sanitize_html_and_parse(html));
markdown.render(text, {
with_math: true,
clean_tables: true,
sanitize: true,
}, function (err, html) {
// add anchors to headings
html.find(":header").addBack(":header").each(function (i, h) {
h = $(h);

View File

@ -14,7 +14,7 @@ casper.notebook_test(function () {
function mathjax_render_test(input_string, result, message){
casper.thenEvaluate(function (text){
window._test_result = null;
require(['notebook/js/mathjaxutils'],function(mathjaxutils){
require(['base/js/mathjaxutils'],function(mathjaxutils){
window._test_result = mathjaxutils.remove_math(text);
});
}, {text: input_string});