Lapel Obsidian Plugin
repository·main·Indexed 40 days ago
https://github.com/liamcain/obsidian-lapelAn Obsidian plugin that adds visual heading level indicators (markers) to the editor gutter to help users navigate document structure. It includes a menu for quick switching of heading levels and supports CSS customization of markers via the .cm-heading-marker class and --heading-marker variable. Version 0.1.10.
What's inside Lapel
- Lapel is an Obsidian plugin designed to help users visually distinguish between heading levels. It works by displaying a marker (e.g., h1, h2, h3) next to each heading in the editor gutter. It also provides a menu to allow for quick switching of heading levels.
Install dependencies for Lapel development
mainTo set up the development environment, ensure you have Node.js (LTS recommended) and
pnpminstalled. Usepnpmexclusively to ensure dependency versions match thepnpm-lock.yamlfile. Do not usenpmoryarn.pnpm installManual smoke test checklist for Lapel
mainBecause Lapel does not have an automated test suite, developers must perform manual smoke testing in a real Obsidian vault to verify stability. Ensure the following behaviors are correct:
- Linting:
pnpm run lintmust exit with code 0. - Production Build:
pnpm run buildmust complete without errors or warnings. - Gutter Markers: Markers must appear next to each heading in the editor.
- Heading Menu: Clicking a marker must open the heading-level menu; selecting a level must rewrite the heading correctly.
- Settings Integration: Toggling "show before/after line numbers" must move the gutter as expected.
- Table Cells: Markers must disappear inside table cell editors.
- Folding: Folded headings must change level cleanly without wiping the block content.
- RTL Support: Markers must align correctly in Right-to-Left mode.
- Popout Windows: The heading menu must attach to the correct window when using popouts.
- Linting:
Develop Lapel against a local Obsidian vault
mainSince
esbuilddoes not automatically copy files into your Obsidian vault, use one of the following two workflows to test your changes:Option 1: Symlink (Recommended for active development)
Create a symbolic link from your repository into your test vault's plugin folder. This allows
pnpm run devto update themain.jsfile directly inside the vault.ln -s "$PWD" "/path/to/TestVault/.obsidian/plugins/lapel"After rebuilding, reload the plugin in Obsidian by toggling it off and on in Settings → Community plugins, or use the Hot Reload community plugin.
Option 2: Build and Copy
Manually build the production files and copy them to the vault's plugin folder.
pnpm run build cp main.js manifest.json styles.css /path/to/TestVault/.obsidian/plugins/lapel/# Symlink approach ln -s "$PWD" "/path/to/TestVault/.obsidian/plugins/lapel" pnpm run dev # Build and copy approach pnpm run build cp main.js manifest.json styles.css /path/to/TestVault/.obsidian/plugins/lapel/Configure Lapel settings
mainLapel provides the following configuration options in the Obsidian settings menu:
- Show before line numbers: When enabled, heading levels are displayed before the line numbers in the editor gutter. By default, they are displayed after the line numbers.
- Show in source mode: Enables or disables the visibility of heading levels when Obsidian is in Source Mode.
Customize heading markers with CSS
mainYou can target specific heading levels for visual customization using CSS. Each heading marker uses the
.cm-heading-markerclass and adata-levelattribute corresponding to the heading level (e.g.,"1"for H1,"2"for H2). You can change the appearance by overriding the--heading-markerCSS variable.Example: To change the H6 marker to a burger menu icon:
.cm-heading-marker[data-level="6"] { --heading-marker: "☰"; }Configure headingMarkerPlugin options
mainWhen calling
headingMarkerPlugin, you can provide an options object of typeHeadingMarkerPluginOptsto control visibility and gutter placement:Option Type Description showBeforeLineNumbersbooleanIf true, the gutter is given high precedence (Prec.high) to appear before line numbers. Iffalse, it usesPrec.low.showInSourceModebooleanIf true, heading markers will be rendered even when the editor is in Source Mode. Iffalse, they only render in Live Preview mode.interface HeadingMarkerPluginOpts { showBeforeLineNumbers: boolean; showInSourceMode: boolean; }Build and lint Lapel
mainLapel uses
esbuildto bundle the plugin into a singlemain.jsfile. The following commands are available viapnpm:pnpm run lint: Runs ESLint over all.tsfiles. This must pass before any release.pnpm run dev: Runsesbuildin watch mode with inline sourcemaps. It outputsmain.jsto the repo root.pnpm run build: Runslintfirst, then performs a minified productionesbuild. It outputs a productionmain.js(without sourcemaps) to the repo root.
pnpm run lint pnpm run dev pnpm run buildUse LapelPlugin to manage heading markers
mainThe
LapelPluginclass is the main entrypoint for the Obsidian plugin. It manages the lifecycle of heading markers within the editor using CodeMirror extensions. It provides a mechanism to update settings dynamically, which triggers a workspace update to reflect changes in how heading markers are displayed (e.g., whether they appear before line numbers or in source mode).// Note: As an Obsidian plugin, this is typically instantiated by the Obsidian app. // Developers interacting with the plugin instance can use updateSettings to change behavior. await plugin.updateSettings((oldSettings) => ({ showBeforeLineNumbers: true, showInSourceMode: false }));Initialize the headingMarkerPlugin
mainThe
headingMarkerPluginfunction creates a CodeMirror view plugin that adds heading level markers to the editor gutter. It provides a visual indicator of heading levels and allows users to change heading levels via a context menu when clicking the marker.It returns an array containing the marker plugin and a gutter plugin. The gutter's priority (precedence) is determined by the
showBeforeLineNumbersoption.import { headingMarkerPlugin } from './src/headingWidget'; const plugin = headingMarkerplugin({ showBeforeLineNumbers: true, showInSourceMode: false });Update Lapel settings via updateSettings()
mainThe
updateSettingsmethod allows for transactional updates to the plugin's configuration. It accepts a transformation functiontxthat receives the currentLapelSettingsand returns aPartial<LapelSettings>.If the updated settings affect visual markers (specifically
showBeforeLineNumbersorshowInSourceMode), the plugin automatically regenerates the CodeMirror extension and callsthis.app.workspace.updateOptions()to apply the changes immediately to the editor./** * @param tx A function that takes the current settings and returns the changes to apply. */ public async updateSettings( tx: (old: LapelSettings) => Partial<LapelSettings> ): Promise<void>LapelSettings Interface
mainThe
LapelSettingsinterface defines the schema for the plugin's configuration. It contains the following boolean properties:showBeforeLineNumbers: Controls the gutter position of heading markers.showInSourceMode: Controls visibility in Obsidian's source mode.
export interface LapelSettings { showBeforeLineNumbers: boolean; showInSourceMode: boolean; }