const PLACEHOLDER_RE = /\{\{(\w+)\}\}/g;
export function resolveTitle(template, variables) {
    return template.replace(PLACEHOLDER_RE, (_, key) => {
        return variables[key] ?? '';
    });
}
// ---------------------------------------------------------------------------
// Site-wide title template (percent-token syntax).
//
// The Settings → SEO "Meta Defaults" title template uses `%token%` syntax so
// it reads naturally to non-developers (`%page% — %site%`). This is distinct
// from the `{{mustache}}` helper above, which powers per-collection templates.
// ---------------------------------------------------------------------------
/** Tokens supported by the site-wide title template. */
export const SITE_TITLE_TOKENS = [
    'page',
    'site',
    'type',
    'separator',
    'author',
    'date',
    'category',
    'tag',
];
/** Fallback used when no template is configured or the configured one is blank. */
export const DEFAULT_SITE_TITLE_TEMPLATE = '%page% — %site%';
const SITE_TOKEN_RE = /%(\w+)%/g;
/**
 * Validate a site-wide title template. An empty/whitespace template is treated
 * as valid (the renderer falls back to {@link DEFAULT_SITE_TITLE_TEMPLATE}).
 * Unknown `%tokens%` and a template with no token *and* no literal text are
 * rejected.
 */
export function validateTitleTemplate(template) {
    const errors = [];
    const unknownTokens = [];
    if (!template || template.trim() === '') {
        return { valid: true, unknownTokens, errors };
    }
    const known = new Set(SITE_TITLE_TOKENS);
    const seen = [];
    for (const match of template.matchAll(SITE_TOKEN_RE)) {
        const token = match[1];
        seen.push(token);
        if (!known.has(token) && !unknownTokens.includes(token)) {
            unknownTokens.push(token);
        }
    }
    if (unknownTokens.length > 0) {
        errors.push(`Unsupported token${unknownTokens.length > 1 ? 's' : ''}: ${unknownTokens
            .map((t) => `%${t}%`)
            .join(', ')}`);
    }
    // Must contain at least one known token OR some literal (non-token) text.
    const literal = template.replace(SITE_TOKEN_RE, '').trim();
    const hasKnownToken = seen.some((t) => known.has(t));
    if (!hasKnownToken && literal === '') {
        errors.push('Template must include at least one token or some literal text.');
    }
    return { valid: errors.length === 0, unknownTokens, errors };
}
/**
 * Apply a site-wide title template. Unknown / empty tokens collapse cleanly so
 * the result never contains dangling separators or double spaces. Falls back to
 * {@link DEFAULT_SITE_TITLE_TEMPLATE} when the template is blank, and to the
 * page title (then site name) if the rendered result is empty.
 */
export function applySiteTitleTemplate(template, vars) {
    const tpl = template && template.trim() !== '' ? template : DEFAULT_SITE_TITLE_TEMPLATE;
    const values = {
        page: vars.page,
        site: vars.site,
        type: vars.type,
        separator: vars.separator ?? '|',
        author: vars.author,
        date: vars.date,
        category: vars.category,
        tag: vars.tag,
    };
    const replaced = tpl.replace(SITE_TOKEN_RE, (_, key) => values[key] ?? '');
    // Tidy up: collapse whitespace, then strip leading/trailing separator-only
    // fragments left behind by empty tokens (e.g. "Page — " → "Page").
    const cleaned = replaced
        .replace(/\s+/g, ' ')
        .replace(/^[\s\-–—|·•]+/, '')
        .replace(/[\s\-–—|·•]+$/, '')
        .trim();
    return cleaned || vars.page?.trim() || vars.site?.trim() || '';
}
export function getDocumentTitle(config, options) {
    if (options.metaTitle)
        return options.metaTitle;
    const sep = config.separator ?? ' | ';
    const template = (options.collection && config.collectionTemplates?.[options.collection]) ||
        config.defaultTemplate ||
        '{{title}}{{sep}}{{siteName}}';
    const now = new Date();
    const variables = {
        title: options.title,
        siteName: config.siteName,
        sep,
        collection: options.collection,
        category: options.category,
        tag: options.tag,
        page: options.page != null ? String(options.page) : undefined,
        year: String(now.getFullYear()),
        month: String(now.getMonth() + 1).padStart(2, '0'),
    };
    return resolveTitle(template, variables);
}
//# sourceMappingURL=title-templates.js.map