# Custom components

Replace links, images or code-block presentation while retaining Markdown parsing.

Suppose every Markdown link should have an arrow, while body text, lists and headings keep their default appearance. Supply a Vue component for `components.a`; the source and Markdown parser stay the same.

## 1. Prepare a link component

The example's `reading/link.vue` receives a validated `href`, displays its default slot and adds an arrow. Keeping an ordinary `<a>` retains the browser's link and keyboard behavior.

## 2. Replace link presentation

Import the link component beside the reader and supply it as `components.a`:

```vue
<script setup lang="ts">
import { QuireMarkdown } from '@quirekit/incremark/vue'
import ReadingLink from './link.vue'
const components = { a: ReadingLink }
</script>
<template>
  <QuireMarkdown content="[Documentation](https://example.com/docs)" :components="components" />
</template>
```

`a` names the semantic tag produced for Markdown links. Tags without a replacement keep their default output. In the example, body text remains unchanged and the link gains an arrow. `reading/components.vue` assembles the reader; `reading/link.vue` defines the link itself.

### reading/components.vue

```vue
<script setup lang="ts">
import { computed } from "vue";
import { QuireMarkdown } from "@quirekit/incremark/vue";
import "@quirekit/incremark/styles.css";
import ReadingLink from "./link.vue";
import type { ExampleLocale } from "../shared/types";

const props = withDefaults(defineProps<{ /** Tutorial language. */ locale?: ExampleLocale }>(), { locale: "zh-CN" });
const components = { a: ReadingLink };
const source = computed(() => props.locale === "zh-CN"
  ? "普通正文保持默认样式，[文档链接](https://example.com/docs)由自己的组件显示。"
  : "Body text keeps its default appearance; the [documentation link](https://example.com/docs) uses a custom component.");
</script>
<template><div class="p-qk-surface"><QuireMarkdown :content="source" :components="components" :locale="locale" /></div></template>

```

### reading/link.vue

```vue
<script setup lang="ts">
import type { MarkdownNodeInfo } from "@quirekit/incremark/vue";
defineProps<{
  /** Validated link destination, omitted when HTML policy rejects it. */ href?: string;
  /** Source metadata is explicitly consumed rather than forwarded to the DOM. */ node?: MarkdownNodeInfo;
}>();
</script>
<template><a :href="href" class="qk-prose-node" data-custom-link><slot /> ↗</a></template>

```

### shared/types.ts

```ts
/** Example host language; independent of the documentation router. */
export type ExampleLocale = "zh-CN" | "en";

```

## Data received by a component

| Replacement | Data supplied |
| --- | --- |
| `a` | Validated `href` and a slot containing link text |
| `img` | Validated image destination and other semantic attributes |
| `pre` | Exact `code` and `language`, suitable for a code viewer |
| `h2`, `table` and others | Corresponding semantic attributes and default children |

Explicitly declare `node?: MarkdownNodeInfo` if you need source positions. It contains `type/from/to` with UTF-16 offsets in the current normalized text. Do not forward this object as a DOM attribute.

Changing components, locale, HTML policy or transport status does not reparse source.
Component maps and `renderNode` callbacks are trusted application code and own any additional
behavior. They should not execute expressions supplied by Markdown.
