Markdown Link Resolver
RequirementsThis extension is designed for Astro-based documentation projects. It requires:
On activation, the extension checks for Astro project structure and displays appropriate status in the status bar. Features1. Go to Definition (Ctrl+Click / F12)Click on any link path in a Markdown or MDX file to jump directly to the resolved file. Works with all supported link types — inline links, reference-style definitions, JSX 2. Peek Definition (Alt+F12)Preview the linked file inline without leaving the current document. The peek window shows the full contents of the resolved file, letting you verify the target without switching tabs. 3. Hover Preview with Resolved File LinkHover over a link to see:
4. Keyboard ShortcutPress Cmd+Shift+. (macOS) or Ctrl+Shift+. (Windows/Linux) while your cursor is on a markdown link to jump to the resolved file. This works as a keyboard-only alternative to 5. Context MenuRight-click on a link in a markdown or MDX file to see a "Go to Linked File" entry in the context menu (under the navigation group, near "Go to Definition"). Clicking it navigates to the resolved file. 6. CodeLens AnnotationsClickable annotations appear above each link showing the resolved file path. If a link cannot be resolved, a warning annotation is displayed instead. Clicking the CodeLens opens the resolved file. 7. Real-time DiagnosticsWarning squiggles appear under links that cannot be resolved to any workspace file. These diagnostics update in real-time as you type (with a 200ms debounce) and are visible in the Problems panel. 8. Quick Fix SuggestionsWhen a link cannot be resolved, the extension provides intelligent quick fix suggestions based on URL similarity. Click the lightbulb icon (or press Similarity Matching (also used in autocomplete):
Typo-Tolerant Autocomplete: When typing a URL in a markdown link, MDX href, or YAML frontmatter, the extension first shows exact matches. If few or no exact matches are found, it automatically suggests similar permalinks based on the same similarity matching algorithm—helping you find the right URL even with typos. Configuration:
9. Command Palette CommandsAll commands are under the MDLR namespace:
10. Redirect File DiagnosticsWhen opening redirect JSON files (files containing redirect mappings with Source (FROM) Validation:A source URL is valid when it has no conflicts. Issues are flagged as:
Destination (MOVED) Validation:A destination is valid when it resolves to:
Issues are flagged as:
Quick Fix Suggestions:When a destination (MOVED) URL is invalid, the extension provides quick fix suggestions:
Features:
11. Status Bar IntegrationThe extension displays its current state in the VS Code status bar:
Click the status bar item to:
12. Show All ReferencesFrom the hover popup, click "Show all references" to see a Quick Pick list of all files that reference a specific permalink. This uses a pre-built reverse index for O(1) lookup performance. 13. Static Asset ResolutionThe extension resolves links to static assets (images, PDFs, etc.) stored in configured asset directories:
Example: Resolving Documentation LinksGiven a markdown file containing:
The extension will:
You can then Ctrl+Click the link to jump directly to that file! Link Types Supported
InstallationFrom Source
Then press F5 in VS Code to launch an Extension Development Host with the extension loaded. Using VSIX
Then install the VSIX:
Replace Multi-Project Support (Monorepo)The extension supports workspaces with multiple Astro projects, such as monorepos managed by pnpm, Lerna, Nx, or Turborepo. Automatic DetectionBy default, the extension auto-detects monorepo structures by checking for:
When a monorepo is detected, the extension scans Status Bar Project IndicatorIn monorepo mode, all detected projects are indexed simultaneously and links resolve across all of them automatically — there's no manual project switching. The status bar shows a project count (or the single project's name when only one is detected):
Hover the status bar item for a tooltip with per-project detection details. ConfigurationAll settings are under the Link Resolution Settings
|
| Setting | Detection Source |
|---|---|
contentRoots |
srcDir + /content from astro.config.* |
assetRoots |
publicDir from astro.config.* |
languages |
i18n config or folder structure |
defaultLanguage |
i18n config |
trailingSlash |
trailingSlash from astro.config.* |
Detected values are shown in the status bar tooltip when hovering over the MDLR status item. To modify these values, update your astro.config.* file.
Monorepo Configuration Examples
Example 1: Auto-Detection (Default)
For standard monorepos with projects in apps/ or packages/:
my-monorepo/
├── pnpm-workspace.yaml
├── apps/
│ ├── docs/ # Astro project
│ │ └── astro.config.mjs
│ └── landing-page/ # Astro project
│ └── astro.config.mjs
└── packages/
└── shared/
No configuration needed. The extension auto-detects both projects.
Example 2: Explicit Project Paths
For custom project locations or when auto-detection doesn't find all projects:
// .vscode/settings.json
{
"markdownLinkResolver.projectRoots": [
"site",
"documentation",
"internal/wiki"
]
}
Project Structure
markdown-link-resolver/
├── .husky/ # Git hooks (commitlint, pre-commit)
├── src/
│ ├── extension.ts # Extension entry point (activate/deactivate)
│ ├── types.ts # Shared TypeScript interfaces
│ ├── commands/
│ │ ├── consolidatedCommands.ts # Command Palette command implementations
│ │ ├── exportIndexesCommand.ts # Debug index export
│ │ ├── htmlReportGenerator.ts # HTML report generation
│ │ ├── permalinkReportCommand.ts # Permalink report command
│ │ └── redirectMapReport.ts # Redirect map report
│ ├── parsers/
│ │ └── linkParser.ts # Markdown/MDX link detection & parsing
│ ├── providers/
│ │ ├── codeLensProvider.ts # Inline CodeLens annotations
│ │ ├── completionProvider.ts # Permalink autocomplete
│ │ ├── definitionProvider.ts # Go to Definition (Ctrl+Click / F12)
│ │ ├── diagnosticsProvider.ts # Real-time warning diagnostics
│ │ ├── frontmatterPermalinkIndicatorProvider.ts # Frontmatter link counts
│ │ ├── hoverProvider.ts # Hover preview with file content
│ │ ├── hoverSchema.ts # Hover content schema generation
│ │ ├── statusBarProvider.ts # Status bar integration & state
│ │ ├── redirectFileDiagnosticsProvider.ts # Redirect JSON validation
│ │ ├── redirectFileCodeLensProvider.ts # CodeLens for redirects
│ │ ├── redirectFileHoverProvider.ts # Hover for redirects
│ │ ├── redirectQuickFixProvider.ts # Quick fix for redirects
│ │ ├── redirectCompletionProvider.ts # Autocomplete for redirects
│ │ ├── redirectDuplicateCodeActionProvider.ts # Duplicate testing
│ │ ├── redirectExternalDestinationDecorator.ts # Decorates external redirect destinations
│ │ ├── redirectMapVisualization.ts # Redirect visualization
│ │ └── quickFixProvider.ts # Quick fix for broken links (similarity matching)
│ ├── resolver/
│ │ ├── assetIndex.ts # Static asset resolution
│ │ ├── assetReferenceIndex.ts # Asset dependency tracking
│ │ ├── astroConfigResolver.ts # Astro config file parsing
│ │ ├── astroPageRouteParser.ts # Astro page route parsing
│ │ ├── compactTypes.ts # Memory-efficient storage types
│ │ ├── detectedConfigProvider.ts # Auto-detected configuration values
│ │ ├── externalLinkIndex.ts # Persistent URL → source-file mapping for external links
│ │ ├── fileIndex.ts # Cached workspace file index
│ │ ├── fileResolver.ts # Multi-strategy path resolution
│ │ ├── languagePatternDiscovery.ts # Language detection from paths
│ │ ├── permalinkIndex.ts # Permalink → file mapping
│ │ ├── permalinkReferenceIndex.ts # Reverse index for O(1) lookups
│ │ ├── persistence/
│ │ │ ├── fileManifest.ts # Per-file mtime/size manifest for snapshot diffing
│ │ │ ├── indexReconciler.ts # Reconciles indexes against a restored snapshot
│ │ │ ├── indexSnapshotStore.ts # Persists/loads index snapshots to disk
│ │ │ └── snapshotFileTable.ts # Shared file-string table for compact snapshot storage
│ │ ├── projectConfigDiscovery.ts # Framework auto-detection
│ │ ├── projectDiscoveryService.ts # Monorepo project discovery
│ │ ├── redirectIndex.ts # Redirect JSON file parsing
│ │ ├── redirectTestIndex.ts # Redirect test history storage
│ │ ├── routeIndex.ts # Page routes, categories, namespaces
│ │ ├── stringPool.ts # String interning for memory savings
│ │ ├── unifiedUrlIndex.ts # Canonical URL resolution (v1.0.2+)
│ │ └── urlVariantGenerator.ts # URL variant computation
│ ├── core/
│ │ ├── linkValidator.ts # Link validation logic
│ │ ├── diagnosticsCache.ts # Persistent diagnostics storage
│ │ └── revalidationCoordinator.ts # Batches/fans out background revalidation work
│ ├── features/
│ │ ├── externalProjectMapper.ts # External project URL tagging
│ │ └── externalUrlChecker.ts # External URL availability checking
│ ├── templates/
│ │ ├── baseReportTemplate.ts # Base report HTML template
│ │ ├── problemsReportTemplate.ts # Problems report template
│ │ ├── redirectMapReportTemplate.ts # Redirect map report template
│ │ ├── reportInteractions.ts # Shared client-side JS (sort/filter/expand) for HTML reports
│ │ └── reportTemplate.ts # Generic report template
│ └── utils/
│ ├── astroDetection.ts # Astro framework detection
│ ├── detectionDefaults.ts # Default setting values
│ ├── logger.ts # Logging utility
│ ├── pathUtils.ts # Path normalization utilities
│ ├── redirectUrlUtils.ts # Redirect URL utilities
│ ├── reportUtils.ts # HTML/Markdown report utilities and runReportCommand runner
│ ├── similarityMatcher.ts # Fuzzy URL matching algorithm
│ └── urlNormalizer.ts # URL normalization (v1.0.2+)
├── .editorconfig # Editor formatting rules
├── .gitignore # Git ignore patterns
├── .releaserc.json # Semantic release configuration
├── commitlint.config.cjs # Commit message validation
├── CONTRIBUTING.md # Contribution guidelines
├── CHANGELOG.md # Release notes
├── CODE_OF_CONDUCT.md # Community conduct guidelines
├── LICENSE # Proprietary, closed-source license
├── package.json # Extension manifest and dependencies
├── tsconfig.json # TypeScript configuration
└── README.md # This file
How It Works
On Activation:
- Detects if the workspace is an Astro project (via
astro.config.*orastroinpackage.json) - Shows appropriate status in the status bar (NoWorkspace, NotAstroProject, LimitedFunctionality, or FullActivation)
- Auto-detects project configuration: framework, languages, content directories, asset directories, trailing slash behavior
- Multi-Project Mode: Scans for monorepo indicators and discovers Astro projects in
apps/andpackages/directories - Builds a file index of all
.mdand.mdxfiles in the workspace
- Detects if the workspace is an Astro project (via
Index Architecture: Multiple specialized indexes maintain workspace state:
- FileIndex — workspace file paths
- PermalinkIndex — permalink → file mappings
- PermalinkReferenceIndex — reverse reference lookups
- AssetIndex — static asset paths
- AssetReferenceIndex — asset dependency tracking
- RedirectIndex — redirect chain mappings
- RouteIndex — page routes, categories, namespaces
- SourceIndex — source file → URL mapping
- ReferenceIndex — URL reference tracking
- UnifiedUrlIndex — canonical URL resolution (single source of truth)
- DiagnosticsCache — centralized issue tracking
- ProjectDiscoveryService — monorepo project discovery
Unified URL Index (v1.0.2+): The single source of truth for canonical URL resolution. Computes the exact URL Astro builds using
buildCanonicalUrl(), normalizes redirect URLs vianormalizeForLookup(), and provides O(1) URL-to-entry resolution.Permalink Index: Scans frontmatter for keys defined in
permalinkKeys(default:permalink). Maintains a permalink → file index with file system watchers. Duplicate permalinks are tracked and reported.Reference Index: Builds a reverse index mapping permalinks to all files that reference them, enabling O(1) lookups for "Show All References" functionality.
Asset Index: Scans auto-detected asset directories (
public/,static/,assets/) for static files. Enables resolution of image links and other asset references.Link Parsing: When you open or edit a markdown file, the link parser detects all link types using built-in regex patterns and produces
ParsedLinkobjects with precise range information.Resolution: For each link, the
FileResolverattempts permalink match, then redirect resolution, then asset resolution. UsesUnifiedUrlIndexfor canonical URL matching. Returns the best match with location information.Diagnostics: The
DiagnosticsProvidergenerates real-time warnings for broken links, displayed in the Problems panel.Multi-Project Behavior:
- All detected Astro projects are indexed together at activation — no per-file project switching
- Links resolve across all detected projects automatically
External Project Mapping: URLs matching configured patterns are tagged as external and can optionally skip HTTP validation.
Enable/Disable Toggle: Click the status bar item to pause/resume the extension. When paused, all indexes are cached for fast resume without rebuilding.
Development
# Install dependencies
npm install
# Compile TypeScript
npm run compile
# Watch for changes
npm run watch
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Build VSIX package
npm run package:vsix
# Launch Extension Development Host
# Press F5 in VS Code
License
Proprietary - all rights reserved. See LICENSE. The Software is provided "as is", without warranty of any kind.