MultiMarkdown Composer v5 Themes

(NOTE: This is a draft document. Feedback welcome!)

Introduction

The format for themes has been redesigned for consistency and flexibility. v2 of the theme syntax is used for both nvUltra and MultiMarkdown Composer v5.

v2 Themes are similar to the JSON theming used in MultiMarkdown Composer 4, but there are some differences. This document describes how these files work, and how you can modify them.

Themes are used to control two separate things:

  • Window chrome styling (e.g. window background color, table colors, etc.)
  • Syntax highlighting attributes for MultiMarkdown syntax

File Location

For nvUltra and MultiMarkdown Composer, Themes (and other customization files) are located in your ~/Library folder. The easiest way to locate them is through the application's Preferences dialog. In the Appearance tab, for example, you can use the Open Themes Button to go directly to the proper folder.

The same folders are used for nvUltra and MultiMarkdown Composer v5, so that you have the same customizations available for both applications.

File Format

Themes for nvUltra and MultiMarkdown Composer are written in JSON.

If you are having trouble, a good first step is to ensure that your file is written in valid JSON. A good place to do that is here.

Colors

Colors are specified using standard/common HTML notation:

  • #RRGGBB - no alpha
  • #RRGGBBAA - support for alpha
  • #RGB - single digit variant
  • #RGBA - single digit with alpha
  • RGB/RRGGBB - # is optional

Window Chrome

Themes are used to style various elements within the windows:

  • searchField
  • tableView
  • tableViewHighlighted
  • tableViewInactive
  • textView
  • window

Attributes applied at the top level serve as a default for all elements.

Window Chrome Example

{
    "darkWindow" : true,
    "lightWindow" : false,
    "transparentTitlebar" : true,

    "backgroundColor" : "#43484C",
    "foregroundColor" : "#dddddd",
    "selectionBackgroundColor" : "#990000",
    "caretColor" : "#eeeeee",

    "searchField" : {
        "backgroundColor" : "#6B7277"
    },

    "tableView" : {
        "fontName" : "Avenir",
        "fontSize" : 14,
        "rowHeight" : 34,
        "drawFocusRing" : false,
        "drawBorder" : false,
        "horizontalPadding" : 8,
        "verticalPadding" : 0
    },

    "tableViewHighlighted" : {
        "backgroundColor" : "#990000"
    },

    "tableViewInactive" : {
        "backgroundColor" : "#dddddd",
        "foregroundColor" : "#990000"
    },

    "textView" : {
        "backgroundColor" : "#eeeeee",
        "foregroundColor" : "#000",
        "selectionBackgroundColor" : "#bbb",
        "caretColor" : "#000"
    }
}

This example sets top level default values, and then overrides for specific elements where appropriate.

Window Chrome Attributes

Top level elements include:

  • darkWindow - boolean to force macOS dark mode
  • lightWindow - boolean to force macOS light mode
  • transparentTitlebar - boolean to use transparent titlebar style for the window's titlebar

The attributes used for individual elements include:

  • backgroundColor - Color applied to background
  • caretColor - Color for the insertion point caret
  • drawFocusRing - Boolean to specify whether table should draw a focus ring
  • drawBorder - Boolean to specifiy whether table should draw a surrounding border frame
  • fontName - The name of the font to use, must match the name expected by the system
  • fontScale - Relative size to element based on size of parent element
  • fontSize - Absolute size to apply to font
  • foregroundColor -- Color applied to text
  • horizontalPadding - Specify horizontal margins in tables
  • rowHeight - Specify row height for tables
  • selectionBackgroundColor - Background color for selected text
  • selectionForegroundColor - Foreground color for selected text
  • verticalPadding - Specify vertical margins in tables

(Not every attribute is used for every element type)

Syntax Highlighting Example

A basic example of the syntax highlighting functionality:

{
    "foregroundColor" : "#dddddd",
    "backgroundColor" : "#43484C",

    "markup" : {
        "foregroundColor" : "#40607F"
    },

    "strong" : {
        "bold" : 1,
        "markupForegroundColor" : "#F00"
    },

    "emphasis" : {
        "italic" : 1,
        "markupForegroundColor" : "#0F0"
    }
}

This simple example sets a default foreground and background color, then adds a different foreground color for all markup elements. Strong (bold) elements are set to use a bold font variant, and use a different markup color. Similarly, emphasis (italics) use an italicized font variant and custom markup color.

Syntax Highlighting Element Properties

Each element can be assigned the following properties

  1. backgroundColor - Color applied to background
  2. bold - Boolean to apply bold font style
  3. fontName - The name of the font to use, must match the name expected by the system
  4. fontScale - Relative size to element based on size of parent element
  5. fontSize - Absolute size to apply to font
  6. foregroundColor - Color applied to text
  7. italic - Boolean to apply italicized font style
  8. leftIndent - Left margin to apply (block level elements only)
  9. leftFirstIndent - Separate indentation for the first line of a paragraph (block level elements only)
  10. markupBackgroundColor - Background color applied to markup elements (if appropriate)
  11. markupForegroundColor - Color applied to markup elements (if appropriate)
  12. mono - Boolean value to apply a monospace font
  13. paraSpace - Space between paragraphs (measured in units of font size) (block level elements only)
  14. paraSpaceBefore - Space between start of paragraph and its content (measured in units of font size) (block level elements only)
  15. rightIndent - Right margin to apply (block level elements only)
  16. superscript - Apply supescript vertical alignment style (1 = superscript, -1 = subscript)
  17. textAlignment - Apply text alignment style (0 = natural, 1 = left, 2 = right, 3 = justified, 4 = center) (block level elements only)
  18. underline - Apply underline style (0 = disable, other numbers based on operating system. I recommend starting with 1 and experimenting.)
  19. writingDirection - Right-to-left, Left-to-Right, etc. (0 = natural, 1 = LTR, 2 = RTL ) (block level elements only)

Syntax Highlighting Element Names

This is a list of the various element types that can be included in your theme file. They are broken into groups of related elements, and include the key used in the theme file, followed by a short description, followed by the token type used by MultiMarkdown. This last part is generally only useful for developers who are using libMultiMarkdown in their own projects.

Sometimes multiple token types are set to the same values (e.g. BLOCK_H1 and BLOCK_SETEXT_1). They may appear more than once in the tables, even though you can't set them to different values.

  • Sample element

    • sampleThemeName - Optional description (MMD TOKEN NAME - useful for developers using libMultiMarkdown in their own projects)
  • Blocks

    • blockquote - Block quote (BLOCK_BLOCKQUOTE)
    • codeBlock - Indented code block (BLOCK_CODE_INDENTED)
    • codeBlock - Fenced code block (BLOCK_CODE_FENCED)
    • definitionList - Definition list (BLOCK_DEFLIST)
    • definition - Individual definition (BLOCK_DEFINITION)
    • metadata - Document metadata (BLOCK_META)
    • table - Table (BLOCK_TABLE)
  • CriticMarkup

    • criticAddition - CriticMarkup insertion (PAIR_CRITIC_ADD)
    • criticComment - CriticMarkup comment (PAIR_CRITIC_COM)
    • criticDeletion - CriticMarkup deletion (PAIR_CRITIC_DEL)
    • criticHighlight - CriticMarkup highlighting (PAIR_CRITIC_HI)
    • criticSubstitution - CriticMarkup substitution (deletion component) (PAIR_CRITIC_SUB_DEL)
    • criticSubstitution - CriticMarkup substitution (insertion component) (PAIR_CRITIC_SUB_ADD)
  • HTML

    • htmlComment - HTML comments (e.g. <!-- foo -->) (PAIR_HTML_COMMENT)
    • html - Raw HTML elements (BLOCK_HTML)
    • html - HTML character entities (e.g. &copy;) (HTML_ENTITY)
  • Headings

    • heading - Default properties for all headings (BLOCK_HEADING)
    • heading1 - Level 1 heading (e.g. # foo #) (BLOCK_H1)
    • heading2 - Level 2 heading (e.g. ## foo ##) (BLOCK_H2)
    • heading3 - Level 3 heading (e.g. ### foo ###) (BLOCK_H3)
    • heading4 - Level 4 heading (e.g. #### foo ####) (BLOCK_H4)
    • heading5 - Level 5 heading (e.g. ##### foo #####) (BLOCK_H5)
    • heading6 - Level 6 heading (e.g. ###### foo ######) (BLOCK_H6)
    • heading1 - Level 1 Setext heading (BLOCK_SETEXT_1)
    • heading2 - Level 2 Setext heading (BLOCK_SETEXT_2)
  • Lists

    • bulletList - Bulleted list (BLOCK_LIST_BULLETED)
    • bulletList - Bulleted list with implied <p> (BLOCK_LIST_BULLETED_LOOSE)
    • orderedList - Enumerated list (BLOCK_LIST_ENUMERATED)
    • orderedList - Enumerated list with implied <p> (BLOCK_LIST_ENUMERATED_LOOSE)
    • listItem - Individual list item (BLOCK_LIST_ITEM)
    • listItem - Single line list item (BLOCK_LIST_ITEM_TIGHT)
  • Markup

    • markup - General markup formatting (MARKUP)
    • toc - Table of contents (BLOCK_TOC)
    • hr - Horizontal rule (divider line) (BLOCK_HR)
  • Math

    • math - MultiMarkdown parenthetical math (e.g. \\(...\\)) (PAIR_MATH)
    • math - MultiMarkdown bracketed math (e.g. \\[...\\]) (PAIR_MATH)
    • math - MultiMarkdown dollar math (e.g. $...$ or $$...$$) (PAIR_MATH)
  • Paired Parentheses

    • linkParens - URL portion of an inline link (e.g. [foo](bar)) (PAIR_PAREN_LINK)
  • Pairs

    • pairs - Generic styling for paired elements (e.g. those that start and end with paired characters such as "...") (PAIRS)
    • angles - Paired angle markers (e.g. <...>) (PAIR_ANGLE)
    • braces - Paired braces (e.g. {...}) (PAIR_BRACE)
    • bracesDouble - Paired double braces (e.g. {{...}}) (PAIR_BRACES)
    • brackets - Paired brackets (e.g. [...]) (PAIR_BRACKET)
    • parens - Paired parentheses (e.g. (...)) (PAIR_PAREN)
    • quoteDouble - Paired double quotation marks (e.g. "...") (PAIR_QUOTE_DOUBLE)
    • quoteSingle - Paired single quotation marks (e.g. '...') (PAIR_QUOTE_SINGLE)
  • Pairs - Brackets

    • abbreviation - Abbreviation brackets (e.g. [>foo]) (PAIR_BRACKET_ABBREVIATION)
    • citation - Citation brackets (e.g. [#foo]) (PAIR_BRACKET_CITATION)
    • footnote - Footnote brackets (e.g. [^foo]) (PAIR_BRACKET_FOOTNOTE)
    • glossary - Glossary brackets (e.g. [?foo]) (PAIR_BRACKET_GLOSSARY)
    • image - Image brackets (e.g. ![foo]) (PAIR_BRACKET_IMAGE)
    • variable - Variable brackets (e.g. [%foo]) (PAIR_BRACKET_VARIABLE)
  • References

    • definitionAbbreviation - Abbreviation definition (e.g. [>foo]: bar) (BLOCK_DEF_ABBREVIATION)
    • definitionCitation - Citation definition (e.g. [#foo]: bar) (BLOCK_DEF_CITATION)
    • definitionFootnote - Footnote definition (e.g. [^foo]: bar) (BLOCK_DEF_FOOTNOTE)
    • definitionGlossary - Glossary definition (e.g. [?foo]: bar) (BLOCK_DEF_GLOSSARY)
    • definitionLink - Link/URL definition (e.g. [foo]: bar) (BLOCK_DEF_LINK)
  • Spans

    • codeSpan - Code text (e.g. `foo`) (PAIR_BACKTICK)
    • emphasis - Emphasized text (e.g. *foo*) (PAIR_EMPH)
    • strong - Strong text (e.g. **foo**) (PAIR_STRONG)
    • subscript - Subscript (e.g. x~y~) (PAIR_SUBSCRIPT)
    • superscript - Superscript (e.g. m^2^)(NOTE: Does not currently work on m^2) (PAIR_SUPERSCRIPT)

Style "Cascading"

All syntax highlighting elements inherit attributes from root level attributes. For example, you can set a default foregroundColor, which is then inherited by all other elements.

Additionally, some syntax highlighting elements inherit their formatting from a "parent" element, but can be overridden for more flexibility.

{
    "foregroundColor" : "#F00",
    "heading" : {
        "foregroundColor" : "#0F0"
    },
    "heading1" : {
        "foregroundColor" : "#00F"
    }
}

In this example, the default text color is red (#F00), which is inherited by all elements. heading overrides this with a green (#0F0) foreground for all headings. Except for level 1 headers (# Foo #), which further override the text color to blue (#00F).

This inheritance model (somewhat similar in philosophy to CSS) offers a great deal of flexibility, while also allowing you to minimize duplicating attributes that are used throughout the document.

This lists the parent token types along with their "children":

  • definitionList - (BLOCK_DEFLIST)
    • definition - Individual definition (BLOCK_DEFINITION)
  • heading - (BLOCK_HEADING)
    • heading1 - Level 1 heading (e.g. # foo #) (BLOCK_H1)
    • heading2 - Level 2 heading (e.g. ## foo ##) (BLOCK_H2)
    • heading3 - Level 3 heading (e.g. ### foo ###) (BLOCK_H3)
    • heading4 - Level 4 heading (e.g. #### foo ####) (BLOCK_H4)
    • heading5 - Level 5 heading (e.g. ##### foo #####) (BLOCK_H5)
    • heading6 - Level 6 heading (e.g. ###### foo ######) (BLOCK_H6)
    • heading1 - Level 1 Setext heading (BLOCK_SETEXT_1)
    • heading2 - Level 2 Setext heading (BLOCK_SETEXT_2)
  • html - (BLOCK_HTML)
    • htmlComment - HTML comments (e.g. <!-- foo -->) (PAIR_HTML_COMMENT)
  • markup - (MARKUP)
    • toc - Table of contents (BLOCK_TOC)
    • hr - Horizontal rule (divider line) (BLOCK_HR)
  • pairs - (PAIRS)
    • angles - Paired angle markers (e.g. <...>) (PAIR_ANGLE)
    • braces - Paired braces (e.g. {...}) (PAIR_BRACE)
    • bracesDouble - Paired double braces (e.g. {{...}}) (PAIR_BRACES)
    • brackets - Paired brackets (e.g. [...]) (PAIR_BRACKET)
    • parens - Paired parentheses (e.g. (...)) (PAIR_PAREN)
    • quoteDouble - Paired double quotation marks (e.g. "...") (PAIR_QUOTE_DOUBLE)
    • quoteSingle - Paired single quotation marks (e.g. '...') (PAIR_QUOTE_SINGLE)
  • brackets - (PAIR_BRACKET)
    • abbreviation - Abbreviation brackets (e.g. [>foo]) (PAIR_BRACKET_ABBREVIATION)
    • citation - Citation brackets (e.g. [#foo]) (PAIR_BRACKET_CITATION)
    • footnote - Footnote brackets (e.g. [^foo]) (PAIR_BRACKET_FOOTNOTE)
    • glossary - Glossary brackets (e.g. [?foo]) (PAIR_BRACKET_GLOSSARY)
    • image - Image brackets (e.g. ![foo]) (PAIR_BRACKET_IMAGE)
    • variable - Variable brackets (e.g. [%foo]) (PAIR_BRACKET_VARIABLE)
  • parens - (PAIR_PAREN)
    • linkParens - URL portion of an inline link (e.g. [foo](bar)) (PAIR_PAREN_LINK)

How to Customize Themes

If you're going to customize themes, I recommend the following:

  1. Start by duplicating an existing theme and then modifying it gradually to get the hang of things. The themes that come with Composer make use of most of the features and show you the general idea.

  2. When building your own, make use of the cascading design. For example, create a style for all headings, and then change what needs to be changed for specific instances. Maybe you want level 1 headings to be a different size, but all colors should be the same.

  3. Be aware that specifying certain properties will override the user's preferences and may lead to confusion. If you intend to share your theme with others, only use those properties if you have a good reason. fontName, fontSize, and writingDirection are some examples of keys to use cautiously.