//! Render-mode-agnostic SEO layer for Rustelo.
//!
//! Produces `<head>` tags, JSON-LD blocks, sitemap.xml, and robots.txt from a
//! single [`PageSeo`] value. Consumed identically by both the Leptos-hydration
//! shell and the HTMX shell so SEO output stays in lock-step across renderers.
//!
//! The crate does **not** depend on Leptos or any renderer; it emits HTML
//! fragments as `String` that callers embed into their own `<head>` builder.

mod canonical;
mod head;
#[cfg(feature = "jsonld")]
mod jsonld;
mod og;
mod robots;
#[cfg(feature = "sitemap")]
mod sitemap;
mod tags;
mod twitter;
mod types;

pub use canonical::{join_url, render_canonical_tags};
pub use head::render_head_tags;
#[cfg(feature = "jsonld")]
pub use jsonld::{render_jsonld_blocks, JsonLdBlock, JsonLdSchema};
pub use og::render_og_tags;
pub use robots::render_robots_txt;
#[cfg(feature = "sitemap")]
pub use sitemap::{render_sitemap_xml, SitemapEntry, SitemapFrequency};
pub use tags::render_basic_tags;
pub use twitter::render_twitter_tags;
pub use types::*;

/// Error type for SEO operations.
#[derive(Debug, thiserror::Error)]
pub enum SeoError {
    #[error("invalid base URL: {0}")]
    InvalidBaseUrl(String),
    #[error("invalid path for canonical: {0}")]
    InvalidPath(String),
    #[error("JSON serialization failed: {0}")]
    JsonSerialization(#[from] serde_json::Error),
}

/// Convenience [`Result`] alias.
pub type Result<T> = std::result::Result<T, SeoError>;
