/**
 * The structured-data graph, rendered from the API's pre-encoded string.
 *
 * Deliberately NOT `JSON.stringify(meta.schemaGraph)`. The backend's
 * SchemaGenerator is 726 lines and 30+ node types and stays the single
 * authority on the graph; re-serialising here would reorder keys and re-escape
 * unicode — semantically identical, but it makes the parity diff noisy for no
 * gain and creates a second place that decides how the graph is spelled.
 *
 * Escaping is applied at source: PageMeta::schemaJson() encodes with
 * JSON_HEX_TAG | JSON_HEX_AMP, so `<`, `>` and `&` arrive already hex-escaped
 * and nothing in the payload can terminate this element. That matters because
 * the graph is built from editor-controlled fields, and before those flags a
 * title containing a literal closing script tag was stored XSS on every page
 * the record appeared on.
 *
 * The pass below is defence in depth for the same characters — idempotent,
 * because a hex escape contains none of them.
 */
function escapeForScriptTag(json: string): string {
  return json.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026");
}

export default function JsonLd({ json }: { json: string | null }) {
  if (!json) {
    return null;
  }

  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: escapeForScriptTag(json) }}
    />
  );
}
