Skip to content

3.Configuration

yousefhadder edited this page Dec 28, 2025 · 3 revisions

Configuration

⚠️ Important: Explicit setup() required

Starting from the next release, you must explicitly call setup() (or use opts = {} in lazy.nvim). Auto-setup without calling setup() is deprecated and will be removed in v2.0.

Minimal lazy.nvim config:

{
  "yousefhadder/markdown-plus.nvim",
  ft = "markdown",
  opts = {},  -- Required: calls setup() with default options
}

Configuration Options

require("markdown-plus").setup({
  -- Global enable/disable
  enabled = true,               -- default: true

  -- Feature toggles (all default: true)
  features = {
    list_management = true,     -- default: true (list auto-continue / indent / renumber / checkboxes)
    text_formatting = true,     -- default: true (bold/italic/strike/code + clear)
    headers_toc = true,         -- default: true (headers nav + TOC generation & window)
    links = true,               -- default: true (insert/edit/convert/reference links)
    images = true,              -- default: true (insert/edit image links + toggle link/image)
    quotes = true,              -- default: true (blockquote toggle)
    callouts = true,            -- default: true (GFM callouts/admonitions)
    code_block = true,          -- default: true (visual selection -> fenced block)
    table = true,               -- default: true (table creation & editing)
    footnotes = true,           -- default: true (footnote insertion/navigation/listing)
  },

  -- TOC window configuration
  toc = {
    initial_depth = 2,          -- default: 2 (range 1-6) depth shown in :Toc window and generated TOC
  },

  -- Callouts configuration
  callouts = {
    default_type = "NOTE",      -- default: "NOTE"  default callout type when inserting
    custom_types = {},          -- default: {}  add custom types (e.g., { "DANGER", "SUCCESS" })
  },

  -- Table configuration
  table = {
    auto_format = true,         -- default: true  auto format table after operations
    default_alignment = "left", -- default: "left"  alignment used for new columns
    confirm_destructive = true, -- default: true  confirm before transpose/sort operations
    keymaps = {                 -- Table-specific keymaps (prefix based)
      enabled = true,           -- default: true  provide table keymaps
      prefix = "<leader>t",     -- default: "<leader>t"  prefix for table ops
      insert_mode_navigation = true,  -- default: true  Alt+hjkl cell navigation
    },
  },

  -- Footnotes configuration
  footnotes = {
    section_header = "Footnotes",  -- default: "Footnotes"  header for footnotes section
    confirm_delete = true,          -- default: true  confirm before deleting footnotes
  },

  -- List configuration
  list = {
    checkbox_completion = {
      enabled = false,            -- default: false  add timestamps when checking tasks
      format = "emoji",           -- default: "emoji"  timestamp format (see below)
      date_format = "%Y-%m-%d",   -- default: "%Y-%m-%d"  os.date() format string
      remove_on_uncheck = true,   -- default: true  remove timestamp when unchecking
      update_existing = true,     -- default: true  update timestamp when re-checking
    },
  },

  -- Global keymap configuration
  keymaps = {
    enabled = true,             -- default: true  set false to disable ALL default maps (use <Plug>)
  },

  -- Filetypes configuration
  filetypes = { "markdown" },   -- default: { "markdown" }
})

-- NOTES:
-- 1. Any field omitted uses its default value shown above.
-- 2. Unknown fields trigger a validation error.
-- 3. vim.g.markdown_plus (table or function) is merged BEFORE this setup() call.
-- 4. setup() options override vim.g values; both override internal defaults.

Using with Multiple Filetypes

The plugin can be enabled for any filetype, not just markdown. This is useful for:

  • Plain text files (.txt, .text)
  • Note-taking formats (.note, .org)
  • Documentation files
  • Any text-based format where you want markdown-style formatting

Example: Enable for markdown and plain text files

{
  "yousefhadder/markdown-plus.nvim",
  ft = { "markdown", "text", "txt" },  -- When to load the plugin (plugin manager)
  opts = {
    filetypes = { "markdown", "text", "txt" },  -- When to activate features (for subsequent buffers)
  },
}

Note: Both ft and filetypes are needed when using multiple filetypes:

  • ft tells your plugin manager (e.g., lazy.nvim) when to load the plugin
  • filetypes tells the plugin which filetypes to activate on for subsequent buffers opened after the plugin loads

Example: Enable for custom note-taking setup

{
  "yousefhadder/markdown-plus.nvim",
  ft = { "markdown", "note", "org", "wiki" },
  opts = {
    filetypes = { "markdown", "note", "org", "wiki" },
  },
}

Alternative Configuration Methods

Using vim.g (for early configuration)

You can use vim.g.markdown_plus to set configuration before the plugin loads. This is useful for:

  • Setting filetypes before the plugin's FileType autocmd registers
  • Vimscript compatibility
  • Dynamic configuration with functions

Note: Using vim.g.markdown_plus alone (without calling setup()) is deprecated. Always use opts = {} or call setup() explicitly.

Setting filetypes early (for custom filetypes)

If you use custom filetypes, set them via vim.g.markdown_plus in lazy.nvim's init:

{
  "yousefhadder/markdown-plus.nvim",
  ft = { "markdown", "text" },
  init = function()
    -- Set filetypes BEFORE plugin loads
    vim.g.markdown_plus = { filetypes = { "markdown", "text" } }
  end,
  opts = {},  -- Still required to call setup()
}

Using a Table (Lua)

-- Set before the plugin loads (e.g., in init.lua)
vim.g.markdown_plus = {
  enabled = true,
  features = {
    list_management = true,
    text_formatting = true,
  },
  keymaps = {
    enabled = false,  -- Disable default keymaps
  },
  filetypes = { "markdown", "text" },
}

-- You still need to call setup() or use opts = {} in your plugin manager
require("markdown-plus").setup()

Using a Table (Vimscript)

" Set before the plugin loads (e.g., in init.vim)
let g:markdown_plus = #{
  \ enabled: v:true,
  \ features: #{
  \   list_management: v:true,
  \   text_formatting: v:false
  \ },
  \ keymaps: #{
  \   enabled: v:true
  \ },
  \ filetypes: ['markdown', 'text']
  \ }

Using a Function (Dynamic Configuration)

For dynamic configuration based on runtime conditions:

vim.g.markdown_plus = function()
  return {
    enabled = vim.fn.has("nvim-0.10") == 1,  -- Only enable on Neovim 0.10+
    features = {
      list_management = true,
      text_formatting = not vim.g.vscode,  -- Disable in VSCode
    },
  }
end

Configuration Priority

When both vim.g.markdown_plus and setup() are used, they are merged with the following priority:

  1. Lowest: Default configuration
  2. Middle: vim.g.markdown_plus configuration
  3. Highest: setup(opts) parameter

Example:

-- This vim.g config sets list_management = false
vim.g.markdown_plus = {
  features = {
    list_management = false,
  },
}

-- But setup() overrides it to true
require("markdown-plus").setup({
  features = {
    list_management = true,  -- Takes precedence over vim.g
  },
})

-- Result: list_management will be true

This allows you to:

  • Set global defaults with vim.g
  • Override specific settings with setup() for certain filetypes or conditions
  • Mix both methods for maximum flexibility

Callouts-Specific Configuration Examples

Configuring Callouts

Change Default Callout Type

require("markdown-plus").setup({
  callouts = {
    default_type = "TIP",  -- Change from NOTE to TIP
  },
})

Add Custom Callout Types

require("markdown-plus").setup({
  callouts = {
    custom_types = { "DANGER", "SUCCESS", "INFO" },
  },
})

After adding custom types, they will:

  • Appear in the type selection menu when inserting callouts
  • Be included in the cycling order when using <leader>mQt
  • Work with all callout operations (insert, wrap, convert, etc.)

Custom Types with Different Default

require("markdown-plus").setup({
  callouts = {
    default_type = "DANGER",  -- Must be either standard or custom type
    custom_types = { "DANGER", "SUCCESS" },
  },
})

Disable Callouts Feature

require("markdown-plus").setup({
  features = {
    callouts = false,  -- Disable callouts entirely
  },
})

Callouts Only Configuration

If you only want callouts and blockquotes:

require("markdown-plus").setup({
  features = {
    list_management = false,
    text_formatting = false,
    headers_toc = false,
    links = false,
    quotes = true,       -- Keep blockquote toggle
    callouts = true,     -- Enable callouts
    code_block = false,
    table = false,
  },
})

Checkbox Completion Timestamps Configuration

Enable automatic completion timestamps when checking tasks, similar to Obsidian-style task tracking.

Enable Checkbox Completion

require("markdown-plus").setup({
  list = {
    checkbox_completion = {
      enabled = true,  -- Enable the feature
    },
  },
})

When enabled, checking a task automatically adds a timestamp:

- [ ] Buy groceries     →  - [x] Buy groceries ✅ 2025-12-28

Timestamp Format Options

Four formats are available:

Format Output Best For
emoji ✅ 2025-12-28 Universal visibility (default)
comment <!-- completed: 2025-12-28 --> Hidden metadata
dataview [completion:: 2025-12-28] Obsidian Dataview queries
parenthetical (completed: 2025-12-28) Plain text compatibility
require("markdown-plus").setup({
  list = {
    checkbox_completion = {
      enabled = true,
      format = "dataview",  -- Use Dataview format for Obsidian
    },
  },
})

Custom Date Formats

Use any valid os.date() format string:

require("markdown-plus").setup({
  list = {
    checkbox_completion = {
      enabled = true,
      date_format = "%d/%m/%Y",  -- European format: 28/12/2025
    },
  },
})

Common date formats:

Format String Output
%Y-%m-%d 2025-12-28 (ISO 8601, default)
%d/%m/%Y 28/12/2025 (European)
%m/%d/%Y 12/28/2025 (US)
%Y-%m-%d %H:%M 2025-12-28 14:30 (with time)
%B %d, %Y December 28, 2025 (long format)

Behavior Options

require("markdown-plus").setup({
  list = {
    checkbox_completion = {
      enabled = true,
      remove_on_uncheck = true,   -- Remove timestamp when unchecking (default: true)
      update_existing = true,     -- Update timestamp when re-checking (default: true)
    },
  },
})
  • remove_on_uncheck: When true, unchecking a task removes the timestamp. When false, the timestamp is preserved.
  • update_existing: When true, re-checking a task that already has a timestamp updates it to today's date. When false, the original timestamp is preserved.