import type { z } from 'astro/zod' ;
import config from 'virtual:starlight/user-config' ;
import { version } from 'starlight-ion-theme/package.json' ;
import type { HeadConfigSchema } from 'starlight-ion-theme/schemas/head.js' ;
import { fileWithBase } from 'starlight-ion-theme/utils/base.js' ;
import { createHead } from 'starlight-ion-theme/utils/head.js' ;
import { localizedUrl } from 'starlight-ion-theme/utils/localizedUrl.js' ;
import type { Props } from '@astrojs/starlight/props' ;
const { entry , lang , siteTitle } = Astro.props;
const canonical = Astro.site ? new URL (Astro.url.pathname, Astro.site) : undefined ;
const description = data.description || config.description;
// Remove all icon brackets, their content and any whitespaces surrounding them from the title string
const titleWithoutIcons = data.title. replaceAll ( / \s * \[ . + \] \s * / gm , '' );
const headDefaults : z . input < ReturnType < typeof HeadConfigSchema>> = [
{ tag: 'meta' , attrs: { charset: 'utf-8' } },
attrs: { name: 'viewport' , content: 'width=device-width, initial-scale=1' },
{ tag: 'title' , content: `${ titleWithoutIcons } ${ config . titleDelimiter } ${ siteTitle }` },
{ tag: 'link' , attrs: { rel: 'canonical' , href: canonical?.href } },
{ tag: 'meta' , attrs: { name: 'generator' , content: Astro.generator } },
attrs: { name: 'generator' , content: `Starlight (Ion) v${ version }` },
href: fileWithBase (config.favicon.href),
type: config.favicon.type,
{ tag: 'meta' , attrs: { property: 'og:title' , content: titleWithoutIcons } },
{ tag: 'meta' , attrs: { property: 'og:type' , content: 'article' } },
{ tag: 'meta' , attrs: { property: 'og:url' , content: canonical?.href } },
{ tag: 'meta' , attrs: { property: 'og:locale' , content: lang } },
{ tag: 'meta' , attrs: { property: 'og:description' , content: description } },
{ tag: 'meta' , attrs: { property: 'og:site_name' , content: siteTitle } },
attrs: { name: 'twitter:card' , content: 'summary_large_image' },
attrs: { name: 'description' , content: description },
// Link to language alternates.
if (canonical && config.isMultilingual) {
for ( const locale in config.locales) {
const localeOpts = config.locales[locale];
if ( ! localeOpts) continue ;
hreflang: localeOpts.lang,
href: localizedUrl (canonical, locale).href,
// Link to sitemap, but only when `site` is set.
href: fileWithBase ( '/sitemap-index.xml' ),
// Link to Twitter account if set in Starlight config.
if (config.social?.twitter) {
content: new URL (config.social.twitter.url).pathname,
const head = createHead (headDefaults, config.head, data.head);
{head. map (({ tag : Tag , attrs , content }) => < Tag { ... attrs} set : html = {content} />)}