A Remark plugin for Astro that automatically adds an <h1>
element to markdown using a variable from the frontmatter or vice versa, add the text of <h1>
as a variable to frontmatter
Note: This plugin requires Astro version 2.0.0-beta.0 or above
- Automatically add
<h1>
heading using frontmatter variable - Copy the text of
<h1>
to the frontmatter as a variable - Create dynamic default titles using the documents
mdast
andvfile
- Option to force only one
<h1>
per document by removing any extras - Option to shift extra
<h1>
headings to a lower depth - Option to override frontmatter variables defined in file
Use this plugin when you have a CMS that enforces a variable in the frontmatter like title
but you forget to add a # Heading
in the markdown body. This can also be useful when using the getHeadings
function from Astro because it can fail if there is no <h1>
heading
There are also other useful options like:
- Create dyanmic default titles using the document
mdast
andvfile
if document has nethier a# Heading
or frontmatter variable - Add the text of the documents
<h1>
to the frontmatter as a variable - forcing only one
<h1>
to a document by removing extras or shifting their depth downwards
Setup Config:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import { autoTitle } from 'astro-auto-title';
export default defineConfig({
markdown: {
remarkPlugins: [
[autoTitle, {
frontmatterToH1: 'title',
h1ToFrontmatter: 'title',
}]
]
}
});
These 3 Markdown Files:
// 1
---
title: H1 Heading
---
This is a description
// 2
# H1 Heading
This is a description
// 3
---
title: I dont override existing h1
---
# H1 Heading
This is a description
Are rendered into this HTML:
<h1>H1 Heading</h1>
<p>This is a description</p>
{
frontmatterToH1: 'title',
h1ToFrontmatter: 'title',
defaultText: (mdast, vfile) => (
// Tries to return a string similar to Astro.url.pathname
// assumes your .md is located in src/pages
vfile.history
.pop()
?.replace(vfile.cwd, '')
.replace(/(\/\/)|(\\)+/g, '/')
.replace('/src/pages','')
.replace('/index.md', '')
.replace('.md', '')
),
override: false,
trimExtraH1: true,
shiftExtraH1: false
}
Default: title
If no <h1>
is found in document inject one with the text of this frontmatter variable
If false
is passed it uses the text defined in default
Example:
{
frontmatterToH1: 'title'
}
---
title: H1 Heading
---
This is a description
<h1>H1 Heading</h1>
<p>This is a description</p>
Default: title
This variable is added to frontmatter containing the first <h1>
element's text
If false
is passed no variable is added to frontmatter
Example:
{
h1ToFrontmatter: 'title'
}
# Heading defined in file
This is a description
frontmatter = {
title: 'Heading defined in file'
}
Default
(mdast, vfile) => (
// Tries to return a string similar to Astro.url.pathname
// assumes your .md is located in src/pages
vfile.history
.pop()
?.replace(vfile.cwd, '')
.replace(/(\/\/)|(\\)+/g, '/')
.replace('/src/pages','')
.replace('/index.md', '')
.replace('.md', '')
)
Can be a static string or a function that calculates a default string using the documents mdast
tree and vfile
Pass false
to disable adding <h1>
by default (will still create <h1>
from frontmatter variable if available)
Default: false
Option to override frontmatter variable if one is already defined in file
Default: true
Enforces only one <h1>
per document, keeps the first <h1>
and removes all extras
Example:
# First h1
# Second h1
# Third h1
<h1>First h1</h1>
Default: false
Note:
trimExtraH1
must be set tofalse
to use
Enforces only one <h1>
per document by keeping the first <h1>
and shifting all extra <h1>
elements downwards to defined depth
Passing true
shifts extra <h1>
elements to <h2>
Passing false
stops shifting from happening
Example:
{
trimExtraH1: false,
shiftExtraH1: 3
}
# First h1
# Second h1
# Third h1
<h1>First h1</h1>
<h3>Second h1</h3>
<h3>Third h1</h3>