---
title: "Headings"
description: "Plugin for extracting the page title and description from document content."
canonical_url: "https://comark.dev/plugins/built-in/headings"
---
# Headings

> Plugin for extracting the page title and description from document content.

The `comark/plugins/headings` plugin extracts the page title and description from the top of a document and stores them in `tree.meta.title` and `tree.meta.description`. By default it reads the first `h1` as the title and the first `p` as the description, keeping both nodes in the tree. Set `remove: true` to strip them so they are not rendered twice.

## Usage

```typescript
import { parseMarkdown } from 'comark'
import headings from 'comark/plugins/headings'

const result = await parseMarkdown(content, {
  plugins: [headings()]
})

console.log(result.meta.title)       // "My Page Title"
console.log(result.meta.description) // "First paragraph text."
```

---

## API

### `headings(options?)`

Returns a `ComarkPlugin` that extracts title and description metadata from top-level nodes.

**Parameters:**

- `options?` - Optional configuration, see [Options](#options)

**Returns:** `ComarkPlugin`

Results are stored at `tree.meta.title` and `tree.meta.description`. Neither field is set when the corresponding node is absent or does not match the configured tag.

<tip>
The description check always looks at the node **immediately after** the title: a non-matching node between them will prevent description extraction.
</tip>

---

## Options

| Option                                      | Type              | Default | Description                                                           |
| ------------------------------------------- | ----------------- | ------- | --------------------------------------------------------------------- |
| [`titleTag`](#options-titletag)             | `string \| false` | `'h1'`  | Element tag to extract as the page title, or `false` to disable       |
| [`descriptionTag`](#options-descriptiontag) | `string \| false` | `'p'`   | Element tag to extract as the page description, or `false` to disable |
| [`remove`](#options-remove)                 | `boolean`         | `false` | Remove extracted nodes from the tree after extraction                 |

### `titleTag`

The element tag to read the title from. Set to `false` to disable title extraction entirely.

```typescript
headings({ titleTag: 'h2' })

// Disable title extraction
headings({ titleTag: false })
```

**Default:** `'h1'`

### `descriptionTag`

The element tag to read the description from. Use `'blockquote'` if you prefer a block quote as the lead-in description. Set to `false` to disable description extraction entirely.

```typescript
headings({ descriptionTag: 'blockquote' })

// Disable description extraction
headings({ descriptionTag: false })
```

**Default:** `'p'`

### `remove`

Whether to remove the extracted nodes from the tree after extraction. Set to `true` when you don't want the title and description rendered, for example, when a layout already displays them separately.

```typescript
headings({ remove: true })
```

**Default:** `false`

---

## Examples

### Default extraction

<code-group>
```markdown [content.md]
# My Page Title

This is the opening paragraph used as the description.

## Section One

More content here.
```


```typescript [parse.ts]
import { parseMarkdown } from 'comark'
import headings from 'comark/plugins/headings'

const result = await parseMarkdown(content, {
  plugins: [headings()]
})

console.log(result.meta.title)       // "My Page Title"
console.log(result.meta.description) // "This is the opening paragraph used as the description."
// result.nodes still contains the h1 and the first p (use remove: true to strip them)
```
</code-group>

### Blockquote as description

```typescript
const result = await parseMarkdown(content, {
  plugins: [headings({ descriptionTag: 'blockquote' })]
})

console.log(result.meta.description) // "A highlighted lead-in sentence shown as the description."
```

### Combining with the TOC plugin

```typescript
import { parseMarkdown } from 'comark'
import headings from 'comark/plugins/headings'
import toc from 'comark/plugins/toc'

const result = await parseMarkdown(content, {
  plugins: [headings(), toc()]
})

console.log(result.meta.title)       // page title
console.log(result.meta.description) // page description
console.log(result.meta.toc)         // table of contents
```

---

- [Parse API](https://comark.dev/reference/parse)
- [Document Model](https://comark.dev/getting-started/document-model)


## Sitemap

See the full [sitemap](https://comark.dev/sitemap.md) for all pages.
