Releases: lucasgaldinos/obsidian-gfm-headers
Releases · lucasgaldinos/obsidian-gfm-headers
Release list
1.4.0
What's Changed
- Bump version to 1.3.8 and update changelog by @lucasgaldinos in #1
New Contributors
- @lucasgaldinos made their first contribution in #1
Full Changelog: 1.3.8...1.4.0
1.3.8
Fixed
- Community review: ESLint fatal error — minAppVersion was '1.12' (invalid semver). Fixed to '1.0.0'.
- versions.json — added missing entries for 1.3.7 and 1.3.8.
- Sentence case in settings UI — fixed 5 obsidianmd/ui/sentence-case warnings.
- README overhaul — badges, before/after table, Settings section, docs links, removed stale GFM collision limitation.
- .gitignore compliance — untracked .agents/ and .github/instructions/ files.
Added
- ESLint config (eslint.config.mjs) with eslint-plugin-obsidianmd
- npm run lint script — catch review failures before submitting
- Pre-submission validation section in README
1.3.7
title: "Changelog"
tags: [changelog, gfm-heading-links, obsidian-plugin]
description: "Release history and notable changes for the GFM Heading Links Obsidian plugin"
date_created: 2026-07-02
date_changed: 2026-07-18
author: "Lucas Galdino"
Changelog
All notable changes to the GFM Heading Links plugin are documented in this file.
The format is based on Keep a Changelog, and this project adheres to
Semantic Versioning.
[1.3.1][] — 2026-07-20
Note: This release consolidates the original v1.3.1 release infrastructure work and all
subsequent community review compliance fixes (previously spread across v1.3.2–1.3.6).
Those intermediate releases have been deleted — this is the definitive v1.3.1.
Added
- Release Infrastructure:
LICENSE(MIT), GitHub Actions release workflow
(.github/workflows/release.yml), branch strategy (main=production/DEBUG_ENABLED=false,
dev=development/DEBUG_ENABLED=true). - CI Artifact Attestations (
actions/attest@v4): Supply-chain provenance for release
artifacts. authorandauthorUrlpopulated inmanifest.json..gitignorehardened:data.json,*.pngexclusions, refined.github/and.agents/
patterns.- Typed Internal APIs (
src/vault-config.ts):getVaultConfig()andisWikilinksEnabled()
helpers replace inline(vault as any)casts. - Type-Safe Editor Suggest:
SuggestionValue,EditorSuggestInstance,
SuggestionDropdownIteminterfaces andunwrapDropdownItem()type guard — allany
types eliminated from the suggest pipeline.
Changed
package.jsonversion aligned withmanifest.json(both1.3.1).- All documentation updated:
docs/plan/*,docs/research/architectural-history.md,
docs/architecture.md,README.md. - Release links in
CHANGELOG.mdfixed to point tolucasgaldinos/obsidian-gfm-headers. - Production console hygiene:
console.log→console.debugin gated debug system
(src/debug.ts).console.debugis suppressed by default in browser DevTools at the
default "Info" log level. - Arrow functions for all monkeypatch assignments:
workspace.openLinkText,
workspace.trigger, andsuggest.selectSuggestionall use arrow functions with
explicit.call(workspace, ...)rebinding. .bind(workspace)at method capture:originalOpenLinkTextandoriginalTrigger
are bound at capture time via.bind(workspace), eliminatingthis-scoping warnings
from Obsidian's review linter.- Safe array initialization:
new Array<number>(n).fill(0)replacesnew Array(n).fill(0)
to avoid implicitany[]inference. window.setTimeout/window.clearTimeoutused instead of baresetTimeout/
clearTimeoutfor browser global compliance.loadData()cast asPartial<GfmSettings>instead ofas any.view.currentModecast as typed interface instead ofas any.injectVirtualBlockandselectSuggestionuse typedPosandSuggestionValueparams.
Removed
- Accidentally committed
image.png,image copy.png, anddata.json. - All
eslint-disableand@typescript-eslint/no-explicit-anydirective comments. - Unused
debugLog/DEBUG_ENABLEDimport frommain.ts. - Non-existent
styles.cssfrom CI release assets.
Fixed
this: voidlinter warnings: Original methods captured fromworkspaceare now
bound via.bind(workspace)at capture time, preventingthis-scoping errors when
the method is called detached from its object.- Review linter compliance: Addressed all warnings reported by Obsidian's automated
plugin review — noanytypes, noconsole.login production builds, no directive
suppressions, nofunction()withoutthis: void.
[1.3.0][] — 2026-07-17
Added
- Settings Tab: Configurable prefix and suffix characters for autocompleted links (e.g.,
§Heading¶). Dual-API support: uses declarativegetSettingDefinitions()on Obsidian 1.13.0+, falls back todisplay()on older versions. - Wikilink Alias Auto-Injection: When Obsidian is using wikilinks (
[[), selecting a heading from autocomplete now automatically appends|Original Heading— producing[[#gfm-slug|Original Heading]]instead of bare[[#gfm-slug]]. - Link Affixes: User-configurable prefix/suffix applied to heading aliases during autocomplete.
isGfmSlug()shared guard predicate ingfm-slugify.ts.transformSuggestion()pure pipeline extracting heading mutation logic fromselectSuggestiongod-function.decodeGfmSlug()andresolveTargetFile()shared resolution helpers.injectVirtualBlock()shared utility with cleanup callback andVIRTUAL_BLOCK_CLEANUP_MSconstant.normalizeSlug()insrc/link-parse.ts.
Changed
patch-workspace.tssplit by SRP intopatch-link-click.ts(applyClickPatch, async) andpatch-link-hover.ts(applyHoverPatch, sync).buildDocumentIndex()replaced O(n²) nested loop with 2-pass O(n) stack-based algorithm.link-target.tsrenamed totypes.ts— all 5 imports updated.- Variable renames for readability:
data→hoverEventPayload,value→suggestionValue,mutated→didModifySubpath. resolveGfmTarget()andresolveGfmTargetSync()unified to use shareddecodeGfmSlug()+resolveTargetFile()helpers, reducing each from ~90 to ~15 lines.- Hover handler no longer uses
require("./document-index")inlining — delegates toresolveGfmTargetSync(). - Settings tab uses declarative
getSettingDefinitions()API (Obsidian 1.13.0+) withdisplay()fallback. minAppVersionset to1.12.7for dual settings API support.DEBUG_ENABLED = trueon dev branch — set tofalsefor production builds.
Fixed
- Inverted guard bug:
isGfmSlug()condition was inverted inresolve-target.ts, causing valid GFM slugs to pass through unresolved. - Settings tab broken on Obsidian <1.13.0: Declarative-only API caused empty settings pane. Fixed with dual-API support.
- Affixes applied to wrong field: Affixes were appended to
suggestionValue.subpath(the slug) instead ofsuggestionValue.heading(the alias). - Wikilink alias not injected: Multiple iterations required; finally resolved via
plugin.app.workspace.activeEditor?.editorpost-insertion modification.
[1.2.0][] — 2026-07-13
Added
- Document Index Architecture: Lightweight background
Map<gfmSlug, AnchorTarget>per file, separate from Obsidian's cache. Enables O(1) slug lookups with zero risk of cache contamination. - Virtual Block Injection: Temporarily injects
#^gfm-click-{slug}blocks intocache.blocksto leverage Obsidian's native block-level scrolling and.is-flashinghighlight — works correctly for duplicate headings. - Autocomplete GFM Slug Output (
EditorSuggest.selectSuggestion): Selecting a heading from the[[dropdown now outputs the GFM slug (e.g.,[My Heading](file.md#my-heading)) while preserving the original heading text as the alias. - Duplicate Heading Resolution in Autocomplete: Advanced dropdown occurrence-index matching correctly resolves which Nth duplicate was selected, producing the correct collision suffix (
-1,-2, etc.). - HTML Anchor Scanning (
scanHtmlAnchors): Parses<a id="...">and<a name="...">tags for target identification (click navigation in Reading mode). - Structured Debug Logging (
src/debug.ts): 15 event types withDEBUG_ENABLEDtoggle for development instrumentation. - Unit Tests (Vitest, 17 tests):
gfmSlugify(basic, Unicode, edge cases),buildDocumentIndex(collision suffixes, endLine),resolveGfmTarget(guard logic).
Changed
- Architectural Shift: Abandoned the speculative
Heading#Headingsubpath navigation. Replaced with Document Index + Virtual Block Injection across all three monkeypatches (openLinkText,trigger('hover-link'),EditorSuggest.selectSuggestion). - Same-file navigation: Bypassed native resolution for same-file links to eliminate jump-to-top flicker.
- HTML in heading aliases: Autocomplete now strips HTML tags from heading text (e.g.,
## Title <a id="x"></a>→ aliasTitle).
Fixed
- Hover Preview on duplicate headings: Corrected
buildDocumentIndex(cache.headings)→buildDocumentIndex(cache)— the former produced an empty index, causing all hover previews to fail. - Alias loss in autocomplete: Stopped mutating
value.heading— onlyvalue.subpathis rewritten to the GFM slug. .is-flashingon duplicates: Native block navigation handles section highlighting correctly, no longer highlights wrong heading.
Known Limitations
- HTML anchor click navigation works only in Reading mode (Live Preview / Source mode under investigation — see Bug 10).
- HTML anchor hover preview is not yet supported (hover interceptor only handles heading-type targets — see Bug 6).
- GFM collision suffix uses last-write-wins (
Map.set()overwrites). First-occurrence priority deferred to v2 (see Bug 8). DEBUG_ENABLED = trueon dev branch — set tofalsefor production builds.
[1.1.0][] — 2026-07-03
Changed
- Architectural Overhaul: Completely abandoned the fragile CodeMirror 6
ViewPluginand DOMMutationObserverarchitecture. The plugin now globally monkeypatches Obsidian's coreWorkspacerouter (workspace.openLinkTextandworkspace.trigger('hover-link')). - Fixed
Ctrl + Hover(Page Preview): Because the plugin now patches the event routing layer rather than aggressively swallowing DOMmouseoverevents, Obsidian's native modifier-key detection and delays work perfectly. - Fixed Cross-File Links: Addressed a critical bug where links pointing to other files (e.g.,
[Link](other-file.md#gfm-slug)) were ignored. The new router patch correctly separates the file path from the hash before attempting resolution.