MultiMarkdown Composer v4 Themes
Background
Composer v2 supported Style Sheet (aka "Styles"). These were written in Apple's Property List format and allowed custom styling for the editor as well as CSS for the Preview.
Composer v3 (beta) changed a few things:
-
Renamed Style Sheets to "Themes". For some reason people kept confusing them with CSS, even though they look completely different. Whatever. ;)
-
The format was still Plist, but the keys were changed slightly and they used a new file extension for disambiguation.
Composer v4 changes things again, to a much better option.
MultiMarkdown Composer Themes (V4)
Themes for v4 are written in JSON. At a superficial level it is similar to the Plist format, but is more flexible and more commonly supported. (In fact, all of the customization files for v4 are written in JSON.) I did this because:
-
I can use a standard library to parse and load these files on any platform, not just macOS or iOS.
-
The JSON format is widely used and supported, so you can use JSON-aware editors to help you troubleshoot your changes while editing.
-
The library I wrote to handle themes for syntax highlighting (and the other features) are written in cross-platform C -- it didn't make sense to stick with a format limited to macOS/iOS devices.
There are many resources online to teach you about the JSON format. Google your own to learn the basics, but you'll probably pick it up along the way.
Colors
Colors are specified using standard/common HTML notation:
#RRGGBB
- no alpha#RRGGBBAA
- support for alpha#RGB
- single digit variantRRGGBB
-#
is optional
Global Properties
There are several properties that apply to the entire window/document:
selectionColor
- color applied to selected textcaretColor
- color applied to the insertion marker ("caret")lineHeight
- line height spacing (e.g. 2.0 = double spaced lines) (Overrides application preferences)horizontalPadding
- left/right padding around the entire document ("margins") (Overrides application preferences)verticalPadding
- top/bottom padding (Overrides application preferences)sidebarBackgroundColor
- background color for the sidebars (e.g. the Table of Contents table)sidebarTextColor
- text color for text in the sidebar tablessidebarTextColorHighlighted
- text color when an item is selected in the tablesidebarTextColorHighlightedInactive
- text color when the table loses focussidebarHighlightColor
- highlight color for selected item in the tablesidebarHighlightColorInactive
- highlight color when table loses focus
These properties are ignored anywhere other than the document root.
Element Properties
Individual elements in the text can have custom properties applied (including the document root, where these are applied as default to the entire text):
foregroundColor
- text color for elementbackgroundColor
- background color for elementfontName
- name of the desired font (you can only choose one, so choose carefully. ;) (Overrides application preferences)fontSize
- size for the text of the element (Overrides application preferences)fontScale
- apply a relative size instead of an absolute size. (Overrides application preferences)bold
- apply bold styling (if available), 1 = enableitalic
- apply italics (if available), 1 = enableunderline
- apply different styles of underlining. 0 = disable, other numbers use different styles according to your operating system. I recommend 1 for simplicity, but you can try larger numbers.superscript
- raise the element above the text baselinesubscript
- lower the element below the text baselineleftIndent
- Indent element from the left marginleftFirstIndent
- Separate left indent for first line of text that wraps across multiple lines in the text view (Remember that a paragraph in Markdown can consist of multiple lines of text, but thatreturn
orenter
splits text into multiple paragraphs in macOS and iOS. You'll have to decide how you want to handle this.)rightIndent
- Indent from the right marginparaSpaceBefore
- extra spacing before a paragraphparaSpace
- extra spacing after a paragraphtextAlignment
-- apply specific text alignment styles, 1 = left, 2 = right, 3 = justified, 4 = center
Element Names
The elements currently available for customization include (NOTE: Indented lists inherit properties from their ancestors. For example pairs->brackets->abbreviation. This limits repetition while preserving flexibility):
- CriticMarkup
criticAddition
- CriticMarkup insertioncriticDeletion
- CriticMarkup deletioncriticComment
- CriticMarkup commentcriticHighlight
- CriticMarkup highlightcriticSubstitution
- CriticMarkup substitution
- Block elements
blockquote
- block quotescodeBlock
- indented or fenced code blocksmath
- math blockmetadata
- document metadatatable
- tables
- Definition lists
definitionList
-- Definition listsdefinition
-- Individual definition
- Headings
heading
- default for all headingsheading1
- level 1 heading (e.g.# foo #
)heading2
heading3
heading4
heading5
heading6
- HTML
html
- HTML elementshtmlComment
- HTML comments (e.g.<!-- foo -->
) (NOTE: An html comment that is a Markdown block by itself will be consideredhtml
, nothtmlComment
)
- Lists
bulletList
- bulleted lists (e.g* foo
)orderedList
- enumerated lists (e.g.1. foo
)listItem
- individual list items
- Reference definitions
definitionAbbreviation
- abbreviation definitions (e.g.[>foo]: bar
)definitionCitation
- citation definitions (e.g.[#foo]: bar
)definitionFootnote
- footnote definitions (e.g.[^foo]: bar
)definitionGlossary
- glossary definitions (e.g.[?foo]: bar
)definitionLink
- link definitions (e.g.[foo]: bar
)
- Text elements
codeSpan
- code text (e.g.`foo`
)emphasis
- emphasized text (e.g.*foo*
)strong
- strong text (e.g.**foo**
)superscript
- superscripts (e.g.m^2^
) (NOTE: Does not currently work onm^2
)subscript
- subscripts (e.g.x~y~
)
- Paired elements
pairs
- generic styling for paired elements (e.g. those that start and end with paired characters such as"..."
)angles
- paired angle markers (<...>
)braces
- paired braces ({...}
)brackets
- specific styling for paired brackets ([...]
)abbreviation
- abbreviation brackets ([>...]
)citation
- citation brackets ([#...]
)footnote
- footnote brackets ([^...]
)glossary
- glossary brackets ([?...]
)image
- image brackets (![...]
)variable
- variable brackets ([%...]
)
parens
- paired parenthesis ((...)
)quoteDouble
- paired double quotation marks ("..."
)quoteSingle
- paired single quotation marks ('...'
)
- Other
markup
- styling for characters used in MultiMarkdown markuphr
-- horizontal rules (e.g.----
)toc
-- Table of Contents marker (e.g.{{TOC}}
)
Previews
The preview pane is no longer controlled by Themes. They use a regular CSS file that can be chosen (and customized) independently from the editor themes.
Comments
You'll notice that there is not a specific styling for links as opposed to regular brackets. This is because there is not a separate markup to disambiguate links without a bit of processing.
For example, [foo]
could be a link if there is a definition for it in the document, otherwise it's just text in some brackets.
However, [foo](bar)
will apply the same bracket styling to the (bar)
if it immediately follows [foo]
, since that implies that a link is intended.
Suggestions
If you're going to customize themes, I recommend the following:
-
Start by adjusting an existing theme 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.
-
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.
-
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.
-
The
Empty.theme
is designed to be a starting place. It applies white background, black text, standard Aqua colors for the sidebars, and "standard" CriticMarkup colors. It sets a monospaced font for code (Courier), a few indented margins, and a basic markup color. Otherwise it's pretty empty.