Link Search Menu Expand Document

Creating Syntaxes

Table of Contents

  1. What Do I Need to Know?
  2. File Format
  3. Editing Syntax Definitions
  4. Workflow for Editing Syntaxes
  5. Sample Files
  6. Root Level Elements
  7. Patterns
  8. Scopes
  9. Navigation Patterns
  10. Indentation Patterns
  11. Task Mark Definitions
  12. Link Definitions
  13. Autocomplete Definitions
  14. List Completion Definitions
  15. Feature Keys

What Do I Need to Know?

Syntax definitions rely heavily on regular expressions to identify patterns in text. A strong familiarity with regular expressions is needed to develop custom syntaxes.

File Format

Syntax definition files are stored in JSON format with UTF-8 encoding. Supported keys as described below. Additional keys will be ignored. When distributed, Drafts exports and imports using the .draftsSyntax file extension, but internally these are JSON files.

Editing Syntax Definitions

Drafts does not have a built-in editor for syntax definitions. Development of syntax definitions is done in JSON files outside of the app. For details, see developer mode information.

Since syntax definitions rely heavily on regular expression, we also recommend use of a regular expression tool/app to work on testing and regular expression patterns. There are many, the one we typically use is Regex 101.

Once a syntax definition is complete, it can be imported into Drafts to be used, and, if desired, shared to the Drafts Directory for other users.

Workflow for Editing Syntaxes

Generally speaking, the recommended workflow for developing a custom syntax is as below. These steps apply on both iOS and macOS.

  • Enable Developer Mode
  • In Drafts, choose an existing built-in or custom syntax that most closely matches the syntax you wish to develop. Select this syntax in editor preferences, and export is as a file using the available share options. Save this file in iCloud Drive/Drafts/Library/Syntaxes (you may have to create this folder).
  • Open your new syntax file in an external JSON editor, make your modifications, and save the file.
  • In Drafts, create a testing draft with sample text for your syntax, and select your new file-based syntax as the syntax assigned to the draft.
  • As you iterate and make changes to your syntax, save the file, and reload it in Drafts by either selecting a different draft and returning to your testing draft, or re-assigning the syntax to force it to reload from file.
  • When you are happy with your syntax, import it into Drafts as a custom syntax using the “Import” options in editor preferences.
  • The imported custom syntax can be used in regular production mode.
  • Disable Developer Mode.

If you are making modifications to a syntax you have worked on in the past, when you use the “Import” feature, you will be offered the option to replace the version you have imported in the past, or import as a new custom syntax.

Sample Files

Complete example syntax definitions:

Other demo syntaxes:

  • Demo-Hashtags.json: Example patterns to highlight Twitter-style #hashtags and @mentions.
  • Demo-Rainbow.json: A silly example which simply colorizes the word “rainbow” when typed in a draft.
  • Demo-Tasks.json: Demostrates a few more advanced possibilities for tappable/clickable task elements in text.

Root Level Elements

The root of the JSON file should be a object which defines the following root element keys:

  • name [string, required]: A friendly name for the Syntax definition. Used in user interface for selection.
  • author [string]: Source credit for who created this theme. This might be your Drafts Community username, Twitter handle, or similar.
  • description [string, required]: Description of the syntax with more details about what is supported by the definition. Used in user interface elements to assist user in selecting syntaxes. Markdown can be included and will be rendered if this syntax is posted to the Directory.
  • sampleText [string, required]: A brief sample text that demonstrates key features supported in the syntax. This text will be displayed in the syntax manager in Drafts.
  • rangeExtensionType [object, required]: Controls how many characters are examined for syntax highlighting changes when text is changed in the document. Most objects will have a single default entry. It is also possible to have separate iOS and macOS entries if it makes sense to have different rangeExtensionTypes by platform for performance reasons. Syntax definitions should select the least of these as necessary to ensure that changes to the text are properly reflected. One of the below values:
    • none: Only for the changed text.
    • line: The entire containing line of the changed text.
    • lineExtended: Include the line before and line after the changes.
    • lookAround500: Extend evaluated range up to 500 characters before and after the changes.
    • lookAround1000: Extend evaluated range up to 1000 characters before and after the changes.
    • lookAround2000: Extend evaluated range up to 2000 characters before and after the changes.
    • fullText: Re-evaluate the entire text when any changes occur.
  • patterns [array, required]: Pattern definitions for the syntax. See Patterns for details.
  • linkDefinitions [array, required]: Used to create live links within a document. See Link Definitions for details.
  • navigationPatterns [array, required]: Definitions used to build in-document navigation markers. See Navigation Patterns for details.
  • indentationPatterns [array, required]: Definitions used to define blocks with indentation, such as Markdown lists. See Indentation Patterns for details.
  • taskMarkDefinitions [array, required]: Definitions used to define tap/clickable tasks in the text. See Task Mark Definitions for details.

Patterns

The patterns key is the heart of the syntax definition, and defines the array of regular expression patterns to apply to identify markup in the text. When changes are made to the text in Drafts, each of these pattern definitions is applied in order to tokenize the text, applying scopes which determine styles to be applied to characters in the text.

Each pattern definition object should contains the following keys:

  • match [string]: Regular expression pattern to use evaluating the pattern. This expression will be applied to the range of characters currently being evaluated to determine any matching strings. The regular expression may contain capture groups mapping to each of the scopes to apply to the text. For example, a match expression for Markdown bold (**bold**) strings might have separate capture groups for the ** before, the ** after, and the text between to style each with a different scope.
  • comment [string]: Description of the purpose of this pattern.
  • exclusive [boolean]: Is this range exclusive. If true, the text range matched by this pattern will be considered complete and not evaluated for matches by and subsequent patterns defined in the syntax.
  • captures [object]: The capture object must contain a dictionary for each capture group in the match expression, named by index. “0” will always be the entire match result. If the match expression contains additional capture group, each should be included by index, like “1”, “2”, etc.
    • [capture index] [object]: Key for object should be integer index of the capture group it applies to.
      • scope [string]: Comma-separated list of scope names to apply to this capture group. Scopes are sets of font traits and styles which are defined in themes. Scopes will be applied in the order listed, so if attributes from one scope may override attributes from another, so be careful of ordering.
      • exclusive [boolean]: Is this range exclusive. If true, the text range matched by this capture group will be considered complete and not evaluated for matches by and subsequent patterns defined in the syntax. If the exclusive value for the parent pattern is true, this is ignored, but allows a capture group within a pattern override the parent to be considered exclusive.

Patterns are applied in order. It is important to plan correctly using the exclusive property and or the correct ordering of patterns to prevent subsequent patterns from overriding scope values for previously styled text where undesirable.

Example

Below is a partial patterns object with two example patterns to perform syntax highlighting on Markdown heading lines and on horizontal rule markup.

"patterns": [
    {
      "match": "^(#+) ([^\\n]+?)(\\1?)$",
      "exclusive": true,
      "comment": "Markdown header like ###",
      "captures": {
        "1": {
          "scope": "markup.heading"
        },
        "2": {
          "scope": "text.heading"
        },
        "3": {
          "scope": "markup.heading"
        }
      }
    },
    {
      "match": "^(\\*{3,}|-{3,})",
      "exclusive": true,
      "comment": "Markdown horizontal rule like *** or ---",
      "captures": {
        "1": {
          "scope": "markup"
        }
      }
    }
  ]

Scopes

Tip

Stick to using scopes names defined in the default themes for the best compatibility with other themes.

Scopes are the means by which the tokens identified by the regular expression patterns in the syntax definition are tied into themes, which determine how that piece of text will actually appear in the editor. Scope names are arbitrary strings, but if a scope name is used which does not exist in the current theme in use, no changes are made to the text.

The themes which come with Drafts define a set of recommended default scope names which are associated with common text styles, like text.normal, text.bold, text.monospace.bold. They also contain some semantic scopes for common types identified in syntaxes, like text.heading01, code.comment, markup, code.keyword - as well as some common colors, like color.blue, color.green.

When designing syntaxes, it’s important to familiarize yourself with the default scopes in Drafts styles. When possible, sticking It is also possible to use your own scope names, but for them to be meaningful, a custom theme may need to be made and used with your syntax.

In most cases, multiple scopes can be applied in a syntax by providing a comma-separate list. For example, to get bold red text, you might have a pattern with a scope text.bold, color.red. When muliple scopes are applied, the are applied in order, so it’s possible to override values from an early scope in the list. For example, using color.blue, color.red would result in red text.

The navigationPatterns array contains objects which define markers within the text which are used by Drafts’ navigation feature to jump between locations in a longer draft.

When building the list of navigation markers, all patterns defined in the syntax will be evaluated against the full text of the draft, then the list of all found markers will be sorted in the order they appear in the text and presented to the user for selection.

Each navigation pattern object should contain the following keys:

  • match [string]: Regular expression pattern used to locate markers in the text. The expression should contain at least one capture group to define a label to use to identify the marker in the navigation interface.
  • comment [string]: Description of the purpose of the match pattern.
  • rangeCapture [string]: Integer index of capture group in the match pattern to use to identify the location of the marker in the text. When selecting a marker in the navigation interface, the editor will jump the cursor to this location.
  • labelCapture [string]: Integer index of capture group in the match pattern to use as a string label for the marker. For example, when navigating to a Markdown heading, you might want to capture only the text of the header without the leading markup (##) to be displayed.
  • prefix [string]: Prefix to display before the label in the navigation interface. This should be used to distinguish the type of marker (For example, “H1”, “H2”).
  • level [number]: Integer value from 0 to 9 to indicate the indention level of this marker in the navigation interface.

Example

The below example is the navigation patterns entry from the default Markdown syntax. It creates markers for each Markdown heading level (1-6), each with appropriate indentation and labelling.

"navigationPatterns": [
    {
      "match": "^# (.*)$",
      "comment": "H1 level markdown headers with #",
      "rangeCapture": "0",
      "labelCapture": "1",
      "prefix": "H1",
      "level": 0
    },
    {
      "match": "^## (.*)$",
      "comment": "H2 level markdown headers with ##",
      "rangeCapture": "0",
      "labelCapture": "1",
      "prefix": "H2",
      "level": 1
    },
    {
      "match": "^### (.*)$",
      "comment": "H3 level markdown headers with ###",
      "rangeCapture": "0",
      "labelCapture": "1",
      "prefix": "H3",
      "level": 2
    },
    {
      "match": "^#### (.*)$",
      "comment": "H4 level markdown headers with ####",
      "rangeCapture": "0",
      "labelCapture": "1",
      "prefix": "H4",
      "level": 3
    },
    {
      "match": "^##### (.*)$",
      "comment": "H5 level markdown headers with #####",
      "rangeCapture": "0",
      "labelCapture": "1",
      "prefix": "H5",
      "level": 4
    },
    {
      "match": "^###### (.*)$",
      "comment": "H6 level markdown headers with ######",
      "rangeCapture": "0",
      "labelCapture": "1",
      "prefix": "H6",
      "level": 5
    }
  ]

Indentation Patterns

Indentation patterns define block level elements which should be indented as a block when lines wrap beyond the editor width. Examples are Markdown list lines and quotations.

Indentation patterns should use a regular expression pattern that anchors to the beginning of a line (^) and contain a capture group that matches the string that is forcing the indentation. The length of that capture group’s string will be used to calculate the depth of the indent.

The indentScope tells Drafts what font metrics to use to calculate the depth of the indentation, and should match the scope applied by patterns to the text in the indentCapture range.

Each the indentationPatterns array should contain objects with the following keys:

  • match [string]: Regular expression pattern used to find the indentation string. This pattern should anchor at the beginning of the line.
  • comment [string]: Description of the purpose of the match pattern.
  • indentCapture [string]: The capture group index from the match pattern which identifies the text to be used to calculate the indent size.
  • indentScope [string]: The scope to assign to the indent capture.

Example

The below example indentationPatterns entry is from the default Markdown syntax and defines a single indentation pattern to locate and intent Markdown list and quote blocks.

"indentationPatterns": [
  {
    "match": "(^\\h*\\* |^\\h*\\- |^\\h*\\+ |^\\h*\\d+\\. |^\\h*>[> ]+).*",
    "comment": "Indent Markdown lists and blockquotes",
    "indentCapture": "1",
    "indentScope": "text.normal"
  }
]

Task Mark Definitions

The objects in the taskMarkDefinitions array create tap/clickable task marks that change state when tapped. The most common usage of these definitions is to create on-off [ ] / [x] style checkboxes which can be tapped to toggle state.

Task mark definitions are not limited to two states, however. They can have more states and each state can have a different scope specification to affect styling of the text.

Each object in the taskMarkDefinitions array should have the following keys:

  • enabled [boolean]: Is this definition active.
  • match [string]: Regular expression which identifies a task mark string. This expression should find all possible states of the task mark.
  • rangeType [string]: Controls handling of task matches. Supported values:
    • task: Use if the match expression will matches the state values only and no surrounding text. This allows more than one mark per line, but these tasks will only toggle the text used to define the task.
    • line: Use if the match expression matches additional content beyond the interface capture. This type allows state values to be separate from the tappable interface task, but are limited to one match per line.
  • captures [object]: Dictionary with the following required keys:
    • interactive [string]: Group capture index of the match expression which represents the tap/clickable task text.
    • state [string]: Group capture index of the match expression which represents the state of the task.
    • label [string]: Group capture index for the text to be considered the label for the task. This is only used for line rangeType, and is usually the remainder of the line after the task state.
  • states [array of strings]: An array, in order, of the possible states of the task mark. When tapping the mark in the text, it will cycle through these states in order changing the value in the state capture range of the match expression.
  • initialState [string]: This should match an entry in the states array, and be the state which should be represent the incomplete or initial state of the task. This will be the value set when using scripted actions that reset a task. For example, [ ]
  • completedState [array of strings]: Should be a subset of the values in the states array which should be considered “completed” states. For example, [x].
  • scopes [object]: Scopes to apply to the task captures. Currently supports only one key:
    • interactive [string]: Scope name to apply to the interactive (tap/clickable) capture group from the match expression. This allows the task to be styled with themes. Note that foreground colors cannot be applied.

Example

The below example taskMarkDefinitions entry is the one used in Markdown syntax to create on-off [ ] and [x] task marks, which will be rendered using the current theme’s text.monospace.bold scope.

"taskMarkDefinitions": [
    {
      "enabled": true,
      "match": "(\\[[ xX]\\])",
      "rangeType": "task",
      "captures": {
        "interactive": "1",
        "state": "1"
      },
      "states": [
        "[ ]",
        "[x]"
      ],
      "scopes": {
        "interactive": "text.monospace.bold"
      }
    }

The objects in the linkDefinitions array create tap/clickable links to URLs, which can dynamically use data from key and value capture groups within the pattern defined by the definition to general URLs.

Each object in the linkDefinitions array should have the following keys:

  • enabled [boolean]: Is this definition active.
  • match [string]: Regular expression which identifies a link text. The match expression should define capture groups which isolate two values for use constructing the link URL. The match pattern should match all possible values for the key.
  • captures [object]: Dictionary with the following required keys:
    • key [string]: Group capture index of the match expression which represents a key to use to determine the template to use in creating the link URL.
    • value [string]: Group capture index of the match expression which represents a value which can be inserted in the resulting URL dynamically using the tag [[value]]
    • link [string]: Group capture index for the range to be highlighted as a link. This could be the entire matching range, or a substring with the range.
    • prefix [string]: Group capture index for any markup before the link. Optional, but allows for separate scope to be applied.
    • suffix [string]: Group capture index for any markup after the link. Optional, but allows for separate scope to be applied.
  • templates [object]: An object containing string entries keyed for each possible value of the key, and providing a template for a URL which will be generated and attached to the link. These templates can contain a [[value]] tag, which will insert the URL encoded version of the value capture group in the URL. [[value_unencoded]] is also available to use the raw value string, primarily for the case where the value is, itself, a valid URL.
  • scopes [object]: Scopes to apply to the task captures to allow themes to apply styling:
    • key [string]: Scope name to apply to the key capture group from the match expression.
    • value [string]: Scope name to apply to the value capture group from the match expression.
    • prefix [string]: Scope name to apply to the prefix capture group from the match expression.
    • suffix [string]: Scope name to apply to the suffix capture group from the match expression.

Example

The below example linkDefinitions entry which enables links in the style [[key:value]], including the [[d:Draft Title]] internal links to other drafts, [[s:Search]] to link to a drafts search, and [[google:Search Terms]] links to Google, etc.

"linkDefinitions": [
  {
    "enabled": true,
    "match": "(\\[\\[)((d|u|s|w|google|wikipedia|bear):(.+))(\\]\\])",
    "captures": {
      "key": "3",
      "value": "4",
      "link": "2",
      "prefix": "1",
      "suffix": "5"
    },
    "templates": {
      "": "drafts://open?title=[[value]]&allowCreate=true",
      "d": "drafts://open?title=[[value]]&allowCreate=true",
      "u": "drafts://open?uuid=[[value]]",
      "s": "drafts://quickSearch?query=[[value]]",
      "w": "drafts://workspace?name=[[value]]",
      "google": "https://www.google.com/search?q=[[value]]",
      "wikipedia": "https://en.wikipedia.org/wiki/[[value]]",
      "bear": "bear://x-callback-url/open-note?title=[[value]]"
    },
    "scopes": {
      "key": "text.bold",
      "value": "text.italic",
      "prefix": "markup",
      "suffix": "markup"
    }
  }
]

Autocomplete Definitions

The objects in the autocompleteDefinitions array define available autocomplete drop-down lists when editing.

Each object in the autocompleteDefinitions array must contain the following keys:

  • type [string]: Supported values are draft and static (details below)
  • enabled [boolean]: If false, this definition will be ignored.
  • trigger [string]: The text that, when typed in the editor, will trigger the appearance of the autocomplete drop-down. This should be a short but unique sequence of characters. It is recommend to use two character strings, but single character or longer strings are supported.

draft Type

If the autocomplete definition object uses type draft, the results provided in the drop-down will be based on a query of other drafts in the user’s drafts data. The following keys should be provided to define the default values for the query as well as the appearance and output of the suggestions:

  • label [string]: Template for the label text that will appear in the drop-down list for selection. This will be evaluated by Drafts’ template engine, and most commonly this value would be [[display_title]], which returns the cleaned version of the target draft’s first line for identification.
  • value [string]: Template for the text to be inserted at the cursor if the drop-down is selected. Like the label, this will be passed through the template engine, so can be used to control what is inserted. For example, this value could be [[draft]] to return the full text of the draft, or [[body]] to return the text without the title line. The template may also contain static text, such as additional line feeds or separators.
  • prefix [string]: If provided, the prefix string will be displayed in the selection drop-down and prepended to the output of the value template when inserting the text.
  • suffix [string]: If provided, the suffix string will be displayed in the selection drop-down and append to the output of the value template when inserting the text.
  • queryType [string]: Supported values are title and fullText. Determines if when querying for drafts matching the partial string the user has typed while autocompleting, if results should include matches only in the title, or in the full text of the draft.
  • queryTagFilter [string]: A comma-separate tag filter which can be used to limit query results to only drafts matching the tag filter. So, for example, a queryTagFilter of blue, red will only provide autocomplete suggestions for drafts with blue and red tags assigned.

Example draft Type

The below example autocompleteDefinitions entries are the default entries which ship in the built-in Markdown syntaxes. They enable autocomplete of draft titles using the [[ trigger, and insertion of the full text of drafts using <<.

"autocompleteDefinitions": [
  {
    "trigger": "[[",
    "type": "draft",
    "label": "[[display_title]]",
    "value": "[[display_title]]",
    "queryType": "title",
    "queryTagFilter": "",
    "prefix": "[[",
    "suffix": "]]",
    "enabled": true
  },
  {
    "trigger": "<<",
    "type": "draft",
    "label": "[[display_title]]",
    "value": "[[draft]]",
    "queryType": "title",
    "queryTagFilter": "",
    "prefix": "",
    "suffix": "",
    "enabled": true
  }
]

static Type

Autocomplete definitions of type static provide a pre-defined array of available drop-down suggestions. In addition to the required keys, the following keys should be provided:

  • items [array]: An array of objects defining the available autocomplete suggestions. Each object in the array should contain the following keys:
    • label [string]: Template for the text to appear in the autocomplete drop-down.
    • value [string]: Template for text to be inserted if item is selected.
    • prefix [string]: If provided, the prefix string will be displayed in the selection drop-down and prepended to the output of the value template when inserting the text.
    • suffix [string]: If provided, the suffix string will be displayed in the selection drop-down and append to the output of the value template when inserting the text.
  • processTemplateTags [boolean]: If true, label and value template will be passed through the template engine to evaluate tags.

Note that the label and value templates will be evaluated for Drafts template tags if processTemplateTags is true, allowing dynamic insertion of values like dates, location, but will be evaluated with the current draft being edited in context.

Example static Type

The below example autocompleteDefinitions entries for a simple static set of suggestions triggered by typing !! in the editor.

"autocompleteDefinitions": [
  {
    "trigger": "!!",
    "type": "static",
    "processTemplateTags": true,
    "items": [
      {
        "label": "My First Item",
        "value": "My First Item",
        "prefix": "",
        "suffix": ""
      },
      {
        "label": "Current Date",
        "value": "[[date|%Y-%m-%d]]",
        "prefix": "",
        "suffix": ""
      }
    ],
    "enabled": true
  }
]

List Completion Definitions

The objects in the listCompletionDefinitions array define the patterns that identify “list” lines, so when a user hits return on a line, the list prefix is auto-inserted to continue the list on the next line.

Each object in the listCompletionDefinitions array should have the following keys:

  • enabled [boolean]: Is this definition enabled.
  • match [string]: Regular expression which identifies a list line. The pattern should contain capture groups to local the line prefix, the full line, and the length of the indentation, and optionally a sequence which captures only a integer value to increment.
  • captures [object]: Dictionary with the following required keys:
    • indent [string]: Group capture index of the match expression which represents a indent to use to padding the next line. Typically, this would match whitespace at the beginning of line.
    • prefix [string]: Group capture index of the match expression which represents a prefix for the line. This should match the text at the beginning for the line which distinguishes it as a list, like * or - for Markdown lists.
    • line [string]: Group capture index which represents the entire line.
    • sequence [string, optional]: Group capture index for an integer sequence value. This should find only the integer value, and if it does that number will be incremented on new lines.
  • sequencePadding [string]: An integer for the number of digits of leading padding to apply to sequence values. For example, sequencePadding value of 0 will result in no padding, and number like 1, 2, 3. A padding value of 2 will results in 001, 002, etc.
  • replacements [object]: An object key-value pairs to be replaced in the prefix text of the new line. The key should be the string to replace, the value the new text to use. This is primarily used for task mark elements, where you want the new line to contain an incomplete task, even if the previous line contained a completed one, so replacing [x] wtih [ ].

Example

The below example listCompletionDefinitions entry which enables list completion in the Markdown syntaxes. It has two entries, the first which finds unordered list lines (like * , - ) with or without task marks. The second which finds ordered lines and demonstrates the use of a sequence.

"listCompletionDefinitions": [
  {
    "comment": "Unordered Markdown lists, like `* `",
    "enabled": true,
    "match": "(^[ |\\t]*)((\\* \\[[ x]\\]|- \\[[ x]\\]|\\+ \\[[ x]\\]|\\*|-|\\+|>) )(.*)",
    "captures": {
      "indent": "1",
      "prefix": "2",
      "line": "4",
      "sequence": ""
    },
    "replacements": {
      "[x]": "[ ]",
      "{x}": "{ }",
      "{-}": "{ }"
    }
  },
  {
    "comment": "Ordered Markdown lists, like `1. `",
    "enabled": true,
    "match": "(^[ |\\t]*)((\\d+)\\. (\\[[ x]\\] )?)(.*)",
    "sequencePadding": "0",
    "captures": {
      "indent": "1",
      "prefix": "2",
      "line": "5",
      "sequence": "3"
    },
    "replacements": {
      "[x]": "[ ]",
      "{x}": "{ }",
      "{-}": "{ }"
    }
  }
]

Feature Keys

Feature keys expose user-level settings to toggle on and off certain functionality of a syntax defintion. They are completely optional, and typically only used where there is a set of options in a syntax that represent common preferences which a user might want to enable and disable - but that are small enough that it doesn’t make sense to create and maintain a totally separate syntax definition to allow for that variance.

Define Feature Keys

Define available feature keys in a featureKeys array at the root of the definition file. Each entry in this array should be an object with the following keys:

  • id [string]: A short string identifier. This will not be visible to the user, but will be used to mark other elements in the definition file as associated with this key.
  • name [string]: A short, user-friendly name for the feature.
  • description [string]: A longer paragraph describing what enabling or disabling this key will change.
  • defaultValue [boolean]: A true/false toggle to define if the feature key should be enabled or disabled by default.

Each of these feature key entries will be exposed in Drafts’ Editor Settings when the user is using the syntax, and they will be able to toggle each off and on in the user interface.

Example featureKeys

"featureKeys": [
    {
        "id": "strikeCompletedTasks",
        "name": "Strikethrough Tasks",
        "description": "Display completed task lines as crossed out text.",
        "defaultValue": true
    },
    {
        "id": "dimCompletedTasks",
        "name": "Dim Tasks",
        "description": "Display completed task lines as dimmed text.",
        "defaultValue": true
    }
]

Implement Feature Key

To implement the changes specific to a feature key, add a featureKeys string entry to any of the objects that make up your syntax, with its value equal to the id property of the feature key you want that item to participate in. featureKeys elements can be in patterns, linkDefinitions, taskMarkDefinitions, or any of the other array elements of your syntax. If the feature key is disabled, either by its defaultValue or by the user, then the elements with that feature key will simply be skipped when evaluating the syntax in the editor.

If an element requires is dependent on more than one feature key, the featureKeys entry can be a comma-separated list of feature key ids, and all the listed features must be active for the element to be used.

Example featureKeys Implementation

The below shows a pattern definition that will only be processed by the syntax highlighting process if the feature key with the id “markdownHeaders” is enabled.

```json “patterns”: [ { “match”: “^(#+) ([^\n]+?)(\1?)$”, “exclusive”: true, “featureKeys”: “markdownHeaders”, “comment”: “Markdown header like ###”, “captures”: { “1”: { “scope”: “markup.heading” }, “2”: { “scope”: “text.heading” }, “3”: { “scope”: “markup.heading” } } } ]


© 2012-2023 by Agile Tortoise, Inc.
Drafts is a registered Trademark of Agile Tortoise, Inc.
Privacy | Terms

Mastodon