Skip to content

Customization

Gnohz Gniy edited this page Sep 10, 2024 · 34 revisions

Entries

MarkEdit relies on these files to customize some behaviors, including the editor and some advanced settings:

~/Library/Containers/app.cyan.markedit/Data/Documents/editor.css
~/Library/Containers/app.cyan.markedit/Data/Documents/editor.js
~/Library/Containers/app.cyan.markedit/Data/Documents/settings.json

You can add your own style sheets and JavaScript code to override appearance and behavior.

These files live in the Documents folder of MarkEdit, you can also open the folder from the main menu:

Open Documents Folder

Note they only affect the main app, the appearance and behavior of the Quick Look extension is not customizable.

After editing these files, restart the app to make them take effect. To debug editor customizations, right click the editor, select Inspect Element to show the web inspector (or press Option-Command-I).

Editor Appearance and Behavior

To change the appearance, just open editor.css and put your custom style sheets there.

For example, this style sheet enables "readable width" for the editor, it looks nicer when you prefer to edit files in full screen.

.cm-line {
  margin: 0 auto !important;
  max-width: 800px !important;
}

If you like more margins when line numbers are off, try this one:

.cm-content {
  margin-left: 20px !important;
  margin-right: 20px !important;
}

Similarly, editor.js is for customizing the behavior. There's window.editor to interact with, to check all available interfaces, refer to index.ts.

To leverage both files, here is also an advanced example showing us how to add a width guide to the editor: #416.

If you have lots of customizations and would like to manage them separately, there are now two folders:

~/Library/Containers/app.cyan.markedit/Data/Documents/styles
~/Library/Containers/app.cyan.markedit/Data/Documents/scripts

Put your .css and .js files in there and you're done. Please note that the order of code injection is not guaranteed.

MarkEdit-api

Inspired by #627, MarkEdit now supports programmable interfaces as MarkEdit-api.

There is a global object called MarkEdit that offers many interfaces:

interface MarkEdit {
  // CodeMirror EditorView instance of the current editor.
  editorView: EditorView;
  // Convenient text editing interfaces.
  editorAPI: TextEditable;
  // Add an extension to MarkEdit.
  addExtension: (extension: Extension) => void;
  // CodeMirror modules used by MarkEdit.
  codemirror: { view, state, language, commands, search };
  // Lezer modules used by MarkEdit.
  lezer: { common, highlight, lr },
}

You can take control of the editor by leveraging CodeMirror extensions.

For a complete example, refer to Example (Markdown Table Editor).

Advanced Settings

As mentioned, we would like to keep settings clean, but we have noticed an increasing demand for more settings.

The ~/Library/Containers/app.cyan.markedit/Data/Documents/settings.json file was introduced for that purpose, these settings are for Pro users and are not visible in the Settings panel. For example:

{
  "editor.autoCharacterPairs" : true,
  "editor.indentParagraphs" : false,
  "editor.writingToolsBehavior" : "complete",
  "general.mainWindowHotKey" : {
    "key" : "M",
    "modifiers" : [
      "Shift",
      "Command",
      "Option"
    ]
  }
}

The file must be a valid JSON format and follow the spec strictly.

Key values are all optional, but if they exist, they must follow the specification. Here are two examples of invalid key values in settings.json:

"editor.autoCharacterPairs" : 10    // The value type is not boolean
"editor.doesNotExist" : true        // The key does not exist

We don't like error-tolerant design, invalid key values will cause the entire settings.json file to be invalid.

editor.autoCharacterPairs

Whether to automatically wrap selections with characters like [], **, etc.

If not provided, the default behavior is to wrap.

editor.indentParagraphs

Whether to indent all paragraphs and blocks, similar to list items.

If not provided, the default behavior is not to do that.

editor.writingToolsBehavior

For macOS Sequoia and higher, controls the Writing Tools behavior.

Possible values are (letter case matters): complete for an inline experience, limited for a panel experience, and none to opt it out.

If not provided, the default behavior respects the system decision.

general.mainWindowHotKey

Define a hotkey to toggle the visibility of the main window. It must be in the following format (letter case matters):

{
  "key" : "M",
  "modifiers" : [
    "Shift",
    "Command",
    "Option"
  ]
}

For printable characters, just use their uppercase form. For example, M, F, =, ., etc.

For non-printable characters, user their names. For example, Tab, Return, F1 etc. (Check here for a list of all valid keys.)

Valid modifiers are Shift, Control, Command, and Option; the order does not matter.

If not provided, the app will not register a global hotkey.

References

If you are new to front-end development, we recommend documentations from Mozilla: CSS reference and JavaScript reference.

To have the best experience in both light mode and dark mode, we recommend taking a look Dark Mode in CSS and Dark Mode Support in WebKit.

Since we use a CodeMirror editor, you can check out the styling guide to learn selectors used in CodeMirror.

Also, we enabled classHighlighter to have stable classes for tokens, prefixed with tok-. Please check out the documentation to learn details.

Markdown Syntax Classes

Markdown elements in MarkEdit generally have a class name with a cm-md- prefix. Here is a quick reference:

Element Classes
Heading cm-md-header, cm-md-heading1, cm-md-heading2, ...
Bold cm-md-bold
Italic cm-md-italic
Strikethrough cm-md-strikethrough
Blockquote cm-md-quote, cm-md-quoteMark
List Mark cm-md-listMark
URL cm-md-url
Link cm-md-link, cm-md-linkMark
Code cm-md-inlineCode, cm-md-codeBlock
Table cm-md-table
Horizontal Rule cm-md-horizontalRule

Note, you often need to use the !important syntax to make sure your style sheets have higher priority than built-in ones (not always the case).

Theming Mechanisms

Please note that this is not intended to replace the theming system or extension system, and there are situations that this approach cannot help with.

To keep the app simple, we are not going to add more themes or theming mechanisms, check out #486 to learn more.

Leveraging Symbolic Links

The customization files mentioned above can be symbolic linked. For example, you can create a symbolic link like this:

ln -s ~/Library/Mobile\ Documents/com~apple~CloudDocs/MarkEdit/editor.css ~/Library/Containers/app.cyan.markedit/Data/Documents/editor.css

In that case, these files can be synced across devices via iCloud. After creating the symbolic link, you will need to grant access to the folder, because MarkEdit is sandboxed and only has access to user selected folders:

Grant Folder Access

Select the folder that contains the original file and restart the app to take effect. In our example, it should be the folder in the iCloud container.

For more details, please check out #537.

Note, you will have to use ln -s, creating an alias in Finder would not work the same way.