Skip to content

Commit 449fa33

Browse files
committed
feat(keybindings): add default <leader>mH keymap for insert header
Adds a default keybinding '<leader>mH' in Normal and Visual modes to trigger the 'insert_header' action. This provides a convenient shortcut for a common Markdown editing task out-of-the-box. Updates the default configuration in and documents the new keybinding in and .
1 parent 4b392a7 commit 449fa33

File tree

20 files changed

+1346
-783
lines changed

20 files changed

+1346
-783
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,9 @@ A clear and concise description of what the bug is.
1212
**To Reproduce**
1313
Steps to reproduce the behavior:
1414

15-
1. Use this minimal configuration:
16-
```lua
17-
-- Paste minimal init.lua or relevant setup here
18-
```
19-
2. Start Neovim with `nvim -u minimal_init.lua`
20-
3. Run the following steps:
21-
- Step 1
22-
- Step 2
23-
- ...
15+
1. Go to '...'
16+
2. Click on '...'
17+
3. Scroll down to '...'
2418
4. See error
2519

2620
**Expected behavior**
@@ -31,9 +25,15 @@ If applicable, add screenshots to help explain your problem.
3125

3226
**Environment (please complete the following information):**
3327

34-
- Neovim Version: [e.g. NVIM v0.9.0]
35-
- OS: [e.g. Ubuntu 22.04]
36-
- markdown-shortcuts.nvim version: [e.g. 0.1.0 or commit hash]
28+
- Neovim Version [e.g. NVIM v0.9.1]:
29+
- OS [e.g. Ubuntu 22.04]:
30+
- markdown-tools.nvim version: [e.g. 0.1.0 or commit hash]
3731

3832
**Additional context**
3933
Add any other context about the problem here.
34+
35+
- Minimal `init.lua` or `init.vim` to reproduce the issue:
36+
37+
```lua
38+
-- Your minimal config here
39+
```

CHANGELOG.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<!-- markdownlint-disable MD024 -->
2+
13
# Changelog
24

35
All notable changes to this project will be documented in this file.
@@ -9,22 +11,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
911

1012
### Added
1113

14+
- Added default keybinding `<leader>mH` for inserting headers.
15+
- Added ability to use generator functions for frontmatter and placeholders in templates.
16+
1217
### Changed
1318

19+
- Updated health checks (`:checkhealth markdown-tools`).
20+
1421
### Deprecated
1522

1623
### Removed
1724

1825
### Fixed
1926

27+
- Fixed minor bugs to enhance performance.
28+
2029
### Security
2130

22-
## [0.1.0] - 2025-05-04
31+
## [0.1.0] - 2024-03-10
2332

2433
### Added
2534

26-
- Initial release of `markdown-shortcuts.nvim`.
27-
- Features include: inserting headers, code blocks, bold/italic text, links, tables, checkboxes; toggling checkboxes; creating files from templates; list continuation; configurable keymaps and commands; optional buffer settings.
35+
- Initial release of `markdown-tools.nvim`.
2836

29-
[Unreleased]: https://github.com/magnusriga/markdown-shortcuts.nvim/compare/v0.1.0...HEAD
30-
[0.1.0]: https://github.com/magnusriga/markdown-shortcuts.nvim/releases/tag/v0.1.0
37+
[Unreleased]: https://github.com/magnusriga/markdown-tools.nvim/compare/v0.1.0...HEAD
38+
[0.1.0]: https://github.com/magnusriga/markdown-tools.nvim/releases/tag/v0.1.0

CONTRIBUTING.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
# Contributing to markdown-shortcuts.nvim
1+
# Contributing to markdown-tools.nvim
22

3-
Thank you for considering contributing to `markdown-shortcuts.nvim`! We appreciate your time and effort.
3+
Thank you for considering contributing to `markdown-tools.nvim`! We appreciate your time and effort.
44

55
## How Can I Contribute?
66

77
### Reporting Bugs
88

9-
- Ensure the bug was not already reported by searching on GitHub under [Issues](https://github.com/magnusriga/markdown-shortcuts.nvim/issues).
10-
- If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/magnusriga/markdown-shortcuts.nvim/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring.
9+
- Ensure the bug was not already reported by searching on GitHub under [Issues](https://github.com/magnusriga/markdown-tools.nvim/issues).
10+
- If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/magnusriga/markdown-tools.nvim/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring.
1111
- Use the "Bug Report" template if available.
1212

1313
### Suggesting Enhancements

README.md

Lines changed: 162 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
11
# markdown-tools.nvim
22

3-
<!-- Badges (replace with actual badges) -->
4-
53
[![Lua](https://img.shields.io/badge/Lua-blue.svg?style=flat-square&logo=lua)](https://www.lua.org)
64
[![License](https://img.shields.io/github/license/magnusriga/markdown-tools.nvim?style=flat-square)](LICENSE)
75

86
> Enhancing your Markdown editing experience in Neovim with intuitive shortcuts and commands.
97
108
`markdown-tools.nvim` provides a set of commands and configurable keymaps to streamline common Markdown editing tasks, from inserting elements like headers and code blocks to managing checkbox lists and creating files from templates.
119

10+
For users migrating from plugins like [obsidian.nvim](https://github.com/epwalsh/obsidian.nvim), `markdown-tools.nvim` aims to fill some gaps by offering features such as creating new notes based on templates with predefined frontmatter, helping maintain a familiar workflow.
11+
12+
The markdown created, including the frontmatter, is compatible with [obsidian](https://obsidian.md/) and other Markdown editors.
13+
1214
## ✨ Features
1315

14-
- **Insert Markdown Elements:** Quickly add headers, code blocks (with language prompt), bold/italic text, links, tables, and checkbox list items.
15-
- **Visual Mode Integration:** Wrap selected text with bold, italic, links, or code blocks.
16+
- **Template Creation:** Create new Markdown files from predefined templates using your choice of picker (`fzf`, `telescope`, `snacks`). Automatically adds frontmatter with configurable placeholders (e.g., `alias`, `tags`).
17+
- **Insert Markdown Elements:** Quickly add links, checkboxes, tables, headers, bold/italic/highlight text, code blocks (with language prompt), and more.
18+
- **Visual Mode Integration:** Wrap selected text with bold, italic, links, or highlights.
1619
- **Checkbox Management:** Insert new checkboxes (`- [ ]`) and toggle their state (`- [x]`).
17-
- **Template Creation:** Create new Markdown files from predefined templates using your choice of picker (`fzf`, `telescope`, `mini.pick`).
1820
- **List Continuation:** Automatically continue Markdown lists (bulleted, numbered, checkbox) when pressing Enter.
1921
- **Configurable:** Customize keymaps, enable/disable commands, set template directory, choose picker, and configure Markdown-specific buffer options.
20-
- **Preview:** Basic preview command (requires external tool configuration).
22+
- **Preview:** Preview command, using other auto-detected nvim plugins (see below) or default system application.
2123

2224
## ⚡️ Requirements
2325

@@ -28,7 +30,7 @@
2830

2931
Use your favorite plugin manager.
3032

31-
**lazy.nvim**
33+
### lazy.nvim
3234

3335
```lua
3436
{
@@ -45,7 +47,7 @@ Use your favorite plugin manager.
4547
}
4648
```
4749

48-
**packer.nvim**
50+
### packer.nvim
4951

5052
```lua
5153
use {
@@ -73,19 +75,71 @@ require('markdown-tools').setup({
7375
-- Directory containing your Markdown templates
7476
template_dir = vim.fn.expand("~/.config/nvim/templates"),
7577

76-
-- Picker to use for selecting templates ('fzf', 'telescope', 'snacks'/'mini.pick')
78+
-- Picker to use for selecting templates ('fzf', 'telescope', 'snacks')
7779
picker = "fzf",
7880

79-
-- Default frontmatter fields for new files created from templates
80-
alias = {},
81-
tags = {},
81+
-- Whether to automatically insert frontmatter if the template doesn't have it
82+
insert_frontmatter = true,
83+
84+
-- Functions to generate frontmatter fields.
85+
-- These functions determine the values used when automatically inserting frontmatter
86+
-- AND when replacing placeholders in templates.
87+
-- Each function receives a table `opts` with:
88+
-- opts.timestamp (string): YYYYMMDDHHMM
89+
-- opts.filename (string): Full filename including .md extension.
90+
-- opts.sanitized_name (string): Filename sanitized for use in IDs.
91+
-- opts.filepath (string): Absolute path to the new file.
92+
-- Return nil from a function to omit that field from automatically generated frontmatter
93+
-- and replace its corresponding placeholder with an empty string.
94+
95+
-- Corresponds to {{id}} placeholder
96+
frontmatter_id = function(opts)
97+
-- Default: YYYYMMDDHHMM_sanitized-filename
98+
return opts.timestamp .. "_" .. opts.sanitized_name
99+
end,
100+
101+
-- Corresponds to {{title}} placeholder
102+
frontmatter_title = function(opts)
103+
-- Default: Filename without extension
104+
return vim.fn.fnamemodify(opts.filename, ":t:r")
105+
end,
106+
107+
-- Corresponds to {{alias}} placeholder (expects a list/table of strings)
108+
frontmatter_alias = function(_opts)
109+
-- Default: Empty list
110+
return {}
111+
end,
112+
113+
-- Corresponds to {{tags}} placeholder (expects a list/table of strings)
114+
frontmatter_tags = function(_opts)
115+
-- Default: Empty list
116+
return {}
117+
end,
118+
119+
-- Corresponds to {{date}} placeholder
120+
frontmatter_date = function(_opts)
121+
-- Default: Current date YYYY-MM-DD
122+
return os.date("%Y-%m-%d")
123+
end,
124+
125+
-- Define custom frontmatter fields and their generator functions.
126+
-- The key is the field name (used in frontmatter and as the placeholder {{key}}).
127+
-- The value is a function receiving the `opts` table.
128+
-- It can return a string, a table (list) of strings, or nil.
129+
frontmatter_custom = {},
130+
-- Example of how to define custom fields:
131+
-- frontmatter_custom = {
132+
-- status = function(_opts) return "draft" end,
133+
-- related = function(_opts) return {} end,
134+
-- },
82135

83136
-- Keymappings for shortcuts. Set to `false` or `""` to disable.
84137
keymaps = {
85138
create_from_template = "<leader>mnt", -- New Template
86-
insert_header = "<leader>mh", -- Header
139+
insert_header = "<leader>mH", -- Header
87140
insert_code_block = "<leader>mc", -- Code block
88141
insert_bold = "<leader>mb", -- Bold
142+
insert_highlight = "<leader>mh", -- Highlight
89143
insert_italic = "<leader>mi", -- Italic
90144
insert_link = "<leader>ml", -- Link
91145
insert_table = "<leader>mt", -- Table
@@ -127,6 +181,61 @@ require('markdown-tools').setup({
127181
})
128182
```
129183

184+
### Types
185+
186+
Here are the type definitions for the configuration options:
187+
188+
```lua
189+
---@class KeymapConfig
190+
---@field create_from_template string? Keymap for creating from template
191+
---@field insert_header string? Keymap for inserting header
192+
---@field insert_list_item string? Keymap for inserting list item
193+
---@field insert_code_block string? Keymap for inserting code block
194+
---@field insert_bold string? Keymap for inserting bold text
195+
---@field insert_italic string? Keymap for inserting italic text
196+
---@field insert_link string? Keymap for inserting link
197+
---@field insert_table string? Keymap for inserting table
198+
---@field insert_checkbox string? Keymap for inserting checkbox
199+
---@field toggle_checkbox string? Keymap for toggling checkbox
200+
---@field preview string? Keymap for previewing markdown
201+
202+
---@class CommandEnableConfig
203+
---@field create_from_template boolean Enable create from template command
204+
---@field insert_header boolean Enable insert header command
205+
---@field insert_code_block boolean Enable insert code block command
206+
---@field insert_bold boolean Enable insert bold text command
207+
---@field insert_italic boolean Enable insert italic text command
208+
---@field insert_link boolean Enable insert link command
209+
---@field insert_table boolean Enable insert table command
210+
---@field insert_checkbox boolean Enable insert checkbox command
211+
---@field toggle_checkbox boolean Enable toggle checkbox command
212+
---@field preview boolean Enable preview command
213+
214+
---@class Config
215+
---@field template_dir string Directory for templates
216+
---@field picker 'fzf' | 'snacks' | 'telescope' Picker to use for file selection
217+
---@field alias string[] Default aliases for new markdown files
218+
---@field tags string[] Default tags for new markdown files
219+
---@field insert_frontmatter boolean Automatically add frontmatter when creating new markdown files with e.g. `MarkdownNewTemplate`.
220+
---@field frontmatter_id fun(opts: {timestamp: string, filename: string, sanitized_name: string, filepath: string}):string | nil Function to generate the 'id' field in the frontmatter. Return nil to omit the id field.
221+
---@field frontmatter_title fun(opts: {timestamp: string, filename: string, sanitized_name: string, filepath: string}):string | nil Function to generate the 'title' field in the frontmatter. Return nil to omit the title field.
222+
---@field frontmatter_alias fun(opts: {timestamp: string, filename: string, sanitized_name: string, filepath: string}):string[] | nil Function to generate the 'alias' field in the frontmatter. Return nil to omit the alias field.
223+
---@field frontmatter_tags fun(opts: {timestamp: string, filename: string, sanitized_name: string, filepath: string}):string[] | nil Function to generate the 'tags' field in the frontmatter. Return nil to omit the tags field.
224+
---@field frontmatter_date fun(opts: {timestamp: string, filename: string, sanitized_name: string, filepath: string}):string | nil Function to generate the 'date' field in the frontmatter. Return nil to omit the date field.
225+
---@field frontmatter_custom table<string, fun(opts: {timestamp: string, filename: string, sanitized_name: string, filepath: string}):string|string[]|nil> Table defining custom frontmatter fields and their generator functions.
226+
---@field keymaps KeymapConfig Keymappings for markdown shortcuts
227+
---@field commands CommandEnableConfig Configuration for enabling/disabling commands
228+
---@field preview_command string|function|nil Command or function to use for previewing markdown
229+
---@field enable_local_options boolean Whether to enable local options for markdown files
230+
---@field wrap boolean Whether to enable line wrapping for markdown files
231+
---@field conceallevel number Conceallevel for markdown files
232+
---@field concealcursor string Concealcursor for markdown files
233+
---@field spell boolean Whether to enable spell checking for markdown files
234+
---@field spelllang string Language for spell checking
235+
---@field file_types string[] File types where keymaps should be active
236+
---@field continue_lists_on_enter boolean Automatically continue lists on Enter
237+
```
238+
130239
## 🚀 Usage
131240

132241
### Commands
@@ -137,20 +246,22 @@ The following commands are available, most work in both visual and normal mode:
137246
- `:MarkdownHeader`: Insert a header. Prompts for level (1-6) or uses `[count]` (e.g., `:3MarkdownHeader`). In Visual mode, wraps selection.
138247
- `:MarkdownCodeBlock`: Insert a code block. Prompts for language. In Visual mode, wraps selection.
139248
- `:MarkdownBold`: Insert `**bold text**`. In Visual mode, wraps selection.
249+
- `:MarkdownHighlight`: Insert `==highlight text==`. In Visual mode, wraps selection.
140250
- `:MarkdownItalic`: Insert `*italic text*`. In Visual mode, wraps selection.
141251
- `:MarkdownLink`: Insert `[link text](url)`. Prompts for text and URL. In Visual mode, uses selection as text and prompts for URL.
142252
- `:MarkdownInsertTable`: Insert a table. Prompts for rows and columns.
143253
- `:MarkdownCheckbox`: Insert a checkbox list item (`- [ ]`). In Visual mode, uses selection as text.
144254
- `:MarkdownToggleCheckbox`: Toggles the checkbox state (`[ ]` <=> `[x]`) on the current line.
145-
- `:MarkdownPreview`: Preview markdown.
255+
- `:MarkdownPreview`: Preview markdown. Saves the current file, then attempts to preview using: 1) the configured `preview_command`, 2) an auto-detected plugin (`markdown-preview.nvim`, `peek.nvim`, `glow.nvim`, `nvim-markdown-preview`), or 3) the system's default application as a fallback.
146256

147257
### Keymaps
148258

149259
Default keymaps are provided (see Configuration). Use them in Normal or Visual mode within Markdown files.
150260

151-
- `<leader>mh`: Insert header (prompts or use count).
261+
- `<leader>mH`: Insert header.
152262
- `<leader>mc`: Insert code block.
153263
- `<leader>mb`: Insert bold.
264+
- `<leader>mh`: Insert highlight.
154265
- `<leader>mi`: Insert italic.
155266
- `<leader>ml`: Insert link.
156267
- `<leader>mt`: Insert table.
@@ -159,6 +270,38 @@ Default keymaps are provided (see Configuration). Use them in Normal or Visual m
159270
- `<leader>mp`: Preview (if configured).
160271
- `<leader>mnt`: Create new file from template.
161272

273+
### Creating Markdown Files from Templates
274+
275+
The `:MarkdownNewTemplate` command (default keymap `<leader>mnt`) allows you to create new Markdown files based on templates stored in your configured `template_dir`.
276+
277+
1. Run the command.
278+
2. Select a template file using the configured picker (fzf, telescope, or snacks).
279+
3. Enter a name for the new file (the `.md` extension will be added automatically if omitted).
280+
4. The new file will be created in the same directory as the currently open file.
281+
282+
#### Frontmatter Handling
283+
284+
When creating a file from a template, the configured frontmatter generator functions (`frontmatter_id`, `frontmatter_title`, `frontmatter_custom`, etc.) are always executed first to produce values for the standard and custom fields.
285+
286+
These generated values are then used in two ways:
287+
288+
1. **Placeholder Replacement:** The content of the selected template file is processed. The following placeholders are supported and replaced with their corresponding generated values:
289+
290+
- `{{id}}`: Value from `frontmatter_id` function.
291+
- `{{title}}`: Value from `frontmatter_title` function.
292+
- `{{date}}`: Value from `frontmatter_date` function.
293+
- `{{alias}}`: YAML list format of values from `frontmatter_alias` function (e.g., `["alias1", "alias2"]`).
294+
- `{{tags}}`: YAML list format of values from `frontmatter_tags` function (e.g., `["tag1", "tag2"]`).
295+
- `{{datetime}}`: Current date and time (YYYY-MM-DD HH:MM:SS). Generated internally.
296+
- `{{timestamp}}`: Timestamp used during generation (YYYYMMDDHHMM). Generated internally.
297+
- `{{key}}`: For each key in `frontmatter_custom`, the corresponding placeholder `{{key}}` is replaced by the value returned by its function. If the function returns a list, it's inserted in YAML list format (e.g., `["item1", "item2"]`).
298+
299+
If a generator function returns `nil`, the corresponding placeholder is replaced with an empty string. **Any other text within double curly braces (e.g., `{{unsupported}}`) that does not match a supported placeholder will be left unchanged in the template content.**
300+
301+
2. **Automatic Frontmatter Insertion:** After placeholder replacement, the plugin checks if the template content starts with `---`.
302+
- If it **does not** start with `---` AND the `insert_frontmatter` configuration option is `true` (the default), a new frontmatter block is automatically added to the beginning of the file. This block includes all fields (standard and custom) for which the generator function returned a non-nil value, formatted correctly in YAML. List values will be formatted like `tags: [tag1, tag2]`.
303+
- If it **does** start with `---`, or if `insert_frontmatter` is `false`, no new frontmatter block is inserted. The template's existing frontmatter (with placeholders already replaced) is kept as is.
304+
162305
### List Continuation
163306

164307
When `continue_lists_on_enter` is `true`, pressing `Enter` in a Markdown list item (bullet `*`, `-`, `+`; numbered `1.`; checkbox `- [ ]`, `- [x]`) will automatically insert the next list marker on the new line.
@@ -174,3 +317,7 @@ Please see CONTRIBUTING.md or open an issue/pull request.
174317
## License
175318

176319
Distributed under the MIT License. See `LICENSE` file for more information.
320+
321+
## 🙏 Credits
322+
323+
- The excellent [obsidian.nvim](https://github.com/epwalsh/obsidian.nvim), for inspiration on various features, including creating Markdown notes from templates.

0 commit comments

Comments
 (0)