1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
x20 x20 x3 x5 x5 x5 x5 x5 x5 x5 x5 x5 x5 x5 x5 x5 x5 x5 x3 x3 |
I I I |
// Imports
import type { MarkdownIt } from "../types.ts"
import { slugify as slug } from "@std/text/unstable-slugify"
/** Wiki links options. */
export type WikilinksOptions = {
/** Indicate which possible slugs are possible for a given reference. */
slugify?: (name: string) => string[]
/** Indicate how to resolve a link to a URL. */
resolve?: (link: string) => string
/** List of existing permalinks (any link not present in the list will possess the `new` class). */
existing?: string[]
}
/**
* Add support for wiki links.
*
* Use the `existing` option to provide a list of existing permalinks.
* Any link not present in the list will possess the `new` class.
*
* Use the `slugify` option to indicate which possible slugs are possible for a given reference.
* The first slug present in the list of existing permalinks is used, defaulting to the first generated slug.
*
* Use the `resolve` option to indicate how to resolve a link to a URL.
*
* All links generated by this plugin will have the `wikilink` class.
*
* ```md
* [[foo]]
* ```
* ```html
* <a class="wikilink" href="/pages/foo">foo</a>
* ```
*/
export default function wikilinks(engine: MarkdownIt, { slugify = (name) => [slug(name)], resolve = (link) => `/pages/${link}`, existing }: WikilinksOptions = {}): void {
engine.inline.ruler.before("link", "wikilinks", (state, silent) => {
if (state.src.slice(state.pos, state.pos + 2) !== "[[")
return false
const match = /^\[\[([^\]|\n]+)(?:\|([^\]\n]+))?\]\]/.exec(state.src.slice(state.pos, state.posMax))
if (!match)
return false
if (!silent) {
const name = match[1].trim()
const label = match[2]?.trim() || name
const slugs = slugify(name)
const target = slugs.find((slugged) => existing?.includes(slugged)) ?? slugs[0] ?? name
const created = Array.isArray(existing) && (!existing.includes(target))
const open = state.push("link_open", "a", 1)
open.attrSet("class", `wikilink${created ? " new" : ""}`)
open.attrSet("href", resolve(target))
state.push("text", "", 0).content = label
state.push("link_close", "a", -1)
}
state.pos += match[0].length
return true
})
}
|