# `SchemaOrg`
[🔗](https://github.com/mike-kostov/schema_org/blob/v0.2.0/lib/schema_org.ex#L1)

Strictly-typed builder for Schema.org JSON-LD.

Each Schema.org Class is a generated struct module under `SchemaOrg.*`
(e.g. `SchemaOrg.Product`, `SchemaOrg.Offer`). Build a graph with ordinary
struct literals — your editor auto-completes the valid fields and the compiler
rejects the rest — then serialise it with `to_json_ld/1`.

    %SchemaOrg.Product{
      name: "MacBook Pro",
      offers: %SchemaOrg.Offer{price: 1999.0}
    }
    |> SchemaOrg.to_map()
    #=> %{
    #     "@type" => "Product",
    #     "name" => "MacBook Pro",
    #     "offers" => %{"@type" => "Offer", "price" => 1999.0}
    #   }

A property field is untyped, so it accepts Schema.org's loose value model
directly: a scalar or a nested struct (`brand: "Apple"` or
`brand: %SchemaOrg.Brand{}`), and a single value or a list
(`offers: %SchemaOrg.Offer{}` or `offers: [%SchemaOrg.Offer{}, ...]`).

## Multiple top-level nodes (`@graph`)

Pass a **list** of structs to describe several independent nodes in one
document (e.g. a landing page's `Organization`, `WebSite`, and
`BreadcrumbList`). They are emitted under a single top-level `@graph`:

    [%SchemaOrg.Organization{name: "Acme"}, %SchemaOrg.WebSite{name: "Acme"}]
    |> SchemaOrg.to_json_ld()
    #=> {"@context":"https://schema.org","@graph":[{...},{...}]}

## Embedding in a page

`to_script_tag/1` returns an HTML-safe `<script type="application/ld+json">`
tag. In Phoenix, `SchemaOrg.HTML.json_ld/1` is a function component wrapping it
(compiled only when `:phoenix_live_view` is available).

# `schema_struct?`

```elixir
@spec schema_struct?(module()) :: boolean()
```

Returns `true` if `module` is a generated SchemaOrg type module.

# `to_json_ld`

```elixir
@spec to_json_ld(struct() | [struct()]) :: String.t()
```

Serialises a generated SchemaOrg struct (or a list of them) into a JSON-LD string.

Adds the top-level `@context`, recurses into nested structs, drops unset
(`nil`) properties, and re-keys each field to its Schema.org camelCase name.
A list of structs is wrapped in a top-level `@graph` array.

# `to_map`

```elixir
@spec to_map(struct() | [struct()]) :: map()
```

Like `to_json_ld/1` but returns the bare JSON-LD map (no `@context`, not encoded).

Useful for embedding inside a larger document or for assertions in tests. A
list of structs returns `%{"@graph" => [...]}`.

# `to_script_tag`

```elixir
@spec to_script_tag(struct() | [struct()]) :: String.t()
```

Renders a struct (or list of structs) as a complete, HTML-safe
`<script type="application/ld+json">` tag, ready to drop into a page `<head>`.

The JSON is encoded with `escape: :html_safe`, so a value containing
`</script>` (or `<!--`) cannot break out of the tag — the `<` is emitted as a
`<` escape, which a JSON-LD parser reads back as `<`.

Returns a plain string. In a Phoenix/HEEx template wrap it with
`Phoenix.HTML.raw/1`, or use the `SchemaOrg.HTML.json_ld/1` component:

    <%= Phoenix.HTML.raw(SchemaOrg.to_script_tag(@product)) %>

---

*Consult [api-reference.md](api-reference.md) for complete listing*
