Skip to content

vitepress-alap

VitePress integration for Alap — use <alap-link> web components directly in your markdown documentation.

A Vite plugin that registers <alap-link> as a Vue custom element so the template compiler passes it through instead of dropping it.

Install

bash
npm install alap vitepress-alap

Setup

Copy alap.iife.js from the Alap dist into docs/public/. Create a config script in docs/public/docs-config.js. Add both to VitePress head, and add the plugin:

js
// docs/.vitepress/config.mjs
import { defineConfig } from 'vitepress';
import { alapPlugin } from 'vitepress-alap';

export default defineConfig({
  head: [
    ['script', { src: '/alap.iife.js' }],
    ['script', { src: '/docs-config.js' }],
  ],
  vite: {
    plugins: [alapPlugin()],
  },
});

The plugin registers <alap-link> as a custom element so Vue's template compiler passes it through. The IIFE and config scripts handle web component registration and config loading.

Config script example

js
// docs/public/docs-config.js
const alapConfig = {
  settings: { listType: 'ul', menuTimeout: 5000 },
  allLinks: {
    golden:   { label: 'Golden Gate Bridge', url: 'https://en.wikipedia.org/wiki/Golden_Gate_Bridge', tags: ['bridge', 'sf'] },
    brooklyn: { label: 'Brooklyn Bridge',    url: 'https://en.wikipedia.org/wiki/Brooklyn_Bridge',   tags: ['bridge', 'nyc'] },
  },
  macros: {
    favorites: { linkItems: 'golden, brooklyn' },
  },
};

Alap.registerConfig(alapConfig);
Alap.defineAlapLink();

Usage

Use <alap-link> anywhere in your markdown:

md
Check out these <alap-link query=".coffee">cafes</alap-link>.

The <alap-link query=".nyc + .bridge">NYC bridges</alap-link> are worth visiting.

Browse the <alap-link query="@favorites">favorites</alap-link>.

The links render as clickable text. On click, a menu appears with the matching items from your config.

Inline placement

Keep <alap-link> on the same line as surrounding text in markdown. If it starts a new line, the markdown parser treats it as a block element and breaks the paragraph.

Options

OptionTypeDefaultDescription
configstringPath to config file (auto-injected). Not yet working — use IIFE approach above.
configNamestringNamed config for multi-config setups
validatebooleantrueValidate config at build time (warns, doesn't fail)

Styling

Style the web component with ::part() selectors. Add a custom theme file for dark mode support:

css
/* docs/.vitepress/theme/custom.css */
alap-link {
  color: var(--vp-c-brand-1);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 3px;
  cursor: pointer;
}

.dark alap-link {
  color: #7eaef5;
}

.dark alap-link::part(menu) {
  background: #1e2a48;
  border: 1px solid #3a5070;
  border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}

.dark alap-link::part(link):hover {
  background: #2a3d68;
  color: #f5c842;
}

Register the theme:

js
// docs/.vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import './custom.css'

export default {
  extends: DefaultTheme,
}

See Styling for the full guide.

What the plugin does

  1. Registers <alap-link> as a custom element in Vue's template compiler — without this, Vue treats it as an unknown component and drops it
  2. Optionally injects the Alap setup script (bundled config path — planned for next beta)

That's it. The web component handles everything else — menus, keyboard nav, ARIA, positioning, dismiss behavior.

Known issues

  • Bundled config injection (alapPlugin({ config: '...' })) does not work yet in VitePress dev mode. Use the IIFE + public scripts approach for now. Fix planned for next beta.

See also