-
Notifications
You must be signed in to change notification settings - Fork 244
Customization
Note
This page is for users who want to customize MarkEdit's appearance and behavior. Developers who want to modify MarkEdit itself should refer to the Development Guide.
For contributors: please read Philosophy and Why MarkEdit before submitting PRs that introduce behavioral changes.
MarkEdit uses the following files for editor customizations and 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/pandoc.yaml
~/Library/Containers/app.cyan.markedit/Data/Documents/statistics-rules.json
~/Library/Containers/app.cyan.markedit/Data/Documents/settings.json
You can add your own style sheets and JavaScript code to override the app's appearance and behavior.
These files are located in MarkEdit's Documents folder, which you can also open from the main menu:
They affect only the main app. The appearance and behavior of the Quick Look extension cannot be customized.
Tip
After editing these files, restart the app for the changes to take effect. To debug editor customizations, right-click the editor and select Inspect Element to open the web inspector, or press Option-Command-I.
For pandoc.yaml and statistics-rules.json, learn more here.
To change the editor's appearance, open editor.css and add your custom style sheets.
For example, this style sheet gives the editor a more readable width when editing files in full screen.
.cm-content {
margin: 0 auto !important;
max-width: 800px !important;
}If you prefer wider margins when line numbers are hidden, try this:
.cm-content {
margin-left: 20px !important;
margin-right: 20px !important;
}Use editor.js to customize behavior. You can interact with window.editor; for all available interfaces, refer to index.ts.
For an advanced example that uses both files to add a width guide to the editor, see #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
Place your .css and .js files in these folders. The order in which the code is injected is not guaranteed.
Inspired by #627, MarkEdit now provides programmable interfaces through MarkEdit-api.
The global MarkEdit object provides many interfaces, including:
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 control the editor through CodeMirror extensions.
For a complete example, refer to Example (Markdown Table Editor) and MarkEdit Extensions.
To keep the app simple, we do not plan to add more built-in themes.
If you want to build your own themes, the best way to do it is to rely on the markedit-theming package.
Refer to MarkEdit Themes for examples.
As mentioned, we want to keep the settings clean, but we have seen growing demand for more options.
Tip
You can press Shift-Command-Comma to quickly edit this file with your default text editor.
You can add the schema to a JSON editor such as VS Code for type information and validation.
The ~/Library/Containers/app.cyan.markedit/Data/Documents/settings.json file provides these additional options. They are intended for advanced users and do not appear in the Settings panel. For example:
{
"editor.autoCharacterPairs" : true,
"editor.autoSaveWhenIdle" : false,
"editor.closeAlwaysConfirmsChanges" : false,
"editor.restoreLastSelection" : true,
"editor.indentBehavior" : "never",
"editor.writingToolsBehavior" : "limited",
"editor.undoGroupingInterval" : 300,
"editor.headerFontSizeDiffs" : [5, 3, 1],
"editor.visibleWhitespaceCharacter" : "·",
"editor.visibleLineBreakCharacter" : "¬",
"editor.searchNormalizers" : {
"[‘’]" : "'",
"[“”]" : "\""
},
"editor.nativeSearchQuerySync" : false,
"editor.toolbarTranslucency" : "default",
"editor.customToolbarItems" : [],
"general.updateBehavior" : "quiet",
"general.defaultOpenDirectory" : "~/Downloads",
"general.defaultSaveDirectory" : "~/Desktop",
"general.disableOpenPanelOptions" : true,
"general.disableCorsRestrictions" : true,
"general.disabledWebKitFeatures" : [],
"general.preferredTerminalApp" : null,
"general.mainWindowHotKey" : {
"key" : "M",
"modifiers" : [
"Shift",
"Command",
"Option"
]
}
}The file must contain valid JSON and strictly follow the specification.
All keys are optional, but any values you provide must follow the specification. Here are two examples of invalid values in settings.json:
"editor.autoCharacterPairs" : "yes" // The value type is not boolean
"editor.indentBehavior" : "all" // The value is not recognized
MarkEdit uses strict validation, so any invalid value makes the entire settings.json file invalid.
Controls whether selections are automatically wrapped with characters such as [] and **.
If not provided, the default behavior is to wrap.
Controls whether changes are saved after you stop typing for a while.
When enabled, the editor does not show an "Edited" label after making changes.
This feature requires editor.closeAlwaysConfirmsChanges to be disabled.
If not provided, changes are not saved automatically.
This is equivalent to "Ask to keep changes when closing documents" in System Settings, but applies only to MarkEdit.
If not provided, the system setting is used.
Controls whether the selection range from the previous editing session is restored.
If not provided, the default behavior is to restore.
Controls whether paragraphs or lines are indented like list items.
Possible values are (letter case matters): paragraph to indent all paragraphs, line to indent all lines, and never to disable indentation.
If not provided, indentation is disabled.
On macOS Sequoia and later, controls the behavior of Writing Tools.
Possible values are (letter case matters): complete for an inline experience, limited for a panel experience, and none to disable Writing Tools.
If not provided, the system setting is used.
The maximum time, in milliseconds, between edits that are grouped into a single undo step.
If not provided, the default value is 300ms.
An array of numbers that dynamically increase the font size of headings, from heading 1 to heading 6.
If not provided, the default values are [5, 3, 1]. For example, if the body text is 15px, heading 1 will be 20px.
The character used to display whitespace. This setting takes effect only when "Render Invisibles" is enabled.
If not provided,
·is used. To hide them, use an empty string.
The character used to display line breaks. This setting takes effect only when "Render Invisibles" is enabled.
If not provided,
¬is used. To hide them, use an empty string.
A key-value map of search-query normalizers. Use a regular expression as the key and the replacement string as the value.
For example, the following configuration ignores the difference between curly and straight quotes:
{
"[‘’]" : "'",
"[“”]" : "\""
}If not provided, the default value is an empty map.
Controls whether search queries are synchronized with native apps. For example, it can automatically populate the search bar with a query entered in TextEdit.
If not provided, search queries from other apps are ignored.
Controls the toolbar translucency. Available presets are readable, default, and vibrant.
For finer control, use a custom three-number string in the form backdropBlur, tintedOpacity, plainOpacity.
For example, default internally resolves to 8, 0.7, 0.4.
This requires macOS Tahoe or later.
If not provided, the default value is
default.
Defines custom toolbar items like this:
[
{
"title" : "View Mode",
"icon" : "eye",
"menuName" : "View Mode"
}
]The menuName value must refer to a valid submenu in the main menu. If the menu item represents an action, specify actionName instead.
The icon value must be a valid SF Symbol name. You can browse available symbols using the official SF Symbols app or third-party websites.
After adding these items, relaunch the app and customize the toolbar to use them.
Controls how new app versions are presented. Valid values are never, quiet, notify, and automatic (installs on next launch).
If not provided, the default value is
quiet.
Controls whether the app checks for updates. Set it to false to disable automatic update checks.
Warning
Deprecated. Use general.updateBehavior instead.
The default directory for opening files. For example, always open files from ~/Downloads.
If not provided, the default behavior is to use the last accessed directory.
The default directory for saving files. For example, always save files to ~/Desktop.
If not provided, the default behavior is to use the last accessed directory.
Controls whether options in the file-open panel are disabled.
If not provided, the default value is true on macOS Tahoe and later because enabling these options can cause performance issues.
Controls whether CORS restrictions are disabled, allowing the Fetch API to work with any URL.
If not provided, CORS restrictions are not enforced.
An array of feature names to disable in WebKit. See UnifiedWebPreferences.yaml for the full list of names.
For example: ["NotificationsEnabled", "PushAPIEnabled"].
If not provided, the default value is an empty array.
The bundle identifier of the preferred terminal app used to run Pandoc commands. For example, "com.apple.Terminal".
If not provided, MarkEdit detects installed popular terminal apps.
Defines a hotkey for toggling the visibility of the main window. Use the following format (letter case matters):
{
"key" : "M",
"modifiers" : [
"Shift",
"Command",
"Option"
]
}For printable characters, use their uppercase form. For example, M, F, =, or ..
For non-printable characters, use their names. For example, Tab, Return, or F1. See the list of 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.
If you are new to frontend development, we recommend Mozilla's CSS reference and JavaScript reference.
For the best experience in both light and dark modes, we recommend reading Dark Mode in CSS and Dark Mode Support in WebKit.
Because MarkEdit uses CodeMirror, you can refer to its styling guide to learn about the available selectors.
We also enable classHighlighter to provide stable token classes prefixed with tok-. Refer to its documentation for details.
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 |
| Task | cm-md-taskMarker, cm-md-taskMarker-checked, -unchecked |
| URL | cm-md-url |
| Link | cm-md-link, cm-md-linkMark |
| Code | cm-md-inlineCode, cm-md-codeBlockWrapper, cm-md-codeBlock |
| Table | cm-md-tableWrapper, cm-md-table |
| Front Matter | cm-md-frontMatterWrapper, cm-md-frontMatter |
| Horizontal Rule | cm-md-horizontalRule |
You may need to use the !important syntax to give your style sheets priority over the built-in styles, although it is not always necessary.
For example, to customize the font used for code blocks:
.cm-md-codeBlock, .cm-md-codeBlock * {
font-family: Menlo !important;
}The customization files mentioned above can be linked symbolically. 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
This allows the files to be synchronized across devices through iCloud. After creating the symbolic link, grant access to the folder containing the original file, then restart the app. In this example, select the folder in the iCloud container.
For more details, please check out #537.
Note
You must use ln -s; an alias created in Finder does not work the same way.
MarkEdit is sandboxed and can access only user-selected folders. Although an exception is applied, it may not work reliably. This step is necessary when MarkEdit cannot access files outside its sandbox.
To revoke access to granted folders, open Terminal and run:
defaults delete app.cyan.markedit general.granted-folder-bookmark
Tip
The entry can also be found from the "File" menu.