WP Scholar provides a clutter-free, direct and fast typing experience for the heavy-duty writers who type a lot every day (technical writers, engineers, analysts, journalists, researchers, scientists, etc.) and are stuck with WordPress as a CMS. It supports equations, footnotes, table of contents, code highlighting, charts drawing, interactive plots and Jupyter notebooks includes, through a direct access to the Markdown and LaTeX code. Then, it refines the typography by converting arrows, quotes and fractions to proper HTML entities, and inserts unbreakable and thin spaces where they belong.

If you are a technical writer, you may feel WordPress Gutenberg editor is going backwards, in an MS Office direction : giving an overwhelming set of formatting options while making actual typing and content production really hard. Those blocks ask you to think about the layout even before having typed the content, and make you travel constantly between mouse and keyboard. More than a hassle, they put pain on your wrists and elbows.

The truth is, WordPress is turning into a better place for marketers, but is becoming a nightmare for anyone who produces content rather than cute formatting. While most technical writers have now turned toward static content generators (Hugo, Jekyll, etc.), and researchers keep writing fixed-width PDF papers (2021 much…), WP Scholar tries to make WordPress great again for you, writer.

Note

While WordPress Gutenberg editor allows you to write Markdown, it will process it on-the-fly and save the post content as processed HTML. If you want to edit it again in the future, you will have to read HTML.

WP Scholar parses posts saved in Markdown syntax, meaning future edits will be done on Markdown as well. The limitation is you need to never open those Mardown posts in Gutenberg or TinyMCE visual editor. Alternatively, WP Scholar allows you to include plain .md text files

Description

Features

  1. Newbie features :
    • adds support for extended Github-flavored Markdown  formatting in posts, pages and comments,
    • adds support for footnotes and inline hover cards for their content,
    • adds table of contents in posts and in sidebars with a widget,
    • adds internal anchors and backlinks to headers, for quick intra-page navigation and permanent linking to inner sections,
    • enforces correct typographic rules for the current language, such as unbreakable and thin spaces where they belong, fractions, quotes, etc.
  2. Intermediate features :
    • adds support for Mermaid  graphs, allowing to quickly plot charts from simplified code,
    • removes WordPress markup filtering in posts and pages, allowing scripts and advanced HTML,
    • removes media library uploads limitations, allowing SVG, HTML and JSON uploads to media library, provides a shortcode to include them in posts and pages,
    • adds support for Plotly  and Bokeh  interactive and self-hosted graphs, for beautiful data visualisations and analytics.
  3. Expert features :
    • adds support for LaTeX equations  in posts, comments and pages, with environments, references and equations numbering,
    • adds syntax highlighting  on code blocks declared with a programming language (245 languages supported),
    • imports Jupyter notebooks  and include them in pages (you can even write full posts with graphs and code in Jupyter then include them).

Compatibility

  1. Supports Typora  Markdown editor output and 90 % of its features, so you can type your posts off-line in Typora editor, and copy-paste the Markdown code,
  2. Supports TinyMCE (classic WordPress editor) and Gutenberg in their code editor versions, plus Gutenberg HTML block. The visual editors are not fully supported (see why),
  3. Supports Jetpack LaTeX syntax as well as [latex] shortcodes,
  4. Supports [toc] shortcode that is also used by many table of content plugins (however, they cannot be enabled at the same time),
  5. Supports all shortcodes from WordPress and other plugins,
  6. Saves posts as true Markdown code, so they can be edited again as Markdown (most editors convert Markdown to HTML in browser and save HTML).

Performance

  1. WP Scholar only loads a minified 1.6 kB CSS file on every page of the website.
  2. The ressources to load (CSS and JS) are lazy-loaded on a page-wise basis, so only the necessary ones are loaded and your home page doesn’t get bloated with useless resources.
  3. Javascript files (Mathjax, Prism, Mermaid, Plotly, Bokeh, etc.) are loaded from cdnjs.cloudflare.com. This ensures fast loading and proper caching for any user.
  4. WP Scholar is compatible with caching plugins and tested with WP Rocket  (see the configuration help).
  5. Most scripts are loaded in footer and can be loaded asynchronously for better loading time.
  6. Since WP Scholar parses Markdown at page-rendering time, this can prove heavy and slow. A caching plugin  is strongly recommended.

How it works

The whole thing is designed to be as lightweight and simple as possible. There is no configuration page, just enable and start writing Markdown or LaTeX. Everything is detected automatically, and options are defined in the text editor through HTML comments tags.

Philosophy

No obstruction. When you put your ideas into text, you want nothing to sit between you and the text, you just want the text to flow. Think about writing in your notebook… Unfortunately, Microsoft Word and WordPress Gutenberg force you to think about the layout even before starting to actually type, because they take the problem the wrong way : you need to start creating layout blocks first, then only later fill them with content. Form doesn’t adapt to content anymore, it is the other way around.

To do so, they heavily rely on mouse actions to define and edit content blocks and their properties, while actual typing happens on keyboard. So they make you travel constantly between mouse and keyboard, which makes you lose time and put your wrist and elbow at risk of musculoskeletal and nervous strain, if you repeat it daily and for long periods of time.

The best-flowing typing experience is one where you don’t have to care about layout, while typing if at all, don’t have to put your hands off the keyboard and don’t need right-click monkey business. Which means typing text as formatted code with some markup (LaTeX, HTML, XML and the likes). But markup may be a huge overhead because it is hard to read, cumbersome to type, and slow to learn.

For this reason, Markdown  was invented in 2004 to deal with formatting in the less-cumbersome way as possible. It is fast to learn, fast to use, and gets later interpreted as HTML, which allows systematic styling through templates and style-sheet. It can also be used in conjunction with HTML for cases where advanced layouts are required.

So WP Scholar takes all the benefits of Markdown, extends them with LaTeX for equations, but also adds the usual WordPress shortcodes on top, for the more advanced features like media galleries. You get all the benefits of WordPress with a simple text editor and most of the bloat out of your sight.

#Suggested workflow

#Companion editor

This plugin is designed to be compatible with Typora , a cross-platform and distraction-free Markdown editor that lets you type maths, graphs, text and tables in a very efficient way, then export to all the usual formats, on Linux, Mac OS and Windows. Type in Typora, copy-paste the Markdown code to a WordPress post or import the .md file to WordPress media library and include it, and be done with it. WP Scholar will be able to translate Typora’s Markdown, equations and graphs to HTML. Typora is, so far, the best implementation of a non-obstructive typing workflow.

This workflow has several advantages :

  • Typora provides a no-distraction WYSIWYG interface, supporting even tables, maths and diagrams rendering,
  • you keep a local copy of your articles for safety and for later export to LaTeX, PDF, ePub, HTML, etc.
  • you can work offline, while commuting, travelling, or simply to cut internet distractions, with no fear of losing your work,
  • WordPress fancy content editors tend to be more and more bloated, heavy and slow as time goes by, inducing lags and CPU overuse. A local lightweight editor is all you need.

WP Scholar supports 95 % of Typora’s features, like its extended Markdown syntax, maths rendering and Mermaid graphs. Flowcharts and Sequence charts are not supported because they duplicate Mermaid’s features for little benefit.


#Dynamic workflow

You can type your posts in Markdown straight from WordPress post editor, using the code editor. Be careful, however, because both TinyMCE (classic editor) or Gutenberg (new editor) used in WYSIWYG mode convert Markdown syntax directly to HTML at typing time, in your browser. So they don’t save real Markdown. Similarly, when you switch back from their code editor to their WYSIWYG mode, they might encode important characters things into HTML and break the Markdown syntax.

In a nutshell, while TinyMCE and Gutenberg let you type some Markdown (just the simple stuff like bold, headings and italics), when you edit those posts later, what you will edit will be HTML. So you get 2 options to retain Markdown untouched :

  • with TinyMCE, always use the code editor and never go back to the visual one, especially if you use maths equations.
  • with Gutenberg, either use the code editor or an HTML block.

Notice if you edit posts first in TinyMCE code editor and later import them in Gutenberg, some characters may by converted to HTML entities in the process, which may break syntax of LaTeX and Mermaid code. For this reason, it is better to keep editing older posts in the same editor they were primarily created, or force your posts to be converted to pure HTML using HTML blocks.

#Static workflow

You can type your posts in any Markdown editor you like, online or offline, then import the Markdown file to your media library and include it in your post (see how to include external Markdown in posts).

To edit those posts later, you can connect from your computer to your web server, through FTP, mount the remote server as a local storage, and keep editing the .md files from within your local editor. You absolutely need to name the file with a .md extension so the Markdown syntax is parsed (otherwise, any other file type is not parsed).

Notice this will not store the content of your post in WordPress database, which will disable the following WordPress features :

  • internal search in posts and pages content,
  • automatic excerpt generation,
  • SEO analyse of content from third-party plugins,
  • any further content extraction/analyse.

#Warnings

#Security

This plugin enables uploading SVG, HTML, JSON, Markdown (.md) and Jupyter notebook files (.ipynb) to WordPress media library and disables the uploaded checks on such files. These files can be used to embed malicious, unfiltered, scripts, which is the reason WordPress disallows them in the first place. Unfortunately, we don’t have a choice if we want to include local Plotly/Bokeh graphs and Jupyter notebooks as pre-rendered HTML files. A security hardening plugin, like Sucuri, Wordfence, or SecuPress, is strongly advised, with double-factor authentication and malware scanners.

This plugin also disables the default WordPress XSS detection and markup removal/sanitization in posts and pages (they are still applied on comments), because it conflicts with Markdown syntax and prevent us from using legitimate scripts in-page. It means any author on your blog can add Javascript and unfiltered markup in posts, that is possibly malicious code in posts. This is a double-edged sword : more power and more responsibilities. You need to trust your blog authors, editors, and administrators to use this plugin.

#Performance

WP Scholar keeps your posts saved as Markdown in the posts database, which means they need to be parsed and interpreted before the front-end page is rendered and served to an user. To avoid re-rendering them every time a new reader comes on your page, it is advised to use caching plugins such as W3 Total Cache, Super Cache or WP Rocket (there are plenty).

WP Scholar loads only one CSS file (1.6 kB) and one JS file (2.3 kB) per page. Both are minified already. All other CSS and JS are loaded on-demand, only on the pages where they are needed. The internal javascript of WP Scholar uses plain javascript (no jQuery or other version-tied library dependency) and will work with any web browser that is not Internet Explorer 8 and more recent than 2012 or so.

Maths equations, Mermaid charts, Plotly and Bokeh interactive graphs are rendered client-side, in the visitor’s browser, by javascript libraries which produce SVG images. This guarantees that fonts and lines are properly scaled to the viewport width and are free from aliasing or blurring, since they use the real screen resolution. However, this puts a computational cost on the visitor’s device and might take some time to render on older devices. Also, SVG is supported only by fairly recent web browsers (newer than 2014).

#Caveats

#Special symbols

WP Scholar expects dollar symbols $ to enclose maths equations, like $x + y = z$ or $ x + y = z $. If you use $ as a price monetary unit only once in a paragraph, you are going to be fine. But if you have at least 2 dollar signs in the same paragraph, WP Scholar will interprete it as an equation enclosing and try to format it as maths. To prevent that, you need to escape the dollar sign with a backslash, like \$.

#Custom post types

To avoid conflicts and performance penalty with custom post types and special pages like cart/checkout pages of web shop plugins, Markdown is parsed only on regular WordPress posts and pages, comments, posts archives, home page and excerpts.

To force Markdown parsing on any post type that uses the_content hook , put somewhere in the page <!-- force-markdown -->.

#Newbie Documentation

#Markdown syntax

The overall logic of Markdown is to replace HTML markup by special characters (brackets, backticks, stars, etc.), spaces and line breaks. Therefore, spaces and line breaks become parts of the syntax and bad spacing (too many or too few) will result in bad parsing.

The Markdown parser is the library PHP Markdown 1.9.0  that has been extended for our needs and for Github Flavored syntax. Here is the complete list of features as part of the Markdown extended syntax : (bold : standard Markdown, italic : extended Markdown, bold italic : WP Scholar addenda)

  • page elements :
    • footnotes,
    • table of content,
    • abbreviations,
  • block elements :
    • paragraphs and line breaks,
    • *headers (with anchors, see below),
    • blockquotes,
    • lists and nested lists,
    • code blocks (with syntax highlighting, see below),
    • horizontal rules,
    • equation blocks (see “Maths” below),
    • tables,
    • ordered lists,
    • definition lists
    • id and class attributes
  • span elements :
    • bold,
    • italics,
    • links and auto links from url,
    • images,
    • code span,
    • striked text,
    • exponents,
    • indices

Documentations :

1* ~~Striked~~
2* 2^nd^
3* H~2~O

renders as :

  • Striked
  • 2 nd
  • H2 O

WP Scholar also changes inline images parsing a bit, by automatically linking images to themselves, with a rel="lightbox" attribute. This allows most themes and plugins that use a Javascript lightbox to open images full-screen. So, ![alt text](https://mysite.com/image.jpeg "title text") becomes :

1<a href="https://mysite.com/image.jpeg" rel="lightbox" class="lightbox" data-rel="iLightbox" data-title="title text" data-caption="alt text">
2  <img alt="alt text" src="https://mysite.com/image.jpeg" title="title text">
3</a>

#Footnotes

The footnotes are part of the Markdown Extra syntax, extending Markdown, but WP Scholar gives them a hover card. Input [^1] in the text where you want the footnote marker to appear, like here[1], then later in the text (where it is convenient), define the footnote text like [^1]: The text with exactly one space after : and with only one definition by line. Footnotes definitions are added at the end of the text.

The footnotes numbers don’t have to follow in increasing order in the text, but only have to be unique and be linked to the same number among definitions. The parser will reorder them and sort them in increasing order, as they appear in the text. Footnotes can be called several times, but have to be defined only once.

Hover cards appear when the mouse goes over the footnote link and display the content of the footnote without having to scroll to the footnotes.

#Internal linking and TOC

#Table of contents

Add a [toc depth=3 title="Contents"] shortcode in the text to make a table of content appear at this place. By default, a TOC shows all levels of heading and doesn’t add a title. The TOC are included in a <details> HTML5 markup which should notify search engines properly about its content.

Optional arguments :

depth

How many levels of headings should go in the TOC list, starting from the first heading in the page.

title

The title to set for the TOC box.

Notice TOCs should work also for external HTML embedded in post pages. A widget is provided to display the TOC in a sidebar, in place or in addition of the post TOC. The options are the same.

#Mixing HTML, Markdown and WorPress shortcodes

Pages can contain a mix of HTML and Markdown syntax, however no Markdown will be parsed inside block-level HTML elements by default. This can be used to deal with corner cases, for example with code blocks (in case the inside of Markdown code blocks is still parsed). If you really need to use HTML divisions and want Markdown to be parsed inside, for example to apply CSS classes and styling, you can change that behavior by adding a markdown=1 property :

1<div class="your-class" markdown="1">
2  **Some** text with *emphasis*.
3</div>

More details… 

WP Scholar keeps the content of posts as originally written (Markdown + PHP) in the database. This ensures they can be later edited as Markdown again.

However, many Markdown plugins (Jetpack) and editors (TinyMCE and Gutenberg) support Markdown for typing, but convert to HTML at some point (possibly with their own CSS selectors which will mess-up styling for us) and save posts as HTML in the database. This will make it impossible to edit posts as Markdown again.

WordPress usual shortcodes are rendered after the Markdown parsing is performed, so you can combine shortcodes and Markdown with no fear of clashes. The Markdown parser will treat WordPress shortcodes as standard text, so mind your paragraphs breaks between shortcodes and content (best policy is generaly to avoid empty lines between shortcodes and content to avoid breaking them apart in different paragraphs in the Markdown parsing).

 1`#mermaid-1675339841449 {font-family:sans-serif;font-size:14px;fill:#000000;}#mermaid-1675339841449 .error-icon{fill:#552222;}#mermaid-1675339841449 .error-text{fill:#552222;stroke:#552222;}#mermaid-1675339841449 .edge-thickness-normal{stroke-width:2px;}#mermaid-1675339841449 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-1675339841449 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-1675339841449 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-1675339841449 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-1675339841449 .marker{fill:#666;stroke:#666;}#mermaid-1675339841449 .marker.cross{stroke:#666;}#mermaid-1675339841449 svg{font-family:sans-serif;font-size:14px;}#mermaid-1675339841449 .label{font-family:sans-serif;color:#000000;}#mermaid-1675339841449 .cluster-label text{fill:#333;}#mermaid-1675339841449 .cluster-label span{color:#333;}#mermaid-1675339841449 .label text,#mermaid-1675339841449 span{fill:#000000;color:#000000;}#mermaid-1675339841449 .node rect,#mermaid-1675339841449 .node circle,#mermaid-1675339841449 .node ellipse,#mermaid-1675339841449 .node polygon,#mermaid-1675339841449 .node path{fill:#eee;stroke:#999;stroke-width:1px;}#mermaid-1675339841449 .node .label{text-align:center;}#mermaid-1675339841449 .node.clickable{cursor:pointer;}#mermaid-1675339841449 .arrowheadPath{fill:#333333;}#mermaid-1675339841449 .edgePath .path{stroke:#666;stroke-width:2.0px;}#mermaid-1675339841449 .flowchart-link{stroke:#666;fill:none;}#mermaid-1675339841449 .edgeLabel{background-color:white;text-align:center;}#mermaid-1675339841449 .edgeLabel rect{opacity:0.5;background-color:white;fill:white;}#mermaid-1675339841449 .cluster rect{fill:hsl(0, 0%, 98.9215686275%);stroke:#707070;stroke-width:1px;}#mermaid-1675339841449 .cluster text{fill:#333;}#mermaid-1675339841449 .cluster span{color:#333;}#mermaid-1675339841449 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:sans-serif;font-size:12px;background:hsl(-160, 0%, 93.3333333333%);border:1px solid #707070;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-1675339841449 :root{--mermaid-font-family:sans-serif;--mermaid-font-size:14px;}#mermaid-1675339841449 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
 2
 3Typed post content
 4
 5Markdown parsing
 6
 7WordPress shortcodes
 8
 9WordPress content filters
10
11WP Scholar typographic enhancements
12
13Final post
14
15`

How WP Scholar processes your posts

#Typography

Good typography really makes a great difference in the life of people who have to read a lot. Also, properly composed text is just more pleasing. Computer typewriting has been responsible for enforcing bad typographic habits over traditional and professional typography, making things like thin space fall into disgrace simply because they have no place to sit on your keyboard anymore (seriously, do you even know what they are for ?).

Thin space has the width of a coma and used to be recommended before colon (:), semi-colon (;), question and exclamation marks ( !?) in both English and French. Their use has simply disappeared with typewriters and computers, and while the French have replaced them with usual space in all these cases, which helps legibility, the English have simply ditched them at all, which is very disagreeable to read. Punctuation simply has to stand out of words, not to get nested in them.

WP Scholar performs automatically these typographic changes to posts, comments and pages :

  • insert a mandatory unbreakable thin space :
    • before : ; ! ?
    • after ¡ 
    • inside French guillemets « »
    • between numbers and their units (as recommended by the SI Unit style ), like 21 kg.
    • between every thousand in numbers if the WordPress locale (language) is set to French,
  • insert a mandatory breakable en space :
    • after : ; ? ! . ,
    • before and after inline code elements
  • convert :
    • quotes :
      • straight single and double quotes '...' and "..." to curly typographic quotes ’…’ and “…” in non-French languages,
      • straight double quotes "..." and double chevron <<...>> into guillemets « … » for French languages,
      • two single quotes ''...'' into proper double quotes ”…”
    • punctuation :
      • 3 dots ... into ellipsis …
      • approximative dashes --- and -- to proper em and en dashes — and –
    • arrows :
      • approximative single and double arrows <-, ->, <—>, <=, =>, <> to ←, →, ↔, ⇐, ⇒, <>
      • approximative tailed arrows >->, <-<, |->, <-| to ↣, ↢, ↦, ↤
    • maths :
      • ~= and \= to ≃ and ≠
      • star multiplication 5*8 to 5×8 
      • plus or minus +/- to ±
      • fractions 1/2, 1/3, 99/100 to ½, ⅓, 99⁄100 (but let dates like 20/09/2019 alone).

#Intermediate documentation

#Mermaid charts

The Mermaid library allows to render graphs as SVG from a couple of Mardown-like commands. The syntactic overhead makes it very efficient to render simple graphs with text properly scaled at display size and DPI, like Gant charts, flow charts, pie diagrams, sequence charts, etc. Simply write a code block with mermaid as the language and type your graphs specifications (more info on the syntax ) :

1 ```mermaid
2  graph TD
3    A[Client] --> B[Load Balancer]
4    B --> C[Server01]
5    B --> D[Server02]
1#mermaid-1675339841745 {font-family:sans-serif;font-size:14px;fill:#000000;}#mermaid-1675339841745 .error-icon{fill:#552222;}#mermaid-1675339841745 .error-text{fill:#552222;stroke:#552222;}#mermaid-1675339841745 .edge-thickness-normal{stroke-width:2px;}#mermaid-1675339841745 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-1675339841745 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-1675339841745 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-1675339841745 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-1675339841745 .marker{fill:#666;stroke:#666;}#mermaid-1675339841745 .marker.cross{stroke:#666;}#mermaid-1675339841745 svg{font-family:sans-serif;font-size:14px;}#mermaid-1675339841745 .label{font-family:sans-serif;color:#000000;}#mermaid-1675339841745 .cluster-label text{fill:#333;}#mermaid-1675339841745 .cluster-label span{color:#333;}#mermaid-1675339841745 .label text,#mermaid-1675339841745 span{fill:#000000;color:#000000;}#mermaid-1675339841745 .node rect,#mermaid-1675339841745 .node circle,#mermaid-1675339841745 .node ellipse,#mermaid-1675339841745 .node polygon,#mermaid-1675339841745 .node path{fill:#eee;stroke:#999;stroke-width:1px;}#mermaid-1675339841745 .node .label{text-align:center;}#mermaid-1675339841745 .node.clickable{cursor:pointer;}#mermaid-1675339841745 .arrowheadPath{fill:#333333;}#mermaid-1675339841745 .edgePath .path{stroke:#666;stroke-width:2.0px;}#mermaid-1675339841745 .flowchart-link{stroke:#666;fill:none;}#mermaid-1675339841745 .edgeLabel{background-color:white;text-align:center;}#mermaid-1675339841745 .edgeLabel rect{opacity:0.5;background-color:white;fill:white;}#mermaid-1675339841745 .cluster rect{fill:hsl(0, 0%, 98.9215686275%);stroke:#707070;stroke-width:1px;}#mermaid-1675339841745 .cluster text{fill:#333;}#mermaid-1675339841745 .cluster span{color:#333;}#mermaid-1675339841745 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:sans-serif;font-size:12px;background:hsl(-160, 0%, 93.3333333333%);border:1px solid #707070;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-1675339841745 :root{--mermaid-font-family:sans-serif;--mermaid-font-size:14px;}#mermaid-1675339841745 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
2
3Client
4
5Load Balancer
6
7Server01
8
9Server02
 pie
   title Key elements in Product X
   "Calcium" : 42.96
   "Potassium" : 50.05
   "Magnesium" : 10.01
   "Iron" :  5
  1Key elements in Product X#mermaid-1675339841838 {font-family:sans-serif;font-size:14px;fill:#000000;}#mermaid-1675339841838 .error-icon{fill:#552222;}#mermaid-1675339841838 .error-text{fill:#552222;stroke:#552222;}#mermaid-1675339841838 .edge-thickness-normal{stroke-width:2px;}#mermaid-1675339841838 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-1675339841838 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-1675339841838 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-1675339841838 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-1675339841838 .marker{fill:#666;stroke:#666;}#mermaid-1675339841838 .marker.cross{stroke:#666;}#mermaid-1675339841838 svg{font-family:sans-serif;font-size:14px;}#mermaid-1675339841838 .pieCircle{stroke:black;stroke-width:2px;opacity:0.7;}#mermaid-1675339841838 .pieTitleText{text-anchor:middle;font-size:25px;fill:#333;font-family:sans-serif;}#mermaid-1675339841838 .slice{font-family:sans-serif;fill:#000000;font-size:17px;}#mermaid-1675339841838 .legend text{fill:#333;font-family:sans-serif;font-size:17px;}#mermaid-1675339841838 :root{--mermaid-font-family:sans-serif;--mermaid-font-size:14px;}#mermaid-1675339841838 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}40%46%9%5%Key elements in Product XCalciumPotassiumMagnesiumIron
  2```
  3
  4Mermaid charts can be drawn from Markdown, but also from any `<code></code>` HTML element with a `class="mermaid"` like :
  5
  6```
  7<pre class="graph">
  8  <code class="mermaid">
  9  pie
 10    title Key elements in Product X
 11    "Calcium" : 42.96
 12    "Potassium" : 50.05
 13    "Magnesium" : 10.01
 14    "Iron" :  5
 15  </code>
 16</pre>
 17```
 18
 19The `<pre></pre>` tag is facultative but highly recommended for HTML5 conformity and proper block display.
 20
 21### [#](#include "Click to copy this section URL")Import and include external Markdown and HTML to WordPress posts[↑](#toc_container "Click to go back to the table of contents")
 22
 23WP Scholar lets you import pure Markdown files or rendered HTML files directly to your media library, to include them in posts, pages and custom types. Markdown files are typically simple text files saved with a `.md` extension.
 24
 25Upload the file to your media library, like any image, then use the shortcode `[include path="path/file.html" load="plotly, mathjax, jupyter"]` where `path` is the complete path of the file within your `wp-content/uploads` directory (using a `year/month/`structure if enabled, or just blank if media are loaded directly in `uploads`).
 26
 27The `load` argument is optional and forces the relevant assets to load in order to properly render your include :
 28
 29`jupyter`
 30
 31Loads the default Jupyter stylesheet. The Jupyter stylesheet is the only one that is never auto-loaded, so you could force your own stylesheet or you need to add this argument everytime.
 32
 33`mathjax`, `plotly`, `bokeh`
 34
 35Forces the relevant javascript files to load. These should be detected automatically, set it explicitly if they are missed.
 36
 37The includes are nested in a `<>` container that gets a generic CSS class `include` and specific classes `plotly`, `jupyter` and `mathjax`, so you can style them in CSS using these selectors :
 38
 39```
 40.include .jupyter {
 41  font-size: 1.1em;
 42}
 43```
 44
 45Markdown syntax is always parsed in external files, then, WordPress shortcodes and typographic enhancements are also applied on the result. So you can write your WordPress blog in a static fashion, by just giving it Markdown posts or exported HTML files.
 46
 47[#](#Expert-Documentation "Click to copy this section URL")Expert Documentation[↑](#toc_container "Click to go back to the table of contents")
 48----------------------------------------------------------------------------------------------------------------------------------------------
 49
 50### [#](#jupyter "Click to copy this section URL")Jupyter notebooks, Plotly & Bokeh graphs[↑](#toc_container "Click to go back to the table of contents")
 51
 52[Jupyter notebooks](https://web.archive.org/web/20230202120922/https://jupyter.org/) are a great way to quickly perform scientific computation, data-mining, text parsing, or even labs in Python, Julia and now C, straight from a web browser. They provide plenty of GUI widgets that let you wire them to your Python functions, to vary parameters, and get the real-time graph straight below the code cells. They also let you write Markdown and `LATEX` which means you can have text, explanations, equations, images, straight along your code and output graphs and table. So you can actually write casual scientific articles straight in notebooks ([see an example](https://web.archive.org/web/20230202120922/https://eng.aurelienpierre.com/2018/05/analyse-the-heat-losses-and-design-the-heating-of-a-sprinter-van/)).
 53
 54Bokeh and Plotly are 2 libraries to render graphs, compatible with Python, Matlab, and many others. They are of great use to us because they allow **interactive** graphs, rendered as SVG directly from the values to plot, through a javascript lib. Interactive graphs let users zoom in/out, select points and get a value reading, or even rotate 3D graphs in space. You can put interactive extra labels and annotations on there too, so users can unfold them when they want, but they stay hidden/discrete otherwise.
 55
 56Notebooks and graphs need to be exported **to** pure HTML pages. See above to include them **from** HTML into WordPress pages. We will see here how to export them **to** HTML.
 57
 58#### [#](#Export-Jupyter-to-HTML "Click to copy this section URL")Export Jupyter to HTML[↑](#toc_container "Click to go back to the table of contents")
 59
 60```
 61jupyter nbconvert --to=html --template=basic notebook.ipynb notebook.html
 62```
 63
 64#### [#](#Export-Plotly-to-HTML "Click to copy this section URL")Export Plotly to HTML[↑](#toc_container "Click to go back to the table of contents")
 65
 66Note : Dont embed Plotly.js in the exported files, it is too heavy and redundant if you have several graphs on the same page. WP Scholar will load Plotly.js automatically, wherever it is needed, but only once per page and properly through the generic WordPress script enqueueing, which means it will be handled by caching plugins if you have them.
 67
 68```
 69import plotly.express as px
 70fig = px.line(x=range(10), y=range(10)) # just a dummy graph
 71fig.write_html("plotly_sample.html", include_plotlyjs = False)
 72```
 73
 74The important part is the `include_plotlyjs = False`. Then, using `[include path="2021/03/plotly_sample.html"]`, we get : 
 75
 76012345678902468
 77
 78xy
 79
 80[.cls-0{fill:#000;} .cls-1{fill:#FFF;} .cls-2{fill:#F26;} .cls-3{fill:#D69;} .cls-4{fill:#BAC;} .cls-5{fill:#9EF;} plotly-logomark](https://web.archive.org/web/20230131211724/https://plotly.com/)
 81
 82window.PLOTLYENV=window.PLOTLYENV || {}; if (document.getElementById("6c0af3fb-7a6a-4791-b6b6-a474fd020331")) { Plotly.newPlot( "6c0af3fb-7a6a-4791-b6b6-a474fd020331", [{"hovertemplate": "x=%{x}<br>y=%{y}<extra></extra>", "legendgroup": "", "line": {"color": "#636efa", "dash": "solid"}, "mode": "lines", "name": "", "orientation": "v", "showlegend": false, "type": "scatter", "x": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], "xaxis": "x", "y": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], "yaxis": "y"}], {"legend": {"tracegroupgap": 0}, "margin": {"t": 60}, "template": {"data": {"bar": [{"error_x": {"color": "#2a3f5f"}, "error_y": {"color": "#2a3f5f"}, "marker": {"line": {"color": "#E5ECF6", "width": 0.5}}, "type": "bar"}], "barpolar": [{"marker": {"line": {"color": "#E5ECF6", "width": 0.5}}, "type": "barpolar"}], "carpet": [{"aaxis": {"endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f"}, "baxis": {"endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f"}, "type": "carpet"}], "choropleth": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "choropleth"}], "contour": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "contour"}], "contourcarpet": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "contourcarpet"}], "heatmap": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "heatmap"}], "heatmapgl": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "heatmapgl"}], "histogram": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "histogram"}], "histogram2d": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "histogram2d"}], "histogram2dcontour": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "histogram2dcontour"}], "mesh3d": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "mesh3d"}], "parcoords": [{"line": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "parcoords"}], "pie": [{"automargin": true, "type": "pie"}], "scatter": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatter"}], "scatter3d": [{"line": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatter3d"}], "scattercarpet": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattercarpet"}], "scattergeo": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattergeo"}], "scattergl": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattergl"}], "scattermapbox": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattermapbox"}], "scatterpolar": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatterpolar"}], "scatterpolargl": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatterpolargl"}], "scatterternary": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatterternary"}], "surface": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "surface"}], "table": [{"cells": {"fill": {"color": "#EBF0F8"}, "line": {"color": "white"}}, "header": {"fill": {"color": "#C8D4E3"}, "line": {"color": "white"}}, "type": "table"}]}, "layout": {"annotationdefaults": {"arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1}, "autotypenumbers": "strict", "coloraxis": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "colorscale": {"diverging": [[0, "#8e0152"], [0.1, "#c51b7d"], [0.2, "#de77ae"], [0.3, "#f1b6da"], [0.4, "#fde0ef"], [0.5, "#f7f7f7"], [0.6, "#e6f5d0"], [0.7, "#b8e186"], [0.8, "#7fbc41"], [0.9, "#4d9221"], [1, "#276419"]], "sequential": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "sequentialminus": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]]}, "colorway": ["#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52"], "font": {"color": "#2a3f5f"}, "geo": {"bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white"}, "hoverlabel": {"align": "left"}, "hovermode": "closest", "mapbox": {"style": "light"}, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": {"angularaxis": {"gridcolor": "white", "linecolor": "white", "ticks": ""}, "bgcolor": "#E5ECF6", "radialaxis": {"gridcolor": "white", "linecolor": "white", "ticks": ""}}, "scene": {"xaxis": {"backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white"}, "yaxis": {"backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white"}, "zaxis": {"backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white"}}, "shapedefaults": {"line": {"color": "#2a3f5f"}}, "ternary": {"aaxis": {"gridcolor": "white", "linecolor": "white", "ticks": ""}, "baxis": {"gridcolor": "white", "linecolor": "white", "ticks": ""}, "bgcolor": "#E5ECF6", "caxis": {"gridcolor": "white", "linecolor": "white", "ticks": ""}}, "title": {"x": 0.05}, "xaxis": {"automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": {"standoff": 15}, "zerolinecolor": "white", "zerolinewidth": 2}, "yaxis": {"automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": {"standoff": 15}, "zerolinecolor": "white", "zerolinewidth": 2}}}, "xaxis": {"anchor": "y", "domain": [0.0, 1.0], "title": {"text": "x"}}, "yaxis": {"anchor": "x", "domain": [0.0, 1.0], "title": {"text": "y"}}}, {"responsive": true} ) };
 83
 84#### [#](#Export-Bokeh-to-HTML "Click to copy this section URL")Export Bokeh to HTML[↑](#toc_container "Click to go back to the table of contents")
 85
 86Same idea, we need to actively tell Bokeh to not embed the Bokeh.js in the export HTML, we take crare of that ourselves.
 87
 88```
 89from bokeh.plotting import figure, show, output_file
 90p = figure()
 91p.line(x=range(10), y=range(10)) # just a dummy graph
 92output_file(filename="bokeh_sample.html", mode="server")
 93show(p)
 94```
 95
 96The important part being `mode="server"`, which does not actually remove the javascript but rather tell Bokeh to go fetch a local lib that is not there (on `localhost`). This trick will produce an error in JS console, but Bokeh has no way to just remove any JS and simply produce HTML. So `[include path="2021/03/bokeh_sample.html"]` gives :
 97
 98 Static HTML file  Bokeh.set_log_level("info");
 99
100{"bf9517e6-7e4a-4ebb-a9c9-6a0c2b46235d":{"defs":[{"extends":null,"module":null,"name":"DataModel","overrides":[],"properties":[]}],"roots":{"references":[{"attributes":{},"id":"1591","type":"DataRange1d"},{"attributes":{},"id":"1606","type":"WheelZoomTool"},{"attributes":{},"id":"1605","type":"PanTool"},{"attributes":{"overlay":{"id":"1611"}},"id":"1607","type":"BoxZoomTool"},{"attributes":{},"id":"1625","type":"Title"},{"attributes":{},"id":"1589","type":"DataRange1d"},{"attributes":{},"id":"1608","type":"SaveTool"},{"attributes":{"data":{"x":[0,1,2,3,4,5,6,7,8,9],"y":[0,1,2,3,4,5,6,7,8,9]},"selected":{"id":"1633"},"selection_policy":{"id":"1632"}},"id":"1619","type":"ColumnDataSource"},{"attributes":{},"id":"1609","type":"ResetTool"},{"attributes":{"below":[{"id":"1597"}],"center":[{"id":"1600"},{"id":"1604"}],"left":[{"id":"1601"}],"renderers":[{"id":"1622"}],"title":{"id":"1625"},"toolbar":{"id":"1612"},"x_range":{"id":"1589"},"x_scale":{"id":"1593"},"y_range":{"id":"1591"},"y_scale":{"id":"1595"}},"id":"1588","subtype":"Figure","type":"Plot"},{"attributes":{"source":{"id":"1619"}},"id":"1623","type":"CDSView"},{"attributes":{},"id":"1626","type":"BasicTickFormatter"},{"attributes":{},"id":"1610","type":"HelpTool"},{"attributes":{"formatter":{"id":"1629"},"major_label_policy":{"id":"1631"},"ticker":{"id":"1598"}},"id":"1597","type":"LinearAxis"},{"attributes":{},"id":"1628","type":"AllLabels"},{"attributes":{},"id":"1632","type":"UnionRenderers"},{"attributes":{"axis":{"id":"1597"},"ticker":null},"id":"1600","type":"Grid"},{"attributes":{},"id":"1631","type":"AllLabels"},{"attributes":{"formatter":{"id":"1626"},"major_label_policy":{"id":"1628"},"ticker":{"id":"1602"}},"id":"1601","type":"LinearAxis"},{"attributes":{"active_multi":null,"tools":[{"id":"1605"},{"id":"1606"},{"id":"1607"},{"id":"1608"},{"id":"1609"},{"id":"1610"}]},"id":"1612","type":"Toolbar"},{"attributes":{},"id":"1629","type":"BasicTickFormatter"},{"attributes":{},"id":"1598","type":"BasicTicker"},{"attributes":{},"id":"1593","type":"LinearScale"},{"attributes":{"bottom_units":"screen","fill_alpha":0.5,"fill_color":"lightgrey","left_units":"screen","level":"overlay","line_alpha":1.0,"line_color":"black","line_dash":[4,4],"line_width":2,"right_units":"screen","syncable":false,"top_units":"screen"},"id":"1611","type":"BoxAnnotation"},{"attributes":{"axis":{"id":"1601"},"dimension":1,"ticker":null},"id":"1604","type":"Grid"},{"attributes":{},"id":"1595","type":"LinearScale"},{"attributes":{"line_color":"#1f77b4","x":{"field":"x"},"y":{"field":"y"}},"id":"1620","type":"Line"},{"attributes":{},"id":"1602","type":"BasicTicker"},{"attributes":{},"id":"1633","type":"Selection"},{"attributes":{"data_source":{"id":"1619"},"glyph":{"id":"1620"},"hover_glyph":null,"muted_glyph":null,"nonselection_glyph":{"id":"1621"},"view":{"id":"1623"}},"id":"1622","type":"GlyphRenderer"},{"attributes":{"line_alpha":0.1,"line_color":"#1f77b4","x":{"field":"x"},"y":{"field":"y"}},"id":"1621","type":"Line"}],"root_ids":["1588"]},"title":"Bokeh Application","version":"2.3.0"}} (function() { var fn = function() { Bokeh.safely(function() { (function(root) { function embed_document(root) { var docs_json = document.getElementById('1734').textContent; var render_items = [{"docid":"bf9517e6-7e4a-4ebb-a9c9-6a0c2b46235d","root_ids":["1588"],"roots":{"1588":"ce8c8ccc-7000-4c2c-b421-aaa1874b16cb"}}]; root.Bokeh.embed.embed_items(docs_json, render_items); } if (root.Bokeh !== undefined) { embed_document(root); } else { var attempts = 0; var timer = setInterval(function(root) { if (root.Bokeh !== undefined) { clearInterval(timer); embed_document(root); } else { attempts++; if (attempts > 100) { clearInterval(timer); console.log("Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing"); } } }, 10, root) } })(window); }); }; if (document.readyState != "loading") fn(); else document.addEventListener("DOMContentLoaded", fn); })();
101
102* * *
103
104**Note** : I personaly find that Bokeh reeks of bad design. The HTML they produce is amateur-level, they dont support responsive width and the whole look is very much high-school. It is provided here only as an alternative, also because it is slightly lighter than Plotly.
105
106* * *
107
108### [#](#Maths-and-chemical-equations "Click to copy this section URL")Maths and chemical equations[↑](#toc_container "Click to go back to the table of contents")
109
110The `LaTeX` support is provided by Mathjax.js 3.1.2 wherever it is detected. The page content is searched for equations, and if some are found, Mathjax.js script is loaded. For performance, comments **are not searched**, which means if the main content (post or page content) has not triggered Mathjax loading, equations will not be rendered in comments. This is intended to prevent commentors to go pedantic with LaTeX in the comments on pages that didnt contain equations in the first place.
111
112#### [#](#Inline-mode "Click to copy this section URL")Inline mode[↑](#toc_container "Click to go back to the table of contents")
113
114Type your equations between `$` (with no inside space), like `$\LaTeX$` for inline equations. Renders : `LATEX`.
115
116For compatibility with other WordPress `LATEX` plugins, the inline mode also supports the shortcode syntax `[latex]...[/latex]` and the Jetpack syntax `` `$...$` `` but they are all converted to inline math display. Optional parameters of the [Jetpack](https://web.archive.org/web/20230202120922/https://jetpack.com/support/beautiful-math-with-latex/) plugin, like size and colors, are not supported (aka the trailing `&s=X` and `&bg=X` before the closing `$`). Similarly, `latex` shortcodes using parameters are not supported.
117
118#### [#](#Display-mode "Click to copy this section URL")Display mode[↑](#toc_container "Click to go back to the table of contents")
119
120Type your equations between `$$` (with no inside space), like `$$\LaTeX \label{eq-a}$$` for equations in display mode, and add at least one line break between the previous text and the `$$` opening the equation. Renders :
121
122```
123(1)(1)LATEX
124```
125
126Display mode has equations numbering enabled by default (that will be incremented page-wise) and can be disabled by using `\nonumber` in the equation. Labels/references can be used, so `` `$\eqref{eq-a}$` `` renders `(1)(1)`.
127
128#### [#](#Display-mode-in-equation-block "Click to copy this section URL")Display mode in equation block[↑](#toc_container "Click to go back to the table of contents")
129
130In case you need to protect line breaks inside equations in display mode, for example with environments, you need to input the equations as an equation block, with one empty line before and after `$$` :
131
132```
133$$
134\begin{align}
135\iint_{-a/2}^{a/2} i^2 \cdot e^{-\frac{i^2}{2 \sigma^2}} \cdot e^{-\frac{j^2}{2 \sigma^2}}\, \mathrm{d}i \, \mathrm{d}j
136  &= \int_{-a/2}^{a/2} e^{-\frac{j^2}{2 \sigma^2}} \, \mathrm{d}j \, \cdot \int_{-a/2}^{a/2} i^2 \cdot e^{-\frac{i^2}{2 \sigma^2}} \, \mathrm{d}i \\\
137  &= \sqrt{2 \pi \sigma^2} \, \cdot \, \frac{1}{2}\sqrt{8 \pi \sigma^6} \\\
138  &= \frac{\sqrt{16 \pi}}{2} \sigma^4
139\end{align}
140$$
141```
142
143renders :
144
145```
146(2)(3)(4)(2)∬−a/2a/2i2ei22σ2ej22σ2didj=∫−a/2a/2ej22σ2dj⋅∫−a/2a/2i2ei22σ2di(3)=2πσ2128πσ6(4)=16π2σ4
147```
148
149This particular equation is using `align` environment and needs line breaks to be honoured at parsing time. To ensure that, you need to enclose it exactly as shown in the code snippet above in an equation block :
150
151*   one empty line before,
152*   `$$` alone on a line, then a new line,
153*   `LATEX` code as usual, possibly with internal line breaks,
154*   a newline, then `$$` alone on a line,
155*   one empty line after.
156
157Failure to comply with these instructions results in garbled line breaks and garbled layout.
158
159#### [#](#Available-plugins "Click to copy this section URL")Available plugins[↑](#toc_container "Click to go back to the table of contents")
160
161The AMS and Physics packages are loaded at startup, which gives you access, out-of-the-box, to many helpers :
162
163*   equations labelling and referencing through `\label`, `\ref` and `\eqref` tags,
164*   equations numbering and aligning, through `\begin{env}...\end{env}` environments like `align`, `equation`, etc. ([see the complete list of available environments](https://web.archive.org/web/20230202120922/http://docs.mathjax.org/en/v3.1-latest/input/tex/macros/index.html#environments)),
165*   usual MathJax and/or `LATEX` packages will be loaded automatically if their use is detected. This includes : `action`, `amscd`, `bbox`, `boldsymbol`, `braket`, `cancel`, `color`, `enclose`, `extpfeil`, `html`, `mhchem` (chemical expressions), `newcommand`, `unicode`, `verb`,
166*   custom packages can be loaded while typing by adding a `\require{package}` before the equations ([see the complete list of available extensions](https://web.archive.org/web/20230202120922/http://docs.mathjax.org/en/v3.1-latest/input/tex/extensions/index.html))
167
168#### [#](#Warnings "Click to copy this section URL")Warnings[↑](#toc_container "Click to go back to the table of contents")
169
1701.  White lines (double line breaks) are not permitted inside a `LATEX` markup,
1712.  White lines around equations (before and after) in display mode are mandatory, no matter if you are in maths block or not. Otherwise, equations are not detected.
1723.  LaTeX line breaks (`\\` character) are not yet supported in [Mathjax 3.1](https://web.archive.org/web/20230202120922/https://github.com/mathjax/MathJax/issues/2312),
1734.  Only maths block will ensure the content of an equation will be completely escaped from any Markdown parsing and change. Remember we are stacking a LaTeX  MathML parser on top of a Markdown  HTML parser, all these languages share some common characters that have a different meaning for each of them, so always add a space between LaTeX commands (even though pure LaTeX doesnt need it), use line breaks wisely and avoid mixing up HTML in your equations.
174
175### [#](#Code-syntax-highlighting "Click to copy this section URL")Code syntax highlighting[↑](#toc_container "Click to go back to the table of contents")
176
177Enclose your code inside 3 backticks (usual Markdown fenced code block) and mention the programming language on the first line, like :
178
179```
180```python
181import numpy as np
182x = np.linspace(0, 1)
183y = np.exp(- x**2 / 2)
184```
185
186```
187
188This will automatically render the code block with syntax highlighting for the current language :
189
190```
191import numpy as np
192x = np.linspace(0, 1)
193y = np.exp(- x**2 / 2)
194```
195
196To get the syntax highlighting similarly in any `<pre></pre>` element, defined in HTML instead of Markdown, you simply need to add it a `<pre class="language-xxx"></pre>` (where `xxx` is the current language, `python` in this instance).
197
198If you want to enable line numbering on a specific block of code, you need to add it a `class="line-numbers"`, which can be done directly on the `<pre></pre>` HTML element or in Markdown by using the custom classes handler :
199
200```
201``` { .language-python .line-numbers }
202import numpy as np
203x = np.linspace(0, 1)
204y = np.exp(- x**2 / 2)
205```
206
207```
208
209which renders :
210
211```
212import numpy as np
213x = np.linspace(0, 1)
214y = np.exp(- x**2 / 2)
215```
216
217Notice you need to input `language-xxx` in full with that configuration and leave a blank space between ` ``` ` and `{`.
218
219For better performance, the presence of code blocks to highlight is detected at parsing time, and the Prism.js autoloader is enqueued to the WordPress page only at that condition. Then, the autoloader is executed in the clients browser and checks the languages currently used on the page, to only load the relevant syntaxes. This ensures minimum bloatware and page loading time.
220
221The language parameter is optional in code blocks and if no language is provided, the parser defaults to a generic code block without styling. To get a styled block but without syntax highlighting, you can declare the language as `none`.
222
223[#](#Helpers "Click to copy this section URL")Helpers[↑](#toc_container "Click to go back to the table of contents")
224--------------------------------------------------------------------------------------------------------------------
225
226### [#](#Disable-Markdown-rendering-and-typography-enhancements "Click to copy this section URL")Disable Markdown rendering and typography enhancements[↑](#toc_container "Click to go back to the table of contents")
227
228To enable the Markdown parsing and avoid formatting conflicts, WP Scholar needs to disable WordPress auto-formatting filters. If, for some reason, this was to clash with page builders or other features, it is possible to disable WP Scholar entirely, on a page-wise basis, by adding the following HTML comment anywhere in the page : 
229
230```
231<!-- no-markdown -->
232```
233
234This will re-enable default WordPress formatting and style. Similarly, to disable the typographic enhancements :
235
236```
237<!-- no-typography -->
238```
239
240### [#](#Disable-table-of-contents-page-wise "Click to copy this section URL")Disable table of contents page-wise[↑](#toc_container "Click to go back to the table of contents")
241
242If you opt-in for the table of contents widget and display TOC in sidebars globally, you can chose to disable it selectively on a page-wise basis, using the comment :
243
244```
245<!-- no-sidebar-toc -->
246```
247
248### [#](#Force-javascript-loading "Click to copy this section URL")Force javascript loading[↑](#toc_container "Click to go back to the table of contents")
249
250At anytime, anywhere in a post, if for some reason (usually a conflict with encoding or with cache plugins) the javascripts ressources didnt load, you can force them by adding one of these HTML comments tag in your post :
251
252```
253<!-- mathjax -->
254<!-- bokeh -->
255<!-- plotly -->
256```
257
258### [#](#Figures-and-captions "Click to copy this section URL")Figures and captions[↑](#toc_container "Click to go back to the table of contents")
259
260Markdown only allows simple images in the content. A shortcode is provided to embed images, tables or code blocks in HTML5 `<figure>` elements and add captions without having to deal with the Markdown compatibility :
261
262```
263[figure align="center" id="that-graph"]
264![](wp-content/uploads/sites/8/2021/02/hue-linearity.jpg "Title")
265[figcaption]
266The legendary hue linearity and uniformity of CIE Lab/Luv 1976 compared to IPT from Fairchild, IC~T~P~T~ from ITU-R BT.2100, CIECAM 2016 UCS, and JzAzBz.
267[/figcaption]
268[/figure]
269```
270
271will render :
272
273![](data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%271189%27%20height%3D%27903%27%20viewBox%3D%270%200%201189%20903%27%3E%3Crect%20width%3D%271189%27%20height%3D%27903%27%20fill-opacity%3D%220%22%2F%3E%3C%2Fsvg%3E "Title")
274
275The legendary hue linearity and uniformity of CIE Lab/Luv 1976 compared to IPT from Fairchild, ICTPT from ITU-R BT.2100, CIECAM 2016 UCS, and JzAzBz.
276
277Available and optional arguments :
278
279`align`
280
281As per [usual WordPress image alignments](https://web.archive.org/web/20230202120922/https://codex.wordpress.org/Styling_Images_in_Posts_and_Pages), the value `align` can take 4 arguments that will attribute a CSS class to the figure :
282
283*   `none`  CSS class `alignnone`,
284*   `left`  CSS class `alignleft`,
285*   `center`  CSS class `aligncenter`,
286*   `right`  CSS class `alignright`.
287
288`id`
289
290A CSS identifier that can be used either to style the `figure` or to make internal links and anchors, like [that graph](#that-graph).
291
292The caption can go before or after the image, although usage tends to put it after for images and before for tables. It is also possible to use the HTML markup directly and to tag elements with `markdown="1"` as shown above.
293
294[#](#Dev-Power-user-documentation "Click to copy this section URL")Dev/Power-user documentation[↑](#toc_container "Click to go back to the table of contents")
295--------------------------------------------------------------------------------------------------------------------------------------------------------------
296
297### [#](#Caching-settings "Click to copy this section URL")Caching settings[↑](#toc_container "Click to go back to the table of contents")
298
299If your caching plugin gets over-zealous with the javascripts used here, you can tell it to exclude the following files. Here is the suggested configuration for WP Rocket (used here) :
300
301Exclude CSS files from minification (since they are already minified) :
302
303```
304(.*).min.css
305cdn(.*)
306```
307
308Exclude JS files from minification (again, already minified) :
309
310```
311cdnjs.cloudflare.com/ajax/libs/(.*)
312(.*).min.js
313```
314
315JS deferring works for all files, except for plotly, so exclude it :
316
317```
318plotly.js
319```
320
321JS delaying seems to work, so you can **add** these files :
322
323```
324prism.min.js
325mathjax.js
326wp-scholar.min.js
327tex-svg.js
328```
329
330This page shows the worst possible case where everything is loaded at once. Since Mathjax and Mermaid are meant to render actual code to SVG, they are anyway quite heavy and there is only so much we can do to make loading time bearable.
331
332### [#](#Sequence-of-processing "Click to copy this section URL")Sequence of processing[↑](#toc_container "Click to go back to the table of contents")
333
334```
335#mermaid-1675339841865 {font-family:sans-serif;font-size:14px;fill:#000000;}#mermaid-1675339841865 .error-icon{fill:#552222;}#mermaid-1675339841865 .error-text{fill:#552222;stroke:#552222;}#mermaid-1675339841865 .edge-thickness-normal{stroke-width:2px;}#mermaid-1675339841865 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-1675339841865 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-1675339841865 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-1675339841865 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-1675339841865 .marker{fill:#666;stroke:#666;}#mermaid-1675339841865 .marker.cross{stroke:#666;}#mermaid-1675339841865 svg{font-family:sans-serif;font-size:14px;}#mermaid-1675339841865 .label{font-family:sans-serif;color:#000000;}#mermaid-1675339841865 .cluster-label text{fill:#333;}#mermaid-1675339841865 .cluster-label span{color:#333;}#mermaid-1675339841865 .label text,#mermaid-1675339841865 span{fill:#000000;color:#000000;}#mermaid-1675339841865 .node rect,#mermaid-1675339841865 .node circle,#mermaid-1675339841865 .node ellipse,#mermaid-1675339841865 .node polygon,#mermaid-1675339841865 .node path{fill:#eee;stroke:#999;stroke-width:1px;}#mermaid-1675339841865 .node .label{text-align:center;}#mermaid-1675339841865 .node.clickable{cursor:pointer;}#mermaid-1675339841865 .arrowheadPath{fill:#333333;}#mermaid-1675339841865 .edgePath .path{stroke:#666;stroke-width:2.0px;}#mermaid-1675339841865 .flowchart-link{stroke:#666;fill:none;}#mermaid-1675339841865 .edgeLabel{background-color:white;text-align:center;}#mermaid-1675339841865 .edgeLabel rect{opacity:0.5;background-color:white;fill:white;}#mermaid-1675339841865 .cluster rect{fill:hsl(0, 0%, 98.9215686275%);stroke:#707070;stroke-width:1px;}#mermaid-1675339841865 .cluster text{fill:#333;}#mermaid-1675339841865 .cluster span{color:#333;}#mermaid-1675339841865 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:sans-serif;font-size:12px;background:hsl(-160, 0%, 93.3333333333%);border:1px solid #707070;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-1675339841865 :root{--mermaid-font-family:sans-serif;--mermaid-font-size:14px;}#mermaid-1675339841865 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
336
337Server
338
339WP Scholar
340
341WordPress
342
343yes
344
345no
346
347yes
348
349link
350
351Final HTML page
352
353 Author article input (Markdown + HTML)
354
355Database
356
357WordPress content filters/shortcodes
358
359+
360
361Template header, body, footer
362
363Pure Markdown
364
365Page splitting
366
367Pure HTML
368
369is inline parsing forced ?
370
371Markdown parser
372
373Intermediate HTML result
374
375Final parsed HTML article
376
377Typographic enhancements
378
379has raw elements to render client-side ?
380
381https://
382
383cdnjs.cloudflare.com

#mermaid-1675339842360 {font-family:sans-serif;font-size:14px;fill:#000000;}#mermaid-1675339842360 .error-icon{fill:#552222;}#mermaid-1675339842360 .error-text{fill:#552222;stroke:#552222;}#mermaid-1675339842360 .edge-thickness-normal{stroke-width:2px;}#mermaid-1675339842360 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-1675339842360 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-1675339842360 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-1675339842360 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-1675339842360 .marker{fill:#666;stroke:#666;}#mermaid-1675339842360 .marker.cross{stroke:#666;}#mermaid-1675339842360 svg{font-family:sans-serif;font-size:14px;}#mermaid-1675339842360 .label{font-family:sans-serif;color:#000000;}#mermaid-1675339842360 .cluster-label text{fill:#333;}#mermaid-1675339842360 .cluster-label span{color:#333;}#mermaid-1675339842360 .label text,#mermaid-1675339842360 span{fill:#000000;color:#000000;}#mermaid-1675339842360 .node rect,#mermaid-1675339842360 .node circle,#mermaid-1675339842360 .node ellipse,#mermaid-1675339842360 .node polygon,#mermaid-1675339842360 .node path{fill:#eee;stroke:#999;stroke-width:1px;}#mermaid-1675339842360 .node .label{text-align:center;}#mermaid-1675339842360 .node.clickable{cursor:pointer;}#mermaid-1675339842360 .arrowheadPath{fill:#333333;}#mermaid-1675339842360 .edgePath .path{stroke:#666;stroke-width:2.0px;}#mermaid-1675339842360 .flowchart-link{stroke:#666;fill:none;}#mermaid-1675339842360 .edgeLabel{background-color:white;text-align:center;}#mermaid-1675339842360 .edgeLabel rect{opacity:0.5;background-color:white;fill:white;}#mermaid-1675339842360 .cluster rect{fill:hsl(0, 0%, 98.9215686275%);stroke:#707070;stroke-width:1px;}#mermaid-1675339842360 .cluster text{fill:#333;}#mermaid-1675339842360 .cluster span{color:#333;}#mermaid-1675339842360 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:sans-serif;font-size:12px;background:hsl(-160, 0%, 93.3333333333%);border:1px solid #707070;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-1675339842360 :root{–mermaid-font-family:sans-serif;–mermaid-font-size:14px;}#mermaid-1675339842360 :root{–mermaid-font-family:“trebuchet ms”,verdana,arial,sans-serif;}

Client

Raw $\LaTeX$ code

Code blocks

Raw charts code

Raw JSON graphs

HTML elements

Incoming HTML page

Mathjax.js

Prism.js

Mermaid.js

Plotly.js

Rendered maths

Highlighted code

Rendered charts

Rendered graphs

Final rendered page

https://

cdnjs.cloudflare.com

load/cache

1
2Flow chart of the post/page content parsing