Heading Level Changer

approved

by Birchove

Promote or demote Markdown heading levels (h1-h6) for the selected lines via hotkeys or the editor context menu. Body text, images, tables, tags and code blocks are left untouched. - This plugin has not been manually reviewed by Obsidian staff.

1 stars177 downloadsUpdated 1mo agoMIT

Heading Level Changer

Promote or demote Markdown heading levels (h1–h6) for the selected lines in Obsidian — via hotkeys, the command palette, or the editor right-click menu. Body text, images, tables, tags and code blocks are left untouched.

选中一段文字,一键把其中的标题升级(## → #)或降级(## → ###)。正文、图片、表格、标签、代码块一律不受影响。

Features

  • Promote headings in the selection: ## Title# Title
  • Demote headings in the selection: ## Title### Title
  • Works on every selected line at once, including multiple selections / cursors
  • Nothing selected? The command acts on the line under the cursor
  • Safe heading detection — a line is a heading only if it starts with 1–6 # characters followed by whitespace. In Obsidian a # without a trailing space is a tag (#tag), and tags are never modified
  • Lines inside ```/~~~ code fences and %% comment blocks are skipped automatically, so shell/Python comments are never corrupted
  • Body text, images (![[…]]), tables, lists and blockquotes pass through unchanged
  • Levels are clamped at h1 and h6 (Markdown has no h0/h7): promoting an h1 or demoting an h6 is a no-op
  • Single undo step per operation; your selection is restored afterwards, so you can hold the hotkey to walk levels
  • Works in both Live Preview and Source mode, on desktop and mobile

Usage

  1. Select one or more lines (or just place the cursor on a line).
  2. Then either:
    • press your bound hotkey, or
    • right-click → Promote heading level / Demote heading level, or
    • open the command palette (Mod+P) and search for “heading level”.

Default hotkeys

ActionmacOSWindows / Linux
Promote heading (## → #)⌘ + ⌥ + ↑Ctrl + Alt + ↑
Demote heading (## → ###)⌘ + ⌥ + ↓Ctrl + Alt + ↓

The plugin registers hotkeys with Obsidian's Mod modifier, which maps to ⌘ Cmd on macOS and Ctrl on Windows/Linux automatically. If a default conflicts with your setup, rebind or remove it in Settings → Hotkeys (search for “heading”) — every user binding there takes precedence.

Behavior details

  • A line is treated as a heading only when it matches CommonMark ATX rules with the Obsidian tag caveat: up to 3 leading spaces, 1–6 #, then at least one space/tab. So:
    • #tag, #, ## (no trailing whitespace) → not touched (tag-like)
    • ####### seven hashes → not a heading, not touched
    • 4+ leading spaces or a leading tab → code block in Markdown, not touched
  • Headings inside blockquotes (> # Title) are out of scope and not touched (they don't start at column 0).
  • Setext headings (underline style) are not handled — only # ATX headings.
  • If nothing in the selection can be changed (no headings, or all of them already at the h1/h6 boundary), a notice is shown and the document is not modified.

Installation

From the community plugin store

This plugin targets the official Obsidian community store. Once it is approved, install it via Settings → Community plugins → Browse → “Heading Level Changer”.

Manual / pre-release

  1. Copy main.js, manifest.json into <your-vault>/.obsidian/plugins/heading-level-changer/.
  2. Reload Obsidian, then enable Heading Level Changer in Settings → Community plugins.

Or use BRAT with this repository.

Development

npm install     # install dev dependencies
npm run dev     # watch mode (esbuild), outputs main.js
npm run build   # type-check (tsc) + production build
npm test        # unit tests for the heading logic (48 cases)
npm run smoke   # end-to-end test of the built main.js against a mocked editor

Project layout:

  • main.ts — plugin entry: commands, default hotkeys, editor context menu, selection handling
  • src/logic.ts — pure, obsidian-free logic: heading parsing, level shifting, code-fence/comment detection
  • tests/logic.test.ts — unit tests
  • scripts/smoke.cjs — loads the built main.js with a mocked obsidian module and simulates real command invocations

Releasing & community-store submission checklist

  1. git init, commit, and push to a GitHub repository (conventionally named heading-level-changer or obsidian-heading-level-changer).
  2. Bump the version: npm version patch|minor|major — this runs version-bump.mjs, keeping manifest.json and versions.json in sync.
  3. Push the tag (git push --tags). The bundled GitHub Action (.github/workflows/release.yml) builds and creates a draft release containing main.js and manifest.json; review and publish it.
  4. Submit the plugin via the Obsidian plugin submission form using the repository URL. The release must expose main.js and manifest.json as assets (they do).
  5. Keep manifest.json fields accurate: id must stay heading-level-changer, version must match the release tag, and minAppVersion must reflect the oldest supported Obsidian version.

Notes on store compliance:

  • The plugin uses only the official, documented Obsidian API (Plugin, addCommand, editor-menu, Editor.transaction, Notice) — no private APIs, no network access, no data collection.
  • isDesktopOnly is false; the editor APIs used are available on mobile as well.
  • MIT licensed.

中文说明

功能

  • 选中一行或多行(支持多光标/多选区),一键升级或降级其中的标题级别(## → # / ## → ###)
  • 不选中任何文本时,作用于光标所在行
  • 正文、图片(![[…]])、表格、列表、引用块一律不受影响
  • # 后没有空格的行(如 #tag)在 Obsidian 中是标签,绝不会被修改
  • ``` / ~~~ 代码块和 %% 注释块内部的行(例如 shell、python 注释)自动跳过
  • 级别封顶:h1 不能再升级,h6 不能再降级;选区内没有可修改的标题时会弹出提示
  • 每次操作只占一个撤销记录,操作后选区自动恢复,可以按住快捷键连续升降级
  • 支持实时预览(Live Preview)和源码模式,桌面端、移动端均可用

使用方法

  1. 选中若干行(或把光标停在目标行上)
  2. 任选一种触发方式:
    • 按你绑定的快捷键;
    • 右键 → Promote heading level(升级)/ Demote heading level(降级);
    • 打开命令面板(Mod+P),搜索 "heading level"。

默认快捷键

操作macOSWindows / Linux
升级标题(## → #)⌘ + ⌥ + ↑Ctrl + Alt + ↑
降级标题(## → ###)⌘ + ⌥ + ↓Ctrl + Alt + ↓

快捷键使用 Obsidian 的 Mod 修饰键,macOS 上自动对应 ⌘ Cmd,Windows/Linux 上对应 Ctrl。如果与你的其他设置冲突,可在 设置 → 快捷键 中搜索 "heading" 改绑或移除。

行为细节

  • 标题识别规则:行首(允许最多 3 个前导空格)+ 1~6 个 # + 至少一个空格或 Tab。因此:
    • #tag###(# 后无空格)→ 视为标签类内容,不修改;
    • #######(7 个及以上 #)→ 不是标题,不修改;
    • 4 个及以上前导空格、或以 Tab 开头 → Markdown 中是代码块,不修改。
  • 引用块内的标题(> # 标题)不在处理范围内(未从行首开始)。
  • 只处理 # 风格的 ATX 标题,不处理下划线式(setext)标题。

安装

  • 上架社区插件市场后:设置 → 第三方插件 → 浏览 → 搜索 "Heading Level Changer"。
  • 手动安装:把 main.jsmanifest.json 复制到 <你的库>/.obsidian/plugins/heading-level-changer/,重启 Obsidian 后在社区插件中启用;也可以用 BRAT 添加本仓库。

开发与发布

开发命令见上方 Development 小节;上架社区市场的完整清单见 Releasing & community-store submission checklist 小节。

License

MIT

For plugin developers

Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.