Source: plugin.js

import videojs from 'video.js';
import {version as VERSION} from '../package.json';
import document from 'global/document';
import duration8601 from './duration';

// Default options for the plugin.
const defaults = {
  schemaId: 'https://players.brightcove.net/{accountId}/{playerId}_{embedId}/index.html?videoId={id}',
  keywords: false,
  excludeTags: [],
  baseObject: {},
  includeEmbedUrl: true,
  preferLongDescription: false
};

/**
 * Schema plugin. Adds schema.org metadata in json+ld format
 * to the DOM for Google and other search engines which will
 * read data inserted by javascript.
 *
 * @function schema
 * @param    {Object} [options={}]
 *           An object of options
 * @param    {string} [options.schemaId]
 *           A URI to use as the id in the schema
 * @param    {boolean} [options.keywords]
 *           Whether to include tags as keywords
 * @param    {Array} [options.excludeTags]
 *           If including tags, an array of tags to exclude
 * @param    {Object} [options.baseObject]
 *           A template object to build the schema onto
 * @param    {boolean} [options.includeEmbedUrl]
 *           Whether to include the embed url
 * @param    {boolean} [options.preferLongDescription]
 *           Whether to prefer the long description
 */
const schema = function(options) {
  // Add element for this player to DOM
  this.schemaEl_ = document.createElement('script');
  this.schemaEl_.type = 'application/ld+json';
  document.head.appendChild(this.schemaEl_);

  options = videojs.mergeOptions(defaults, options);

  // This listens to error because Googlebot cannot play video
  this.on(['loadstart', 'error'], e => {

    if (!this.bcinfo || !this.mediainfo || !this.mediainfo.id) {
      videojs.log.warn('Unable to add schema without catalog info.');
      return;
    }

    const ld = videojs.mergeOptions(options.baseObject, {
      '@context': 'http://schema.org/',
      '@type': 'VideoObject',
      'name': this.mediainfo.name,
      'thumbnailUrl': this.mediainfo.poster,
      'uploadDate': this.mediainfo.publishedAt.split('T')[0],
      // Poor man's ad macros
      '@id': options.schemaId
        .replace('{id}', this.mediainfo.id)
        .replace('{referenceId}', this.mediainfo.referenceId)
        .replace('{playerId}', this.bcinfo.playerId)
        .replace('{embedId}', this.bcinfo.embedId)
        .replace('{accountId}', this.bcinfo.accountId)
    });

    if (options.preferLongDescription) {
      ld.description = this.mediainfo.longDescription || this.mediainfo.description || this.mediainfo.name;
    } else {
      ld.description = this.mediainfo.description || this.mediainfo.name;
    }

    const formattedDuration = duration8601(this.mediainfo.duration);

    if (formattedDuration) {
      ld.duration = formattedDuration;
    }

    if (options.includeEmbedUrl) {
      if (this.socialSettings) {
        const parser = document.createElement('div');

        parser.innerHTML = this.socialOverlay.getEmbedCode();
        ld.embedUrl = parser.querySelector('iframe').src;
      } else {
        ld.embedUrl = 'https://players.brightcove.net/' + this.bcinfo.accountId +
            '/' + this.bcinfo.playerId + '_' + this.bcinfo.embedId +
            '/index.html?videoId=' + this.mediainfo.id;
      }
    }

    if (options.keywords) {
      const keywords = [];

      this.mediainfo.tags.forEach(tag => {
        if (options.excludeTags.indexOf(tag) === -1) {
          keywords.push(tag);
        }
      });

      if (keywords.length > 0) {
        ld.keywords = keywords.join(',');
      }
    }

    this.schemaEl_.textContent = JSON.stringify(ld);
  });

  // Remove this player's element on dispose
  this.on('dispose', _ => {
    this.schemaEl_.parentNode.removeChild(this.schemaEl_);
  });
};

// Register the plugin with video.js.
videojs.registerPlugin('schema', schema);

// Include the version number.
schema.VERSION = VERSION;

export default schema;