<commit_before>import { useStaticQuery, graphql } from 'gatsby';

import React, { ReactElement } from 'react';
import { Helmet } from 'react-helmet';

import getPreFoldContent from 'src/util/getPreFoldContent';
import extractImage from 'src/util/extractImage';

import { LocationType } from 'src/types/Location';
import { PostType } from 'src/types/Post';
import { SiteMetadataType } from 'src/types/SiteMetadata';
import { SiteMetadataQueryType } from 'src/types/queries';

type PropsType = {
  location: LocationType;
  pageTitle: string;
  post?: PostType;
};

function create(name?: string, value?: string): ReactElement | null {
  if (!name || !value) {
    return null;
  }

  return <meta key={name} property={name} content={value} />;
}

function removeHTML(html?: string): string | undefined {
  if (!html) {
    return html;
  }
  return html.replace(/<[^>]*>/g, '');
}

function generatePostSpecificTags(
  post: PostType | undefined,
  siteMetadata: SiteMetadataType,
  url: string
): Array<ReactElement | null> {
  if (!post) {
    return [];
  }

  const data = post?.frontmatter;
  if (!data) {
    throw new Error(`Page had missing frontmatter: ${JSON.stringify(data)}`);
  }

  const postImage = extractImage(post.html);
  const preFold = getPreFoldContent(post.html);
  const description = removeHTML(preFold);
  const twitterCardType = postImage ? 'summary_large_image' : 'summary';
  const socialImage = postImage || siteMetadata.author.image;

  const ld = {
    '@context': 'http://schema.org',
    '@type': 'Article',
    publisher: {
      '@type': 'Organization',
      name: siteMetadata.blogTitle,
      logo: siteMetadata.author.image,
    },
    author: {
      '@type': 'Person',
      name: siteMetadata.author.name,
      image: siteMetadata.author.image,
      url: siteMetadata.author.url,
      description: siteMetadata.author.blurb,
    },
    headline: data.title,
    datePublished: data.date,
    url,
    description,
    image: {
      '@type': 'ImageObject',
      url: socialImage,
    },
    mainEntityOfPage: url,
  };

  return [
    create('og:image', socialImage),
    create('twitter:image', socialImage),

    create('og:type', 'article'),
    create('og:title', data.title),
    create('og:description', description),
    create('article:published_time', data.date),

    create('twitter:card', twitterCardType),
    create('twitter:title', data.title),
    create('twitter:description', description),

    <script
      key="ld"
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(ld, null, '  ') }}
    />,
  ];
}<commit_msg>fix(metadata): an application/ld+json script tag that react-helmet likes<commit_after>import { useStaticQuery, graphql } from 'gatsby';

import React, { ReactElement } from 'react';
import { Helmet } from 'react-helmet';

import getPreFoldContent from 'src/util/getPreFoldContent';
import extractImage from 'src/util/extractImage';

import { LocationType } from 'src/types/Location';
import { PostType } from 'src/types/Post';
import { SiteMetadataType } from 'src/types/SiteMetadata';
import { SiteMetadataQueryType } from 'src/types/queries';

type PropsType = {
  location: LocationType;
  pageTitle: string;
  post?: PostType;
};

function create(name?: string, value?: string): ReactElement | null {
  if (!name || !value) {
    return null;
  }

  return <meta key={name} property={name} content={value} />;
}

function removeHTML(html?: string): string | undefined {
  if (!html) {
    return html;
  }
  return html.replace(/<[^>]*>/g, '');
}

function generatePostSpecificTags(
  post: PostType | undefined,
  siteMetadata: SiteMetadataType,
  url: string
): Array<ReactElement | null> {
  if (!post) {
    return [];
  }

  const data = post?.frontmatter;
  if (!data) {
    throw new Error(`Page had missing frontmatter: ${JSON.stringify(data)}`);
  }

  const postImage = extractImage(post.html);
  const preFold = getPreFoldContent(post.html);
  const description = removeHTML(preFold);
  const twitterCardType = postImage ? 'summary_large_image' : 'summary';
  const socialImage = postImage || siteMetadata.author.image;

  const ld = {
    '@context': 'http://schema.org',
    '@type': 'Article',
    publisher: {
      '@type': 'Organization',
      name: siteMetadata.blogTitle,
      logo: siteMetadata.author.image,
    },
    author: {
      '@type': 'Person',
      name: siteMetadata.author.name,
      image: siteMetadata.author.image,
      url: siteMetadata.author.url,
      description: siteMetadata.author.blurb,
    },
    headline: data.title,
    datePublished: data.date,
    url,
    description,
    image: {
      '@type': 'ImageObject',
      url: socialImage,
    },
    mainEntityOfPage: url,
  };

  return [
    create('og:image', socialImage),
    create('twitter:image', socialImage),

    create('og:type', 'article'),
    create('og:title', data.title),
    create('og:description', description),
    create('article:published_time', data.date),

    create('twitter:card', twitterCardType),
    create('twitter:title', data.title),
    create('twitter:description', description),

    <script key="ld" type="application/ld+json">
      {JSON.stringify(ld, null, '  ')}
    </script>,
  ];
}
{'fraction_non_alphanumeric': 0.1493048943058465, 'fraction_numerical': 0.0, 'mean_word_length': 3.82277318640955, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7112958', 'n_tokens_mistral': 1639, 'n_tokens_neox': 1620, 'n_words': 368}