/**
* Structured Data Projector
*
* Takes the raw `StructuredDataResult` extracted from a page (via
* `structured-data-extractor.ts`) and projects it into a flat,
* source-agnostic "common fields" view that downstream consumers
* can read uniformly without caring which markup format the source
* site happened to use.
*
* ## Why this exists
*
* `extractStructuredData()` returns a rich tree with separate
* branches for JSON-LD, microdata, OpenGraph, Twitter Card, Dublin
* Core, and RDFa. That's the right shape for callers who care
* which source provided the data, but it's the wrong shape for
* "I just want the page's title and author."
*
* Real pages tend to publish overlapping subsets of the same
* fields across multiple formats: a Wikisource page has both
* JSON-LD `Article.headline` and OpenGraph `og:title`; a news
* article has Twitter Card title, OpenGraph title, microdata
* NewsArticle headline, AND a regular `
` tag — all saying
* the same thing. The projector picks the most-preferred source
* per field and returns a single value, with provenance attached.
*
* ## Provenance
*
* Every projected field carries a `source` string (e.g.
* "jsonld:Article.headline", "opengraph:title", "microdata:headline")
* so callers can audit where each value came from. Useful for
* debugging unexpected projections and for AI-citation
* verification ("the page's title came from JSON-LD, which is
* publisher-controlled metadata").
*
* ## Field priority
*
* For each common field, the projector walks a priority list of
* sources and returns the first one that resolves. The lists are
* tuned to favor publisher-curated structured metadata (JSON-LD,
* microdata) over social-media tags (Twitter Card, OpenGraph),
* which in turn beat the bare HTML ``. JSON-LD is
* preferred because it's the most widely-adopted machine-readable
* format on modern sites and has the richest semantics.
*
* ## Limitations
*
* - Bag-of-fields, not full schema introspection. The projection
* targets a fixed set of common fields. Custom schemas (e.g.
* "give me back ProductData with these specific properties")
* are out of scope for this module — the raw `StructuredDataResult`
* is still surfaced separately so callers needing custom shapes
* can read it directly.
* - First-match wins. The projector doesn't try to merge or
* reconcile conflicting values across sources. For most fields
* on most sites this is fine; for the rare case where multiple
* sources disagree, the priority order is deterministic and
* the source is reported.
*/
import type { StructuredDataResult } from './structured-data-extractor.js';
/**
* The projected common fields. Every field is optional — pages
* vary widely in which structured data they publish.
*/
export interface ProjectedFields {
/** Page or document title. */
title?: string;
/**
* Document authors. ALWAYS an array, even for single-author
* documents (which produce a one-element array). This sidesteps
* the polymorphic-string-or-array footgun: callers can always
* write `result.author?.join(', ')` without runtime type checks.
*/
author?: string[];
/** ISO 8601 publication date string. */
datePublished?: string;
/** ISO 8601 last-modified date string. */
dateModified?: string;
/**
* Schema.org type chosen by the projector — the highest-priority
* type signal it found (typically from JSON-LD Article-like).
* Use `typeAlternates` for the full set of type signals across
* all sources, which is useful when sources disagree (e.g.
* JSON-LD says Person but microdata says Article).
*/
type?: string;
/**
* All distinct type signals found across sources. Empty array
* if no type was detected. The first entry matches `type`.
* Useful for citation verification where the Book-vs-Article
* distinction matters and disagreement between sources is itself
* signal worth surfacing.
*/
typeAlternates?: Array<{
type: string;
source: string;
}>;
/** Document description / summary. */
description?: string;
/** Primary image URL. */
image?: string;
/**
* Page language as a BCP47 code (e.g. "en", "en-US", "es",
* "ja-JP"). The projector normalizes Facebook's `og:locale`
* underscore convention (`en_US`) to BCP47 (`en-US`).
*/
language?: string;
/** Publisher name. */
publisher?: string;
/**
* Human-readable site name (e.g. "The New York Times").
* Sourced only from `og:site_name` — Twitter Card's `twitter:site`
* is a Twitter handle (@nytimes), not a display name, and is
* not used here.
*/
siteName?: string;
}
/**
* Provenance for each projected field — where the value came from.
* Keys mirror `ProjectedFields`. Only present when the corresponding
* field is set.
*/
export type ProjectedFieldSources = Partial>;
/**
* Result of projecting structured data into common fields.
*/
export interface ProjectedFieldsWithSources {
/** The projected values. */
values: ProjectedFields;
/** Provenance string per populated field. */
sources: ProjectedFieldSources;
}
/**
* Project a structured data result into common fields.
*
* Each field is resolved by walking a priority list of sources
* and returning the first one that has a value. The priority
* order is:
*
* 1. Schema.org Article-like JSON-LD (Article, NewsArticle,
* BlogPosting, ScholarlyArticle) — richest, most curated
* 2. Normalized `result.article` (already merged from JSON-LD
* and microdata by structured-data-extractor.ts)
* 3. OpenGraph
* 4. Twitter Card
* 5. Dublin Core
* 6. Raw meta tags (last resort)
*
* Title-specific override: if no Article-like JSON-LD exists, the
* raw page `` (passed in as `pageTitle`) is also considered
* AFTER OpenGraph but before Twitter Card. The page title is
* usually the worst source because it's optimized for browser
* tabs, but it's the only thing some sites have.
*/
export declare function projectFields(structured: StructuredDataResult, pageTitle?: string): ProjectedFieldsWithSources;
//# sourceMappingURL=structured-projector.d.ts.map