# Hashtag Links

This page explains how `MDViewer` turns `#tag` in the text into links, along with the matching rules and limits.

## Enabling

```javascript
new MDViewer({
    id: "viewer",
    sync: { editor: editor },
    hashtag: { path: "/search?tag=", target: "_blank" }
});
```

| Condition | Result |
|---|---|
| `hashtag.path` is a non-empty string | Conversion enabled |
| `hashtag.path` empty or unset | No conversion; `#tag` is output as-is |
| Using `MDParser` | No conversion: `MDParser` passes `null` as the path |

## Output

```markdown
Today's topics #JavaScript and #前端
```

```html
Today's topics <a class="tag" href="/search?tag=JavaScript" target="_blank">JavaScript</a> and <a class="tag" href="/search?tag=前端" target="_blank">前端</a>
```

| Item | Rule |
|---|---|
| `href` | `hashtag.path` concatenated with the tag text, without URL encoding |
| Link text | Without the `#` |
| `class` | `tag`, styled by `NanoMD.css` |
| `target` | `_blank` when `hashtag.target` is `"_blank"`, otherwise `_self` |

## Matching Rules

| Rule | Detail |
|---|---|
| Prefix | Half-width `#` or full-width `＃` |
| Preceded by | A whitespace character (newline included), so a `#` glued to preceding text (`a#b`) is not converted; a `#` at the start of a line counts as preceded by a newline |
| Tag characters | CJK unified ideographs, hiragana/katakana, Hangul syllables, ASCII letters, digits and underscore |
| End | Stops at the first character outside that set (punctuation, space, `-`) |
| Escape | `\#tag` is not converted and outputs the literal `#tag` |

`setHashtag` runs last in the pipeline; code blocks and inline code are already placeholders by then, so a `#` inside them is untouched. A `#` followed by a space is heading syntax and is handled earlier by `setHeading`.
