<commit_before>import React, { PropTypes } from 'react'
import Helmet from 'react-helmet'
import trunc from 'trunc-html'

function getTextContent(blocks) {
  let text = ''
  for (const block of blocks) {
    if (block.kind === 'text') {
      text += block.data
    }
  }
  return text.length ? trunc(text, 200).text : ''
}

function getTitle(text, username) {
  const paragraphs = text.split('\n')
  const title = paragraphs[0].split('.')[0]
  return (
    title.length ?
    `${title} - from @${username} on Ello.` :
    `A post from @${username} on Ello.`
  )
}

function getDescription(text) {
  return text.length ? text : 'Discover more amazing work like this on Ello.'
}

function getImages(blocks) {
  const imageUrls = []
  for (const block of blocks) {
    if (block.kind === 'image' && block.data && block.data.url) {
      imageUrls.push(block.data.url)
    }
  }
  return imageUrls
}

function getEmbeds(blocks) {
  const embedUrls = []
  for (const block of blocks) {
    if (block.kind === 'embed' && block.data && block.data.thumbnailLargeUrl) {
      embedUrls.push(block.data.thumbnailLargeUrl)
    }
  }
  return embedUrls
}

function getMetaTags({ title, desc, url }) {
  const tags = [
    { name: 'name', itemprop: 'name', content: title },
    { name: 'url', itemprop: 'url', content: url },
    { name: 'description', itemprop: 'description', content: desc },
  ]
  return tags
}

function getOpenGraphTags({ title, desc, images, embeds, url }) {
  const tags = [
    { property: 'og:type', content: 'article' },
    { property: 'og:url', content: url },
    { property: 'og:title', content: title },
    { property: 'og:description', content: desc },
  ]
  const imgs = [].concat(images, embeds)
  for (const img of imgs) {
    tags.push({ property: 'og:image', content: img })
  }
  return tags
}

// Twitter wants images under 1mb, so we may need to look up the assets
// eventually. For now, only flip the card if we don't have any images.
function getTwitterTags({ images = [], embeds = [] }) {
  const tags = []
  if (!images.length && !embeds.length) {
    tags.push({ name: 'twitter:card', content: 'summary' })
  }
  return tags
}

function getSchemaTags({ images, embeds }) {
  const tags = []
  const imgs = [].concat(images, embeds)
  for (const img of imgs) {
    tags.push({ name: 'image', itemprop: 'image', content: img })
  }
  return tags
}

export const PostDetailHelmet = ({ post, author }) => {
  const blocks = (post.repostContent || post.content) || post.summary
  const text = getTextContent(blocks)
  const title = getTitle(text, author.username)
  const desc = getDescription(text)
  const images = getImages(blocks)
  const embeds = getEmbeds(blocks)
  const url = `${ENV.AUTH_DOMAIN}/${author.username}/post/${post.token}`

  const metaTags = getMetaTags({ title, desc, url })
  const openGraphTags = getOpenGraphTags({ title, desc, images, embeds, url })
  const twitterTags = getTwitterTags({ images, embeds })
  const schemaTags = getSchemaTags({ images, embeds })
  const tags = [].concat(metaTags, openGraphTags, twitterTags, schemaTags)
  return <Helmet title={ title } meta={ tags } />
}

PostDetailHelmet.propTypes = {
  author: PropTypes.object.isRequired,
  post: PropTypes.object.isRequired,
}

<commit_msg>Adds a canonical link to the original for a repost<commit_after>import React, { PropTypes } from 'react'
import Helmet from 'react-helmet'
import trunc from 'trunc-html'

function getTextContent(blocks) {
  let text = ''
  for (const block of blocks) {
    if (block.kind === 'text') {
      text += block.data
    }
  }
  return text.length ? trunc(text, 200).text : ''
}

function getTitle(text, username) {
  const paragraphs = text.split('\n')
  const title = paragraphs[0].split('.')[0]
  return (
    title.length ?
    `${title} - from @${username} on Ello.` :
    `A post from @${username} on Ello.`
  )
}

function getDescription(text) {
  return text.length ? text : 'Discover more amazing work like this on Ello.'
}

function getImages(blocks) {
  const imageUrls = []
  for (const block of blocks) {
    if (block.kind === 'image' && block.data && block.data.url) {
      imageUrls.push(block.data.url)
    }
  }
  return imageUrls
}

function getEmbeds(blocks) {
  const embedUrls = []
  for (const block of blocks) {
    if (block.kind === 'embed' && block.data && block.data.thumbnailLargeUrl) {
      embedUrls.push(block.data.thumbnailLargeUrl)
    }
  }
  return embedUrls
}

function getMetaTags({ title, desc, url }) {
  const tags = [
    { name: 'name', itemprop: 'name', content: title },
    { name: 'url', itemprop: 'url', content: url },
    { name: 'description', itemprop: 'description', content: desc },
  ]
  return tags
}

function getOpenGraphTags({ title, desc, images, embeds, url }) {
  const tags = [
    { property: 'og:type', content: 'article' },
    { property: 'og:url', content: url },
    { property: 'og:title', content: title },
    { property: 'og:description', content: desc },
  ]
  const imgs = [].concat(images, embeds)
  for (const img of imgs) {
    tags.push({ property: 'og:image', content: img })
  }
  return tags
}

// Twitter wants images under 1mb, so we may need to look up the assets
// eventually. For now, only flip the card if we don't have any images.
function getTwitterTags({ images = [], embeds = [] }) {
  const tags = []
  if (!images.length && !embeds.length) {
    tags.push({ name: 'twitter:card', content: 'summary' })
  }
  return tags
}

function getSchemaTags({ images, embeds }) {
  const tags = []
  const imgs = [].concat(images, embeds)
  for (const img of imgs) {
    tags.push({ name: 'image', itemprop: 'image', content: img })
  }
  return tags
}

export const PostDetailHelmet = ({ post, author }) => {
  const blocks = (post.repostContent || post.content) || post.summary
  const text = getTextContent(blocks)
  const title = getTitle(text, author.username)
  const desc = getDescription(text)
  const images = getImages(blocks)
  const embeds = getEmbeds(blocks)
  const url = `${ENV.AUTH_DOMAIN}/${author.username}/post/${post.token}`
  const repostUrl = post.repostContent ? `${ENV.AUTH_DOMAIN}${post.repostPath}` : null

  const metaTags = getMetaTags({ title, desc, url })
  const openGraphTags = getOpenGraphTags({ title, desc, images, embeds, url })
  const twitterTags = getTwitterTags({ images, embeds })
  const schemaTags = getSchemaTags({ images, embeds })
  const tags = [].concat(metaTags, openGraphTags, twitterTags, schemaTags)
  const links = post.repostContent ? [{ rel: 'canonical', href: repostUrl }] : []

  return <Helmet title={ title } link={ links } meta={ tags } />
}

PostDetailHelmet.propTypes = {
  author: PropTypes.object.isRequired,
  post: PropTypes.object.isRequired,
}


{'fraction_non_alphanumeric': 0.1481810115350488, 'fraction_numerical': 0.001774622892635315, 'mean_word_length': 3.6481099656357387, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, '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': '5617762', 'n_tokens_mistral': 2194, 'n_tokens_neox': 2182, 'n_words': 633}