Add link support for badges using >> syntax

Badges can now include clickable links with `[!!type:text>>link]` syntax.
Supports both wikilinks (`[[Note]]`) and external URLs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@gapmiss 2026-05-29 17:47:22 -05:00
parent f672e3492e
commit 02c82a339e
3 changed files with 73 additions and 3 deletions

View file

@ -8,6 +8,7 @@ A light-weight plugin for displaying inline "badges" in [Obsidian.md](https://gi
- [Github styled badges](#Github)
- [Plain-text](#Plain-text)
- [custom](#custom)
- [Links](#links)
- [Usage in tables](#usage-in-tables)
- [Installation](#Installation)
- [CSS styles](#CSS)
@ -190,6 +191,32 @@ For example, `[!!success]` displays as "Success" with a checkmark icon. This wor
![](assets/Badges-demo-Obsidian-v1.3.7-20230709171541.png)
![](assets/Badges-demo-Obsidian-v1.3.7-20230709171534.png)
### Links
Badges can be made clickable by adding a link using the `>>` syntax.
###### syntax
```markdown
`[!!KEY:VAL>>LINK]`
```
| syntax | details |
| ------ | ------- |
| `>>` | link delimiter |
| `LINK` | wikilink `[[Note]]` or external URL `https://...` |
###### examples
```markdown
`[!!info:Documentation>>https://obsidian.md]`
`[!!note:See also>>[[My Note]]]`
`[!!tip:Jump to section>>[[My Note#Heading]]]`
```
> [!NOTE]
> Links work with all badge types including custom badges.
### Usage in tables
When using badges inside Markdown tables, the `|` pipe character conflicts with the table cell separator. To work around this, use escaped pipes `\|` instead of `|` in your badge syntax.

View file

@ -3,7 +3,7 @@ import { RangeSetBuilder } from "@codemirror/state"
import { ViewPlugin, WidgetType, EditorView, ViewUpdate, Decoration, DecorationSet } from '@codemirror/view'
import { BADGE_TYPES } from './constants';
const REGEXP = /(`\[!!([^\]]*)\]`)/gm;
const REGEXP = /(`\[!!(.*?)\]`)/gm;
const TAGS = 'code'
export default class BadgesPlugin extends Plugin {
@ -131,7 +131,7 @@ const viewPlugin = ViewPlugin.fromClass(class {
decorations: (v) => v.decorations,
})
function buildBadge(text: string): HTMLSpanElement {
function buildBadge(text: string): HTMLSpanElement | HTMLAnchorElement {
const newEl = createSpan();
const iconEl = createSpan();
const titleEl = createSpan();
@ -139,11 +139,25 @@ function buildBadge(text: string): HTMLSpanElement {
let attrType = "";
const part = text.substring(2);
// Support escaped pipes (\|) for use inside Markdown tables
const content = part.substring(part.length-1,1).trim().replace(/\\\|/g, '|');
let content = part.substring(part.length-1,1).trim().replace(/\\\|/g, '|');
if (!content.length) {
newEl.setText("Badges syntax error");
return newEl;
}
// Parse optional link syntax: >>[[wikilink]] or >>https://...
let linkTarget: string | null = null;
let isWikilink = false;
const linkMatch = content.match(/>>(\[\[.+?\]\]|.+)$/);
if (linkMatch) {
const rawLink = linkMatch[1].trim();
if (rawLink.startsWith('[[') && rawLink.endsWith(']]')) {
linkTarget = rawLink.slice(2, -2);
isWikilink = true;
} else {
linkTarget = rawLink;
}
content = content.slice(0, content.lastIndexOf('>>')).trim();
}
const parts = content.split(':');
let badgeType = parts[0].trim();
let badgeContent: string;
@ -225,5 +239,24 @@ function buildBadge(text: string): HTMLSpanElement {
}
newEl.appendChild(titleEl);
}
// Wrap in anchor if link was specified
if (linkTarget) {
const anchor = createEl('a');
if (isWikilink) {
anchor.addClass('internal-link');
anchor.setAttr('data-href', linkTarget);
anchor.setAttr('href', linkTarget);
anchor.setAttr('data-tooltip-position', 'top');
} else {
anchor.addClass('external-link');
anchor.setAttr('href', linkTarget);
anchor.setAttr('target', '_blank');
anchor.setAttr('rel', 'noopener');
anchor.setAttr('aria-label', linkTarget);
anchor.setAttr('data-tooltip-position', 'top');
}
anchor.appendChild(newEl);
return anchor;
}
return newEl;
}

View file

@ -416,3 +416,13 @@ body {
color: rgba(var(--badge-color), 1);
background-color: rgba(var(--badge-color),.123);
}
a:has(> .inline-badge) {
text-decoration: none;
}
a:has(> .inline-badge),
a:has(> .inline-badge) .inline-badge {
cursor: pointer;
}
a:has(> .inline-badge):hover .inline-badge {
filter: brightness(1.1);
}