Authoring best practices

This page helps you create a consistent, parallel, readable browsing experience. You achieve this by doing the small things consistently right, from the ground up.

Guide titles and descriptions on ExL landing pages
Tables of contents
Placement of common elements on pages

Tips and rules to prevent common errors

File and folder names

  • Markdown filenames must be lowercase with hyphens. No capital letters, underscores, periods, or spaces. However, although not recommended, assets such as image files can include capital letters and underscores.


  • Discrete components such as headings, fenced code blocks, and bullet/number lists should be surrounded by blank lines.
  • Only a single h1 heading (#) is allowed in the document, and all later headings are h2 (##) or lower level headings. First line in the file below the metadata should be h1 (top level heading, or title).
  • No duplicate heading IDs (anchor IDs) are allowed in a document.
  • Heading IDs should not include periods. Bad example: {#version-2.3} Good example: {#version-2-3}
  • No space between the markers of the text or surrounding the links e.g. abcd or [ abcd ]


  • Every section heading in the TOC must have a valid section ID. Bad example: + Processing rules Good example: + Processing rules {#processing-rules}
  • A section heading (parent) in the TOC cannot be a link.
  • You must use proper syntax for TOC section headings (e.g., + Processing rules {#processing-rules}) and TOC article links (e.g., + [Article name](
  • Avoid adding the same file multiple times to a TOC (or to multiple TOCs). Doing so causes odd behavior.

Visual Studio Code tips

If you’re using Visual Studio Code (VSC) for editing, here are some tips and techniques that we’ve found useful.

Adobe Markdown Authoring extension for VSC

The Adobe Markdown Authoring extension is available for download in the VSC Extensions Marketplace.

  1. Do the following:

    • Uninstall any previous version of Adobe Markdown Authoring.
    • Disable any custom preview extension you may have installed.
    • Disable Markdown Shortcuts by mdickin if previously installed to avoid duplicated shortcuts.
  2. In the left nav, click the Extensions icon.

  3. Search for adobe markdown authoring.

  4. Click Adobe Markdown Authoring, and then click Install.

adobe extension

This extension pack includes the following add-ons:

  • Preview. Click the Preview icon addon-preview-icon.png in the upper right area to view a reasonably close rendering of Adobe markdown syntax.
  • Shortcuts. Right-click in the document area to view available keyboard shortcuts. You can edit these shortcuts or create your own, as described later.
  • Validation. Most of the Adobe syntax rules are included in this add-on. If you add unsupported syntax, you’ll see squiggly underlines below the potentially offending text. Hover over the text to view the flagged problem.

Manual install (legacy)

  1. Do the following:

    • Uninstall any previous version of Adobe Markdown Authoring.
    • Disable any custom preview extension you may have installed.
  2. To install the extension, right-click this link to download the adobe markdown authoring .vsix file.

  3. In VSC, press Command+Shift+P and type install from vsix to run the ‘Extensions: Install from VSIX’ command. Specify the adobe-markdown-authoring-1.1.1.vsix file you downloaded. Install.

Known bugs and limitations

  • Not all syntax rules are included. We try to keep the extension up to date, but there will rarely be a 100% match between Jenkins validation and what gets flagged in VSC.
  • Images with root links are not displaying properly in preview. Only images with relative links are displaying. Ctrl/Cmd-clicking a link with a root link appears to be dead. Bug regression that should be fixed in the next update.
  • The preview is not a 100% representation of what the rendered page will look like. For example, {style="table-layout:auto"} is not removed.
  • If multiple DNL or UICONTROL tags set within same paragraph, only the first result is hidden in preview. The rest of the tags appear.

Visual Studio Code add-ons we like

Extension Description
Adobe Markdown Authoring See Adobe Markdown Authoring extension above.
Acrolinx for Visual Studio Code Uses custom Adobe rules to check spelling, grammar, and Adobe terminology. We have a limited number of Visual Studio Code licenses, so we want to limit usage to lead writers. See Using Acrolinx.
markdownlint (automatically installed with Adobe Markdown Authoring) Flags content for possible validation errors based on lint, which we use in Jenkins.
Bracket Pair Colorizer 2 (EOL) Bracket pairs are now enabled natively.
Highlight Bad Chars Highlights illegal characters such as BOM characters that can cause validation failures.
Copy Relative Path Posix (for Windows users) In Windows, copying the relative path using this command uses / instead of \, which is necessary for root links.
Paste Image Paste image directly from clipboard to markdown, adding the file and creating an image link. See the add-on instructions.

Feel free to add any extension to this list that you find useful.

Using Quick Open

Command+P is your friend. If you need to open a file, press Command+P and paste or start typing the filename, or open one of your recently edited files. Press Command+Shift+P to open the Command palette.

Command palette image

Linking tips

See the Linking tips article.

Global Find/Replace

Visual Studio Code lets you find/change text either within a document or across all the files you have open.

  1. Make sure that your cloned repo is in sync with the main branch on the server.
  2. Choose File > Open, and open the folder containing the repo, user guide, or section that you want to search.
  3. Choose Edit > Replace in Files. Specify the text you want to search for and what you want to replace it with.

Replace in files

  1. Do any of the following:

    • Click the Replace All icon next to the Replace box to replace all occurrences across all files.
    • Click the Replace All icon next to the filename to replace all occurrences in that file.
    • Click the Replace icon next to the occurrence to replace only that instance.
    • Click the x icon next to any occurrance to remove it. This will exclude it from any Replace All action.

When you use the Replace in Files feature, replacing items automatically saves the affected files.

Wildcard Find/Replace

If you do a lot of finding and changing, or if you’re making global changes for a migration or cutover, using wildcards can save time. But this section isn’t for everyone.

Common expressions

  • Use (.+?) for wildcard search text.
  • Use $1 for replacing with the same wildcard content. $1 for first wildcard, $2 for second, and so on.
  • Use ^ for from start of line and $ for to end of line.
  • Use [^n] for not this character.
  • Use \ before a character to escape a character that will otherwise be used as an expression.
  1. Choose File > Open, and open the folder containing the repo, user guide, or section that you want to search.

  2. Choose Edit > Replace or Replace in Files.

  3. (Important) Click the Use Regular Expression icon to the right of the search box.

  4. Specify the search string using (.+?) for wildcard.

    The parentheses indicate a group. The dot . indicates a wildcard. The plus sign + indicates multiple characters. The question mark ? tells it not to be greedy so that the string ends with the first instance of whatever comes after the group.

  5. Specify the replace string using $1 where you want the wildcard text to appear.

    The $1 returns wildcard text was stored in the first group.

wildcard search

Wildcard search examples

Here are some useful strings for converting the loc tags in HTML table content.

search/replace links$$1

search/replace links

<a href="(.+?)"(.+?)> (.+?)</a>

In this case, we use three wildcard groups. The first group captures the link path. The second group captures HTML properties that we don’t need. The third group captures the link text. We then put the link text in brackets [$3] and the link path in parentheses ($1).

search replace image

<img (.+?)src="assets/(.+?)"(.+?)>
![$2 image](assets/$2)

You might need to tweak this one by adding or removing spaces, depending on how the table was migrated.

search replace code

<span class="codeph">(.+?)</span>
`$1` (Markdown) or <code>$1</code> (HTML)

You might need to add a space before or after the wildcard group, depending on how the table was migrated.

search replace varname

<span class="varname">(.+?)</span>
*$1* (Markdown) or <i>$1</i>

search for a character that’s not a specific character

<a [^h]

In this example, we want to find HTML links that start with something other than a href.


In this example, we want to find anchor IDs that are missing the # character.

&search replace [ ] in headings

We’ll use [!DNL] as an example…

\# (.+?) \[!DNL(.+?)]
# $1$2

Use \ to escape characters such as # and [ used in expressions.

In this example, we’ll look for anchors in a TOC that are missing the # character, such as {admin} instead of {#admin}:


Copy empty alt text with image name

For example, you want ![](assets/rule-regs.png) to become ![rule-regs](assets/rule-regs.png)


Find spaces or tabs at end of a line


Find step numbers that start with 2-9 instead of 1.

Best practice is to start all numbered list items with 1 so that steps are treated as a list.


Find headings with missing anchor hashes

We require {#anchor} not {anchor}.


Find markdown components with extra space

In Experience League, we don’t allow a space between > and [! in extension syntax. In other words, we accept >[!NOTE] but not > [!NOTE]. Use this search to find these unwanted spaces, and remove them.


Post-migration cleanup searches

You can use these Visual Studio Code search techniques to find common issues that appeared when the files were migrated. When it’s difficult to find errors in Visual Studio Code searches, you can use search patterns in Google to locate problems.

Visual Studio Code Searches

Here’s a list of searches in Visual Studio Code that help identify common formatting problems. Feel free to add to this list.

Basic (non-expression) searches

Use these basic searches in Visual Studio Code to find common formatting errors.

the the search

Find “the the”

  • Syntax: “the the” (with “Match Case” selected and surrounding spaces)
  • Problem: “Time zone of the the data workbench server”
  • Should be: “Time zone of the data workbench server”

Find any bad bolds before [!DNL] or [!UICONTROL]

  • Syntax: ** [!
  • Problem: ** [!DNL Visitor Page Views]**
  • Should be: **[!DNL Visitor Page Views]**

Find failed bold in definition lists

  • Syntax: "* ** " (add space after **)
  • Problem: * ** [!DNL Longitude] column:** This column...
  • Should be: * **[!DNL Longitude] column:** This column...

Expression-based searches

For these search expressions, make sure that you turn on the Use Regular Expressions option.

expression search

Find any ** preceded by a space at the end of a line

  • Syntax:

    ^(.+?) \*\*$
  • Problem: **Period-Based Unique Visitors Reports **

  • Should be: Period-Based Unique Visitors Reports

Find any ** followed by a space at the beginning of a line

  • Syntax:

    ^\*\* (.+?)
  • Problem: ** Next steps:** We will begin to migrate users

  • Should be: Next steps: We will begin to migrate users

Find [!DNL] or [!UICONTROL] in HTML tables

These errors are usually the result of a global Find/Change that failed to account for HTML. Remember, Markdown syntax isn’t supported in HTML.

  • Syntax: <p(.+?)\[!

  • Problem:

    <td colname="col2"> <p>Replaces the <span class="uicontrol"> Show Metrics</span>
    popup in [!UICONTROL Reports & Analytics]. </p>
  • Should be:

    <td colname="col2"> <p>Replaces the <span class="uicontrol"> Show Metrics</span>
    popup in <span class="uicontrol"> Reports & Analytics</span>. </p>

Find Markdown links in HTML tables

Here’s another problem caused by an overly greedy Find/Change.

  • Syntax: <p(.+?)\]\(

  • Problem:

    <td colname="col2"> <p>If your site contains links to files with any
    of the listed extensions, the URLs of these links will appear in
    reporting. See [Configuration Variables](js-implementation
    /c-variables/ </p> </td>
  • Should be:

    <td colname="col2"> <p>If your site contains links to files with any
    of the listed extensions, the URLs of these links will appear in
    reporting. See <a href="/docs/authoring-guide-exl/implement/js-implementation/c-variables
    /"> Configuration Variables</a>. </p> </td>

Google Searches

If you do a search in Visual Studio Code for "** " or “&gt;”, the improper uses get lost among all the proper uses. With a Google search, it’s much easier to search for formatting that failed to render properly.

google search

In these examples, using the parameter narrows the search to our help content. You can further narrow the search by adding your specific help domain, such as

Find the failed instances of bold ** syntax

  • ** **<myrepo>

Find unformatted [!UICONTROL]/[!DNL] tags

  • UICONTROL<myrepo>
  • DNL<myrepo>

Find unescaped escape characters

  • &gt;<myrepo>
  • &lt;<myrepo>
  • &nbsp;<myrepo>
  • &amp;<myrepo>

Keyboard shortcuts for Visual Studio Code


When the Adobe Markdown Authoring extension, custom shortcuts for adding notes and uicontrol/dnl tags will be available. You can edit these shortcuts. More info to follow.

You can use existing VS Code keyboard shortcuts, create your own custom shortcuts, and use shortcuts from an excellent add-on.

Editing keyboard shortcuts

You can edit existing keyboard shortcuts. This is especially useful if you’ve added the Adobe Markdown Authoring extension and want to use different keyboard shortcuts.

  1. Choose Code > Preferences > Keyboard Shortcuts.
  2. Locate the shortcut you want to edit. Click the pencil icon, and enter the new shortcut.


In this example, replaced the default ‘Toggle Tip’ shortcut (which is available because of the Adobe Markdown Authoring extension) with Control+Shift+Option+T. After I did that, the new shortcut appeared in the context menu.

See Key Bindings for Visual Studio Code (Microsoft documentation) for details.

Creating custom keyboard shortcuts for markdown extensions

Consider adding your own keyboard shortcuts for common tasks. Here’s how.

  1. Choose Code > Preferences > Keyboard Shortcuts.

  2. Click the icon for editing shortcuts.

    json icon

  3. Copy and paste the shortcuts below, and save the keybindings.json file.

  4. Test the keyboard shortcuts in a different file.

    You can switch between different windows to test the keystrokes and make/save edits. The shortcuts work in runtime.


    In some cases, you might already have a function assigned to one or more of these keystrokes. You’ll need to find a different keyboard shortcut to get around the conflict.

    keybindings.json file

             "key": "ctrl+shift+u",
             "command": "type",
             "args": { "text": "[!UICONTROL ]" },
             "when": "editorTextFocus"
             "key": "ctrl+shift+d",
             "command": "type",
             "args": { "text": "[!DNL ]" },
             "when": "editorTextFocus"
             "key": "ctrl+shift+n",
             "command": "type",
             "args": { "text": ">[!NOTE]\n>\n>" },
             "when": "editorTextFocus"
             "key": "ctrl+shift+i",
             "command": "type",
             "args": { "text": ">[!IMPORTANT]\n>\n>" },
             "when": "editorTextFocus"
             "key": "ctrl+shift+c",
             "command": "type",
             "args": { "text": ">[!CAUTION]\n>\n>" },
             "when": "editorTextFocus"
             "key": "ctrl+shift+w",
             "command": "type",
             "args": { "text": ">[!WARNING]\n>\n>" },
             "when": "editorTextFocus"
             "key": "ctrl+shift+t",
             "command": "type",
             "args": { "text": ">[!TIP]\n>\n>" },
             "when": "editorTextFocus"
             "key": "ctrl+shift+v",
             "command": "type",
             "args": { "text": ">[!VIDEO](url)" },
             "when": "editorTextFocus"
             "key": "ctrl+shift+m",
             "command": "type",
             "args": { "text": ">[!Related Articles]\n>\n>* [article](url)\n>* [article](url)" },
             "when": "editorTextFocus"
             "key": "ctrl+shift+a",
             "command": "type",
             "args": { "text": "![](assets/)" },
             "when": "editorTextFocus"
             "key": "ctrl+shift+l",
             "command": "type",
             "args": { "text": "<ul><li>Item1</li><li>Item2</li></ul>" },
             "when": "editorTextFocus"

Advanced version that applies UICONTROL and DNL to selection


If you install the Adobe Markdown Authoring extension, it’s easy to edit the existing shortcuts for UICONTROL and DNL, so there’s no need to create the snippets described here. But I’m leaving this section here in case you want to create snippets for a different reason.

Most writers would rather apply UICONTROL and DNL tags to a selection of text instead of inserting the tags at the cursor. To get the keystroke to work with a selection, you need to use a combination of snippets and shortcuts. It’s a little more advanced, but not that difficult. Here’s how to set that up.

If you create a snippet for UICONTROL and DNL, we recommend that you use different keystrokes (such as Ctrl+u and Ctrl+d) for selected text, as instructed. Then you can use one keystroke for applying to a selection and another keystroke (ctrl+shift+u and ctrl+shift+d) to insert the syntax at the cursor. Additionally, you can create a snippet for when you want to also apply bold formatting to your UICONTROL selection.

  1. Create a snippet for UICONTROL with bold. This shortcut wraps the selection in UICONTROL and applies bold formatting to the selection.

    1. Choose Code > Preferences > User Snippets > New Global Snippets file.

    2. Specify a name such as uicontrol with bold and press Enter.

    3. Paste the following code into the snippet:

        "uicontrol-with-bold": {
        "scope": "markdown",
        "prefix": "uicontrol with bold",
        "body": [
            "**[!UICONTROL $TM_SELECTED_TEXT]**"
        "description": "Wrap selection with uicontrol and apply bold formatting to selection"}
    4. Save the snippet file.

  2. Create a similar snippet for UICONTROL without bold.

      "uicontrol-without-bold": {
      "scope": "markdown",
      "prefix": "uicontrol without bold",
      "body": [
      "description": "Wrap selection with uicontrol"}
  3. Create a similar snippet for DNL.

       "dnl": {
       "scope": "markdown",
       "prefix": "dnl",
       "body": [
          "[!DNL $TM_SELECTED_TEXT]"
       "description": "Wrap selection with dnl"}
  4. In the keybindings.json file (see above), add the shortcuts for UICONTROL with bold, UICONTROL without bold, and DNL.

             "key": "ctrl+u",
             "command": "editor.action.insertSnippet",
             "args": { "name": "uicontrol-with-bold" },
             "when": "editorHasSelection"
             "key": "ctrl+n",
             "command": "editor.action.insertSnippet",
             "args": { "name": "uicontrol-without-bold" },
             "when": "editorHasSelection"
             "key": "ctrl+d",
             "command": "editor.action.insertSnippet",
             "args": { "name": "dnl" },
             "when": "editorHasSelection"
  5. Test the keyboard shortcuts in a different file with selected text. Again, replace any keyboard shortcuts that are already taken on your system.

Custom keyboard shortcut quick reference

The following table shows the keyboard shortcuts that we used in the above examples. Make the appropriate adjustments if you edited your shortcuts to avoid system conflicts.

Shortcut Extension Notes
ctrl+shift+n !NOTE
ctrl+shift+i !IMPORTANT
ctrl+shift+c !CAUTION
ctrl+shift+w !WARNING
ctrl+shift+t !TIP
ctrl+shift+v !VIDEO Paste video URL
ctrl+shift+m !Related Articles
ctrl+shift+a image link to assets folder Edit if necessary
ctrl+shift+l (letter L) insert unordered list in table
ctrl+shift+u !UICONTROL - Insert at cursor
ctrl+u !UICONTROL - Wrap around selected text and apply bold formatting If you created the snippet
ctrl+n !UICONTROL - Wrap around selected text, no bold If you created the snippet
ctrl+shift+d !DNL - Insert at cursor
ctrl+d !DNL - Wrap around selected text If you created the snippet

Additional keystrokes to consider creating


If you want to wrap selected text in comment syntax (<!-- -->), here’s the snippet syntax:

  "comment": {
  "scope": "markdown",
  "prefix": "comment",
  "body": [
      "<!-- $TM_SELECTED_TEXT -->"
  "description": "Wrap selection with comment tags"}

And here’s the section you could add to the keybindings.json file:

    "key": "ctrl+shift+h",
    "command": "editor.action.insertSnippet",
    "args": { "name": "comment" },
    "when": "editorHasSelection"

Shortcuts for commands such as slugify or lowercase

Visual Studio Code has many editing actions you can take advantage of. For example, if you want to create anchor IDs from heading text, you can run the “Slugify selection” command to convert headings (such as Creating visual elements) into anchor format (such as creating-visual-elements). Or, you can change the case of selected text.

Here’s how to assign keyboard shortcuts to VSC commands.

  1. Identify the command you want to use.

    In VSC, press Ctrl+Shift+P and begin typing the command you want to use. You can include commands such as “Toggle Note” that are used in the Adobe Markdown Authoring plug-in.

  2. Choose Code > Preferences > Keyboard Shortcuts.

  3. In the search box, type the name of the action, such as “Slugify selection” or “Transform to Lowercase.”

  4. Click the plus sign next to the action and specify your keystroke.

Renaming, Moving, and Deleting Files

See Moving, renaming, and restructuring content

Working with Tables

See Tables

Adding redirects

See Redirects

Experimenting with test content

Feel free to use the sandbox.en repo to experiment with the Git workflow or test out Markdown syntax. The sandbox repo should be clean and small. Feel free to edit or remove any content.

If you value any sandbox content, save a backup. We want to keep this repo clean, so remove content whenever we need to.

On this page