I have struggled with most solutions to convert and embed Jupyter notebooks into WordPress blog posts since I use Plotly as a graphic lib, as well as many LaTeX equations and images. Finally, I had to code my way through. Here is what I did :

#Write the jupyter notebook

Nothing that you don’t know here. If you embed pictures in the notebook though, it would be good to upload them on your WordPress media library, then use the external URL to include them (from your server) in the Markdown cells of Jupyter. Otherwise, you have to put them in the same directory as the notebook and link them with their relative path, it’s less convenent.

#Convert the Jupyter notebook to HTML

We convert with a basic template :

1jupyter nbconvert --to=html --template=basic notebook.ipynb notebook.html

#Allow HTML uploads in WordPress

Many security plugins disable this feature so you have to track the culprit if WordPress says “This filetype is forbidden for security reasons” and add this line in your theme

functions.php or wp-config.php:

1define('ALLOW_UNFILTERED_UPLOADS', true);

Now you can import HTML pages just as any other media type. Be careful, this is a security issue. You need to harden the security of your WordPress install to prevent hackers to login, because they can now embed any kind of deceptive or fraudulent content in your pages.

#Create a shortcode to include the page

This sounds worse than it is : we will just add a small shortcode to allow PHP to include the HTML file directly, without iframes or external renderer. Create a plugin, or add this in your functions.php:

 1// Include HTML
 2function include_shortcode( $atts )
 3{
 4    $atts = shortcode_atts( array('id' => ''), $atts, 'include' );
 5    $uploads = wp_upload_dir();
 6
 7    // Enqueue maths scripts on HTML includes
 8    wp_enqueue_script( 'plotly' );
 9    wp_enqueue_script( 'mathjax' );
10    ob_start();
11    include $uploads["basedir"].'/'.trim($atts['id']);
12    return ob_get_clean();
13}
14
15add_shortcode( 'include', 'include_shortcode' );

From now on, when in a WordPress post editor, to include the HTML notebook file directly from your WordPress uploads directory (//:your-website.com/wp-content/uploads/), you can use the shortcode [include id="2018/05/notebook.html"] or alternatively [include id="notebook.html"] if you didn’t activate the date structure.

Notice that we enqueue the maths scripts here (see the next section) manually, the explanation is on the next section.

#Load Plotly and MathJax

Exported with the basic template, Plotly javascript libraries are not embedded and neither are these from Mathjax. Some plugins do the work for MathJax but, as we have to code for Plotly, let’s do both. Again, in your functions.php or in a plugin, write :

 1wp_register_script( 'plotly',
 2                    "//cdn.plot.ly/plotly-latest.min.js",
 3                    array(), null, true);
 4wp_register_script( 'mathjax',
 5                    "//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML",
 6                    array(), null, true);
 7
 8function load_maths( $content)
 9{
10    if (strpos($content, '$') !== false || strpos($content, '[latex]') !== false)
11        {
12        wp_enqueue_script( 'plotly' );
13        wp_enqueue_script( 'mathjax' );
14    }
15
16    return $content;
17}
18
19add_filter( 'the_content', 'load_maths' );
20
21function my_custom_js() {
22    echo "<script type='text/x-mathjax-config'>
23            MathJax.Hub.Config({
24              tex2jax: {
25                inlineMath: [ ['$','$'], ['[latex]', '[/latex]']],
26                displayMath: [ ['$$','$$'] ],
27                processEscapes: true,
28                processEnvironments: true },
29              // Center justify equations in code and markdown cells. Elsewhere
30              // we use CSS to left justify single line equations in code cells.
31              displayAlign: 'center',
32              'HTML-CSS': {
33                  styles: {'.MathJax_Display': {'margin': 0}},
34                  linebreaks: { automatic: true },
35              extensions: ['handle-floats.js'],
36              availableFonts: ['STIX','TeX'],
37                  preferredFont: 'STIX',
38              webFont:'STIX-Web' } });
39       </script>;";
40}
41
42// Add hook for front-end &lt;head&gt;&lt;/head&gt;
43add_action('wp_head', 'my_custom_js');

The first two lines register the scripts and enables footer loading to improve the page loading speed. The function load_maths  parses the post content and enqueue the scripts only if the LaTeX markups are detected on the page, avoiding unnecessary scripts on other posts (keep the web minimalist). We also need to enqueue them manually on the include shortcode (see section 5.) because the WordPress content filter is not able to parse includes, so the on-demand enqueuing only works on posts containing maths in the post entry.

The rest is a bit of configuration of MathJax to match the built-in configuration of Jupyter and the default WordPress LaTeX plugin shortcode for retro-compatibility. We add it on every page header, which is not necessary but does not really affect performance so we don’t need to add a content filter that will make the server work more for no user benefit. Notice that the LaTeX display math mode using [  and ] won’t be available since it conflicts for some reasons with the brackets enclosing the Jupyter cell numbers, so you will have to use $$ instead.

#A little bit of styling

Now, everything works except there is no styling. So, I just copy/pasted the CSS from Jupyter :

  1/*!
  2*
  3* IPython notebook
  4*
  5*/
  6/* CSS font colors for translated ANSI colors. */
  7.ansibold {
  8font-weight: bold;
  9}
 10/* use dark versions for foreground, to improve visibility */
 11.ansiblack {
 12color: black;
 13}
 14.ansired {
 15color: darkred;
 16}
 17.ansigreen {
 18color: darkgreen;
 19}
 20.ansiyellow {
 21color: #c4a000;
 22}
 23.ansiblue {
 24color: darkblue;
 25}
 26.ansipurple {
 27color: darkviolet;
 28}
 29.ansicyan {
 30color: steelblue;
 31}
 32.ansigray {
 33color: gray;
 34}
 35/* and light for background, for the same reason */
 36.ansibgblack {
 37background-color: black;
 38}
 39.ansibgred {
 40background-color: red;
 41}
 42.ansibggreen {
 43background-color: green;
 44}
 45.ansibgyellow {
 46background-color: yellow;
 47}
 48.ansibgblue {
 49background-color: blue;
 50}
 51.ansibgpurple {
 52background-color: magenta;
 53}
 54.ansibgcyan {
 55background-color: cyan;
 56}
 57.ansibggray {
 58background-color: gray;
 59}
 60div.cell {
 61/* Old browsers */
 62display: -webkit-box;
 63-webkit-box-orient: vertical;
 64-webkit-box-align: stretch;
 65display: -moz-box;
 66-moz-box-orient: vertical;
 67-moz-box-align: stretch;
 68display: box;
 69box-orient: vertical;
 70box-align: stretch;
 71/* Modern browsers */
 72display: flex;
 73flex-direction: column;
 74align-items: stretch;
 75border-radius: 2px;
 76box-sizing: border-box;
 77-moz-box-sizing: border-box;
 78-webkit-box-sizing: border-box;
 79border-width: 1px;
 80border-style: solid;
 81border-color: transparent;
 82width: 100%;
 83padding: 5px;
 84/* This acts as a spacer between cells, that is outside the border */
 85margin: 0px;
 86outline: none;
 87border-left-width: 1px;
 88padding-left: 5px;
 89background: linear-gradient(to right, transparent -40px, transparent 1px, transparent 1px, transparent 100%);
 90}
 91div.cell.jupyter-soft-selected {
 92border-left-color: #90CAF9;
 93border-left-color: #E3F2FD;
 94border-left-width: 1px;
 95padding-left: 5px;
 96border-right-color: #E3F2FD;
 97border-right-width: 1px;
 98background: #E3F2FD;
 99}
100@media print {
101div.cell.jupyter-soft-selected {
102border-color: transparent;
103}
104}
105div.cell.selected {
106border-color: #ababab;
107border-left-width: 0px;
108padding-left: 6px;
109background: linear-gradient(to right, #42A5F5 -40px, #42A5F5 5px, transparent 5px, transparent 100%);
110}
111@media print {
112div.cell.selected {
113border-color: transparent;
114}
115}
116div.cell.selected.jupyter-soft-selected {
117border-left-width: 0;
118padding-left: 6px;
119background: linear-gradient(to right, #42A5F5 -40px, #42A5F5 7px, #E3F2FD 7px, #E3F2FD 100%);
120}
121.edit_mode div.cell.selected {
122border-color: #66BB6A;
123border-left-width: 0px;
124padding-left: 6px;
125background: linear-gradient(to right, #66BB6A -40px, #66BB6A 5px, transparent 5px, transparent 100%);
126}
127@media print {
128.edit_mode div.cell.selected {
129border-color: transparent;
130}
131}
132.prompt {
133/* This needs to be wide enough for 3 digit prompt numbers: In[100]: */
134min-width: 14ex;
135/* This padding is tuned to match the padding on the CodeMirror editor. */
136padding: 0.4em;
137margin: 0px;
138font-family: monospace;
139text-align: right;
140/* This has to match that of the the CodeMirror class line-height below */
141line-height: 1.21429em;
142/* Don't highlight prompt number selection */
143-webkit-touch-callout: none;
144-webkit-user-select: none;
145-khtml-user-select: none;
146-moz-user-select: none;
147-ms-user-select: none;
148user-select: none;
149/* Use default cursor */
150cursor: default;
151}
152@media (max-width: 540px) {
153.prompt {
154text-align: left;
155}
156}
157div.inner_cell {
158min-width: 0;
159/* Old browsers */
160display: -webkit-box;
161-webkit-box-orient: vertical;
162-webkit-box-align: stretch;
163display: -moz-box;
164-moz-box-orient: vertical;
165-moz-box-align: stretch;
166display: box;
167box-orient: vertical;
168box-align: stretch;
169/* Modern browsers */
170display: flex;
171flex-direction: column;
172align-items: stretch;
173/* Old browsers */
174-webkit-box-flex: 1;
175-moz-box-flex: 1;
176box-flex: 1;
177/* Modern browsers */
178flex: 1;
179}
180/* input_area and input_prompt must match in top border and margin for alignment */
181div.input_area {
182border: 1px solid #cfcfcf;
183border-radius: 2px;
184background: #f7f7f7;
185line-height: 1.21429em;
186}
187/* This is needed so that empty prompt areas can collapse to zero height when there
188is no content in the output_subarea and the prompt. The main purpose of this is
189to make sure that empty JavaScript output_subareas have no height. */
190div.prompt:empty {
191padding-top: 0;
192padding-bottom: 0;
193}
194div.unrecognized_cell {
195padding: 5px 5px 5px 0px;
196/* Old browsers */
197display: -webkit-box;
198-webkit-box-orient: horizontal;
199-webkit-box-align: stretch;
200display: -moz-box;
201-moz-box-orient: horizontal;
202-moz-box-align: stretch;
203display: box;
204box-orient: horizontal;
205box-align: stretch;
206/* Modern browsers */
207display: flex;
208flex-direction: row;
209align-items: stretch;
210}
211div.unrecognized_cell .inner_cell {
212border-radius: 2px;
213padding: 5px;
214font-weight: bold;
215color: red;
216border: 1px solid #cfcfcf;
217background: #eaeaea;
218}
219div.unrecognized_cell .inner_cell a {
220color: inherit;
221text-decoration: none;
222}
223div.unrecognized_cell .inner_cell a:hover {
224color: inherit;
225text-decoration: none;
226}
227@media (max-width: 540px) {
228div.unrecognized_cell &gt; div.prompt {
229display: none;
230}
231}
232div.code_cell {
233/* avoid page breaking on code cells when printing */
234}
235@media print {
236div.code_cell {
237page-break-inside: avoid;
238}
239}
240/* any special styling for code cells that are currently running goes here */
241div.input {
242page-break-inside: avoid;
243/* Old browsers */
244display: -webkit-box;
245-webkit-box-orient: horizontal;
246-webkit-box-align: stretch;
247display: -moz-box;
248-moz-box-orient: horizontal;
249-moz-box-align: stretch;
250display: box;
251box-orient: horizontal;
252box-align: stretch;
253/* Modern browsers */
254display: flex;
255flex-direction: row;
256align-items: stretch;
257}
258@media (max-width: 540px) {
259div.input {
260/* Old browsers */
261display: -webkit-box;
262-webkit-box-orient: vertical;
263-webkit-box-align: stretch;
264display: -moz-box;
265-moz-box-orient: vertical;
266-moz-box-align: stretch;
267display: box;
268box-orient: vertical;
269box-align: stretch;
270/* Modern browsers */
271display: flex;
272flex-direction: column;
273align-items: stretch;
274}
275}
276/* input_area and input_prompt must match in top border and margin for alignment */
277div.input_prompt {
278color: #303F9F;
279border-top: 1px solid transparent;
280}
281div.input_area &gt; div.highlight {
282margin: 0.4em;
283border: none;
284padding: 0px;
285background-color: transparent;
286}
287div.input_area &gt; div.highlight &gt; pre {
288margin: 0px;
289border: none;
290padding: 0px;
291background-color: transparent;
292}
293/* The following gets added to theif it is detected that the user has a* monospace font with inconsistent normal/bold/italic height. See* notebookmain.js. Such fonts will have keywords vertically offset with* respect to the rest of the text. The user should select a better font.* See: https://github.com/ipython/ipython/issues/1503** .CodeMirror span {* vertical-align: bottom;* }*/.CodeMirror {line-height: 1.21429em;/* Changed from 1em to our global default */font-size: 14px;height: auto;/* Changed to auto to autogrow */background: none;/* Changed from white to allow our bg to show through */}.CodeMirror-scroll {/* The CodeMirror docs are a bit fuzzy on if overflow-y should be hidden or visible.*//* We have found that if it is visible, vertical scrollbars appear with font size changes.*/overflow-y: hidden;overflow-x: auto;}.CodeMirror-lines {/* In CM2, this used to be 0.4em, but in CM3 it went to 4px. We need the em value because *//* we have set a different line-height and want this to scale with that. */padding: 0.4em;}.CodeMirror-linenumber {padding: 0 8px 0 4px;}.CodeMirror-gutters {border-bottom-left-radius: 2px;border-top-left-radius: 2px;}.CodeMirror pre {/* In CM3 this went to 4px from 0 in CM2. We need the 0 value because of how we size *//* .CodeMirror-lines */padding: 0;border: 0;border-radius: 0;}/*
294
295Original style from softwaremaniacs.org (c) Ivan Sagalaev &lt;Maniac@SoftwareManiacs.Org&gt;
296Adapted from GitHub theme
297
298*/
299.highlight-base {
300color: #000;
301}
302.highlight-variable {
303color: #000;
304}
305.highlight-variable-2 {
306color: #1a1a1a;
307}
308.highlight-variable-3 {
309color: #333333;
310}
311.highlight-string {
312color: #BA2121;
313}
314.highlight-comment {
315color: #408080;
316font-style: italic;
317}
318.highlight-number {
319color: #080;
320}
321.highlight-atom {
322color: #88F;
323}
324.highlight-keyword {
325color: #008000;
326font-weight: bold;
327}
328.highlight-builtin {
329color: #008000;
330}
331.highlight-error {
332color: #f00;
333}
334.highlight-operator {
335color: #AA22FF;
336font-weight: bold;
337}
338.highlight-meta {
339color: #AA22FF;
340}
341/* previously not defined, copying from default codemirror */
342.highlight-def {
343color: #00f;
344}
345.highlight-string-2 {
346color: #f50;
347}
348.highlight-qualifier {
349color: #555;
350}
351.highlight-bracket {
352color: #997;
353}
354.highlight-tag {
355color: #170;
356}
357.highlight-attribute {
358color: #00c;
359}
360.highlight-header {
361color: blue;
362}
363.highlight-quote {
364color: #090;
365}
366.highlight-link {
367color: #00c;
368}
369/* apply the same style to codemirror */
370.cm-s-ipython span.cm-keyword {
371color: #008000;
372font-weight: bold;
373}
374.cm-s-ipython span.cm-atom {
375color: #88F;
376}
377.cm-s-ipython span.cm-number {
378color: #080;
379}
380.cm-s-ipython span.cm-def {
381color: #00f;
382}
383.cm-s-ipython span.cm-variable {
384color: #000;
385}
386.cm-s-ipython span.cm-operator {
387color: #AA22FF;
388font-weight: bold;
389}
390.cm-s-ipython span.cm-variable-2 {
391color: #1a1a1a;
392}
393.cm-s-ipython span.cm-variable-3 {
394color: #333333;
395}
396.cm-s-ipython span.cm-comment {
397color: #408080;
398font-style: italic;
399}
400.cm-s-ipython span.cm-string {
401color: #BA2121;
402}
403.cm-s-ipython span.cm-string-2 {
404color: #f50;
405}
406.cm-s-ipython span.cm-meta {
407color: #AA22FF;
408}
409.cm-s-ipython span.cm-qualifier {
410color: #555;
411}
412.cm-s-ipython span.cm-builtin {
413color: #008000;
414}
415.cm-s-ipython span.cm-bracket {
416color: #997;
417}
418.cm-s-ipython span.cm-tag {
419color: #170;
420}
421.cm-s-ipython span.cm-attribute {
422color: #00c;
423}
424.cm-s-ipython span.cm-header {
425color: blue;
426}
427.cm-s-ipython span.cm-quote {
428color: #090;
429}
430.cm-s-ipython span.cm-link {
431color: #00c;
432}
433.cm-s-ipython span.cm-error {
434color: #f00;
435}
436.cm-s-ipython span.cm-tab {
437background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);
438background-position: right;
439background-repeat: no-repeat;
440}
441div.output_wrapper {
442/* this position must be relative to enable descendents to be absolute within it */
443position: relative;
444/* Old browsers */
445display: -webkit-box;
446-webkit-box-orient: vertical;
447-webkit-box-align: stretch;
448display: -moz-box;
449-moz-box-orient: vertical;
450-moz-box-align: stretch;
451display: box;
452box-orient: vertical;
453box-align: stretch;
454/* Modern browsers */
455display: flex;
456flex-direction: column;
457align-items: stretch;
458z-index: 1;
459}
460/* class for the output area when it should be height-limited */
461div.output_scroll {
462/* ideally, this would be max-height, but FF barfs all over that */
463height: 24em;
464/* FF needs this *and the wrapper* to specify full width, or it will shrinkwrap */
465width: 100%;
466overflow: auto;
467border-radius: 2px;
468-webkit-box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.8);
469box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.8);
470display: block;
471}
472/* output div while it is collapsed */
473div.output_collapsed {
474margin: 0px;
475padding: 0px;
476/* Old browsers */
477display: -webkit-box;
478-webkit-box-orient: vertical;
479-webkit-box-align: stretch;
480display: -moz-box;
481-moz-box-orient: vertical;
482-moz-box-align: stretch;
483display: box;
484box-orient: vertical;
485box-align: stretch;
486/* Modern browsers */
487display: flex;
488flex-direction: column;
489align-items: stretch;
490}
491div.out_prompt_overlay {
492height: 100%;
493padding: 0px 0.4em;
494position: absolute;
495border-radius: 2px;
496}
497div.out_prompt_overlay:hover {
498/* use inner shadow to get border that is computed the same on WebKit/FF */
499-webkit-box-shadow: inset 0 0 1px #000;
500box-shadow: inset 0 0 1px #000;
501background: rgba(240, 240, 240, 0.5);
502}
503div.output_prompt {
504color: #D84315;
505}
506/* This class is the outer container of all output sections. */
507div.output_area {
508padding: 0px;
509page-break-inside: avoid;
510/* Old browsers */
511display: -webkit-box;
512-webkit-box-orient: horizontal;
513-webkit-box-align: stretch;
514display: -moz-box;
515-moz-box-orient: horizontal;
516-moz-box-align: stretch;
517display: box;
518box-orient: horizontal;
519box-align: stretch;
520/* Modern browsers */
521display: flex;
522flex-direction: row;
523align-items: stretch;
524}
525div.output_area .MathJax_Display {
526text-align: left !important;
527}
528div.output_area .rendered_html table {
529margin-left: 0;
530margin-right: 0;
531}
532div.output_area .rendered_html img {
533margin-left: 0;
534margin-right: 0;
535}
536div.output_area img,
537div.output_area svg {
538max-width: 100%;
539height: auto;
540}
541div.output_area img.unconfined,
542div.output_area svg.unconfined {
543max-width: none;
544}
545/* This is needed to protect the pre formating from global settings such
546as that of bootstrap */
547.output {
548/* Old browsers */
549display: -webkit-box;
550-webkit-box-orient: vertical;
551-webkit-box-align: stretch;
552display: -moz-box;
553-moz-box-orient: vertical;
554-moz-box-align: stretch;
555display: box;
556box-orient: vertical;
557box-align: stretch;
558/* Modern browsers */
559display: flex;
560flex-direction: column;
561align-items: stretch;
562}
563@media (max-width: 540px) {
564div.output_area {
565/* Old browsers */
566display: -webkit-box;
567-webkit-box-orient: vertical;
568-webkit-box-align: stretch;
569display: -moz-box;
570-moz-box-orient: vertical;
571-moz-box-align: stretch;
572display: box;
573box-orient: vertical;
574box-align: stretch;
575/* Modern browsers */
576display: flex;
577flex-direction: column;
578align-items: stretch;
579}
580}
581div.output_area pre {
582margin: 0;
583padding: 0;
584border: 0;
585vertical-align: baseline;
586color: black;
587background-color: transparent;
588border-radius: 0;
589}
590/* This class is for the output subarea inside the output_area and after
591the prompt div. */
592div.output_subarea {
593overflow-x: auto;
594padding: 0.4em;
595/* Old browsers */
596-webkit-box-flex: 1;
597-moz-box-flex: 1;
598box-flex: 1;
599/* Modern browsers */
600flex: 1;
601max-width: calc(100% - 14ex);
602}
603div.output_scroll div.output_subarea {
604overflow-x: visible;
605}
606/* The rest of the output_* classes are for special styling of the different
607output types */
608/* all text output has this class: */
609div.output_text {
610text-align: left;
611color: #000;
612/* This has to match that of the the CodeMirror class line-height below */
613line-height: 1.21429em;
614}
615/* stdout/stderr are 'text' as well as 'stream', but execute_result/error are *not* streams */
616div.output_stderr {
617background: #fdd;
618/* very light red background for stderr */
619}
620div.output_latex {
621text-align: left;
622}
623/* Empty output_javascript divs should have no height */
624div.output_javascript:empty {
625padding: 0;
626}
627.js-error {
628color: darkred;
629}
630/* raw_input styles */
631div.raw_input_container {
632line-height: 1.21429em;
633padding-top: 5px;
634}
635pre.raw_input_prompt {
636/* nothing needed here. */
637}
638input.raw_input {
639font-family: monospace;
640font-size: inherit;
641color: inherit;
642width: auto;
643/* make sure input baseline aligns with prompt */
644vertical-align: baseline;
645/* padding + margin = 0.5em between prompt and cursor */
646padding: 0em 0.25em;
647margin: 0em 0.25em;
648}
649input.raw_input:focus {
650box-shadow: none;
651}
652p.p-space {
653margin-bottom: 10px;
654}
655div.output_unrecognized {
656padding: 5px;
657font-weight: bold;
658color: red;
659}
660div.output_unrecognized a {
661color: inherit;
662text-decoration: none;
663}
664div.output_unrecognized a:hover {
665color: inherit;
666text-decoration: none;
667}
668.rendered_html pre {
669margin: 1em 2em;
670}
671.rendered_html pre,
672.rendered_html code {
673border: 0;
674background-color: #fff;
675color: #000;
676font-size: 100%;
677padding: 0px;
678}
679.rendered_html blockquote {
680margin: 1em 2em;
681}
682.rendered_html table {
683margin-left: auto;
684margin-right: auto;
685border: 1px solid black;
686border-collapse: collapse;
687}
688.rendered_html tr,
689.rendered_html th,
690.rendered_html td {
691border: 1px solid black;
692border-collapse: collapse;
693margin: 1em 2em;
694}
695.rendered_html td,
696.rendered_html th {
697text-align: left;
698vertical-align: middle;
699padding: 4px;
700}
701.rendered_html th {
702font-weight: bold;
703}
704.rendered_html * + table {
705margin-top: 1em;
706}
707.rendered_html p {
708text-align: left;
709}
710.rendered_html * + p {
711margin-top: 1em;
712}
713.rendered_html img {
714display: block;
715margin-left: auto;
716margin-right: auto;
717}
718.rendered_html * + img {
719margin-top: 1em;
720}
721.rendered_html img,
722.rendered_html svg {
723max-width: 100%;
724height: auto;
725}
726.rendered_html img.unconfined,
727.rendered_html svg.unconfined {
728max-width: none;
729}
730div.text_cell {
731/* Old browsers */
732display: -webkit-box;
733-webkit-box-orient: horizontal;
734-webkit-box-align: stretch;
735display: -moz-box;
736-moz-box-orient: horizontal;
737-moz-box-align: stretch;
738display: box;
739box-orient: horizontal;
740box-align: stretch;
741/* Modern browsers */
742display: flex;
743flex-direction: row;
744align-items: stretch;
745}
746@media (max-width: 540px) {
747div.text_cell &gt; div.prompt {
748display: none;
749}
750}
751div.text_cell_render {
752/*font-family: "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;*/
753outline: none;
754resize: none;
755width: inherit;
756border-style: none;
757padding: 0.5em 0.5em 0.5em 0.4em;
758color: #000;
759box-sizing: border-box;
760-moz-box-sizing: border-box;
761-webkit-box-sizing: border-box;
762}
763a.anchor-link:link {
764text-decoration: none;
765padding: 0px 20px;
766visibility: hidden;
767}
768h1:hover .anchor-link,
769h2:hover .anchor-link,
770h3:hover .anchor-link,
771h4:hover .anchor-link,
772h5:hover .anchor-link,
773h6:hover .anchor-link {
774visibility: visible;
775}
776.text_cell.rendered .input_area {
777display: none;
778}
779.text_cell.rendered .rendered_html {
780overflow-x: auto;
781overflow-y: hidden;
782}
783.text_cell.unrendered .text_cell_render {
784display: none;
785}
786.cm-header-1,
787.cm-header-2,
788.cm-header-3,
789.cm-header-4,
790.cm-header-5,
791.cm-header-6 {
792font-weight: bold;
793font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
794}
795.cm-header-1 {
796font-size: 185.7%;
797}
798.cm-header-2 {
799font-size: 157.1%;
800}
801.cm-header-3 {
802font-size: 128.6%;
803}
804.cm-header-4 {
805font-size: 110%;
806}
807.cm-header-5 {
808font-size: 100%;
809font-style: italic;
810}
811.cm-header-6 {
812font-size: 100%;
813font-style: italic;
814}
815.highlight .hll { background-color: #ffffcc }
816.highlight { background: #f8f8f8; }
817.highlight .c { color: #408080; font-style: italic } /* Comment */
818.highlight .err { border: 1px solid #FF0000 } /* Error */
819.highlight .k { color: #008000; font-weight: bold } /* Keyword */
820.highlight .o { color: #666666 } /* Operator */
821.highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
822.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
823.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
824.highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
825.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
826.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
827.highlight .gd { color: #A00000 } /* Generic.Deleted */
828.highlight .ge { font-style: italic } /* Generic.Emph */
829.highlight .gr { color: #FF0000 } /* Generic.Error */
830.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
831.highlight .gi { color: #00A000 } /* Generic.Inserted */
832.highlight .go { color: #888888 } /* Generic.Output */
833.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
834.highlight .gs { font-weight: bold } /* Generic.Strong */
835.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
836.highlight .gt { color: #0044DD } /* Generic.Traceback */
837.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
838.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
839.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
840.highlight .kp { color: #008000 } /* Keyword.Pseudo */
841.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
842.highlight .kt { color: #B00040 } /* Keyword.Type */
843.highlight .m { color: #666666 } /* Literal.Number */
844.highlight .s { color: #BA2121 } /* Literal.String */
845.highlight .na { color: #7D9029 } /* Name.Attribute */
846.highlight .nb { color: #008000 } /* Name.Builtin */
847.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
848.highlight .no { color: #880000 } /* Name.Constant */
849.highlight .nd { color: #AA22FF } /* Name.Decorator */
850.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
851.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
852.highlight .nf { color: #0000FF } /* Name.Function */
853.highlight .nl { color: #A0A000 } /* Name.Label */
854.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
855.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
856.highlight .nv { color: #19177C } /* Name.Variable */
857.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
858.highlight .w { color: #bbbbbb } /* Text.Whitespace */
859.highlight .mb { color: #666666 } /* Literal.Number.Bin */
860.highlight .mf { color: #666666 } /* Literal.Number.Float */
861.highlight .mh { color: #666666 } /* Literal.Number.Hex */
862.highlight .mi { color: #666666 } /* Literal.Number.Integer */
863.highlight .mo { color: #666666 } /* Literal.Number.Oct */
864.highlight .sa { color: #BA2121 } /* Literal.String.Affix */
865.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
866.highlight .sc { color: #BA2121 } /* Literal.String.Char */
867.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */
868.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
869.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
870.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
871.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
872.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
873.highlight .sx { color: #008000 } /* Literal.String.Other */
874.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
875.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
876.highlight .ss { color: #19177C } /* Literal.String.Symbol */
877.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
878.highlight .fm { color: #0000FF } /* Name.Function.Magic */
879.highlight .vc { color: #19177C } /* Name.Variable.Class */
880.highlight .vg { color: #19177C } /* Name.Variable.Global */
881.highlight .vi { color: #19177C } /* Name.Variable.Instance */
882.highlight .vm { color: #19177C } /* Name.Variable.Magic */
883.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */

Et voilà ! See the result on my first post… Well, this is sort of depressing… to end up with such a short post whereas I spent 4 hours making everything work.

Edit of 25th, March 2021 : I actually made a WordPress plugin to include maths, Plotly, Bokeh and Jupyter notebooks in WordPress posts in a seamless way : WP Scholar

Edit of 30th, January 2024 : I finally moved this site (and others) from WordPress to Hugo  because it is simpler, cleaner and a lot easier on server’s and client’s power than WordPress, and I’m tired of having to work around the design mistakes of WordPress.