MarkDown Extensions in CoWeM

Steven J Zeil

Last modified: Jun 9, 2020
Contents:

CoWeM pre-processes Markdown documents using a macro processor described in more detail later. Using that, I have added a number of extensions to the basic Markdown. Theme may not always adhering to the Markdown goal of keeping the source text looking suggestive of the formatted results, but they do add facilitiesthat I find particularly useful.

1 Inline mark-up

These extensions can be applied to text inside a paragraph:

1.1 Incremental Lists

 

You can view this document as slides to see this in action.

1.2 firstterm and emph

 

I have a markup for new terms being introduced for the first time in a document, and for very strong emphasis.

1.3 Highlighting and Callouts

 

I also have a set of markups for highlighting text in one, two, three, and four colors. I have commands to generate callout numbers , , …, . Both the callout numbers and color highlighting are generally used in conjunction with the code markups discussed later.

2 Block mark-ups

Block mark-ups flag a block of paragraphs for special formatting. Most of these are begin by a \b… command and terminated by a matching \ecommand.

2.1 Examples

 
Example 1: An Example of Examples

For example, you can introduce numbered examples.

As a general rule, these \b… and \e… commands should be entered on a separate line, as if they constitute a separate paragraph. (This was required in older versions of this software. It’s more relaxed in the current version, but it is probably still a good idea if only because it improves the visibility of the commands and helps you make sure that, for every \b… you have a corresponding \e

 

I do like an occasional sidebar.

 

Sidebars can be width-constrained so that they will not extend horizontally past a certain percentage of the page width. Any multiple of 5 can be given as a maximum with. 33 and 67 are also supported.

If no value is given, the default is 50.

If the sidebar contents have a “natural” width less than the value given, it will stay that wide. the value is only used to set a maximum width.

2.3 Slideshows

 

You can insert an internal “slideshow”.

Clicking on the controls below…

first prev1 of 3next last

2.4 Splitting into Columns

Every now and then, I like to present two columns of material, side-by-side.

// Do something
void foo();
 

Like this, for example. The right column will wind up getting bumped down below the left.

// Do something
void foo();

This is not a particularly robust formatting, however, and things get ugly if the content is a bit too wide for the screen.

3 Hiding and Revealing Text

 
click to reveal
 

A variation on this is the ability to load long code listings, contained in a separate file providing both a link to the code as a separate HTML page and a click-to-reveal button to expand the listing in place.

unittest.h
#ifndef UNITTEST_H
#define UNITTEST_H

#include <string>

/*
 *  This class helps support self-checking unit tests.
 *  
 *  A small collection of test assertions (inspired by the JUNIT
 *  package for Java is supported). The number of successes and failures
 *  of these assertions are tallied and can be accessed at any time (typically
 *  at the end of the test suite).
 *
 *  In addition, detailed error messages are printed for the first
 *  DETAIL_LIMIT failures. (After that additional failures are tallied
 *  but not printed.)
 *
 */

class UnitTest {
private:
  static long numSuccesses;
  static long numFailures;
  static long DETAIL_LIMIT;
  static long NOTICE_INTERVAL;

public:
  // The main test function - normally called via one of the macros
  // declared following this class.
  static void checkTest (bool condition, const char* conditionStr,
			 const char* fileName, int lineNumber);
  static void checkTest (bool condition, const std::string& conditionStr,
			 const char* fileName, int lineNumber);


  // Summary info about tests conducted so far
  static long getNumTests()     {return numSuccesses + numFailures;} 
  static long getNumFailures()  {return numFailures;} 
  static long getNumSuccesses() {return numSuccesses;} 
  
  // Change the number of detailed messages to be printed.
  static void setDetailLimit (long limit) {DETAIL_LIMIT = limit;}

  // Start a fresh tally.
  static void reset() {numSuccesses = numFailures = 0L; NOTICE_INTERVAL = 10L;}

  // Print a simple summary report
  static void report (std::ostream& out);
};


/**
 *   Macros - actual tests will invoke one of these
 */

#define assertTrue(cond) UnitTest::checkTest (cond, #cond, __FILE__, __LINE__)
#define assertFalse(cond) UnitTest::checkTest (!(cond), "!( ## cond ## )", __FILE__, __LINE__)

#define assertEqual( x, y ) UnitTest::checkTest ((x)==(y),\
                            "assertEqual("  #x "," #y ")", \
                            __FILE__, __LINE__)

#define assertNotEqual( x , y ) assertFalse ((x)==(y))

#define assertNull(x) checkTest ((x)==0)

#define assertNotNull(x) checkTest ((x)!=0)

#define succeed UnitTest::checkTest (true, "succeed", __FILE__, __LINE__)

#define fail UnitTest::checkTest (false, "fail", __FILE__, __LINE__)




#endif

A link is included to the unmodified source code file (to facilitate downloading), so that file should be one of the support files for the document set.

4 Graphics

4.1 Positioning Graphics

 

As noted earlier, Markdown already has support for inserting graphics into a page. You can place graphics inline like this: lab icon.

You can also type HTML img tags directly, which makes it possible to use the “align” attribute to position your graphics.

A problem with this can occur when long vertical graphics are accompanied by relatively short text (particularly when viewed on a wide screen).

The floating graphics can stack up on one another, leading to a confusing layout.

 

As a fix for this, I provide a CSS style class noFloat with the attribute clear:both. This can be inserted as an empty paragraph:

This has the effect of forcing any following text and graphics to be positioned after the end of floating graphics, sidebars, or other floating content.

However, I find that I often wind up using the same graphics sequences over and over, so I have some shortcut commands. The command \picOnRight(_filename_,_pct_) is equivalent to

<div class="noFloat"></div>
<img src="filename.png" align="right"
     style="max-width: pct%/>"

It drops below any existing floating content, then inserts a floating graphic on the right, reducing the graphic’s size only if it exceeds a width of pct%.

 

 

Similarly, I can insert graphics on the left instead of on the right.

 

Or I can put them inline within the text.

 

 
an array of books

The ‘A’ variants of these commands add simple (no double-quotations or commas) alt-text for accessibility.

4.2 Generated Graphics (PlantUML & Mermaid)

4.2.1 PlantUML

 

If a code block (introduced with three back-ticks) is labeled with the language name “plantuml”, then the code block will be replaced by a graphic representing a UML diagram as interpreted by PlantUML. (This mechanism is similar to the support for PlantUML in the GitHub dialect of Markdown.)

 
 

It is possible to add CSS styles to the generated image using the class= modifier. The most obvious application of this is to cause the image to float on the right or left.

 

Change the “right” to “left” to float on the other side.

Change to “center” for a centered, non-floating figure.

 

It is actually possible to add multiple CSS class names (inside single-quotes).

 

(Although you would have to examine the generated HTML to see that the useless class “foobar” is attached to the image.)

4.2.2 Mermaid

Support is also available for Mermaid, another Markdown-friendly graphics processor.

 

If a code block (introduced with three back-ticks) is labeled with the language name “mermaid”, then the code block will be replaced by a graphic representing a diagram as interpreted by Mermaid.

graph TD need[Need a graphic] inUML{Is it UML?} need --> inUML thenPart[I prefer PlantUML] inUML --yes--> thenPart elsePart[Use Mermaid] inUML --no--> elsePart joined([done]) thenPart --> joined elsePart --> joined
 

As with the PlantUML diagrams, class info can be attached to alter the formatting.