| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- 'use strict';
- const urlFn = require('url');
- const moment = require('moment');
- const util = require('hexo-util');
- const htmlTag = util.htmlTag;
- const stripHTML = util.stripHTML;
- const escapeHTML = util.escapeHTML;
- let cheerio;
- function meta(name, content, escape) {
- if (escape !== false && typeof content === 'string') {
- content = escapeHTML(content);
- }
- return `${htmlTag('meta', {
- name,
- content
- })}\n`;
- }
- function og(name, content, escape) {
- if (escape !== false && typeof content === 'string') {
- content = escapeHTML(content);
- }
- return `${htmlTag('meta', {
- property: name,
- content
- })}\n`;
- }
- function openGraphHelper(options = {}) {
- if (!cheerio) cheerio = require('cheerio');
- const page = this.page;
- const config = this.config;
- const content = page.content;
- let images = options.image || options.images || page.photos || [];
- let description = options.description || page.description || page.excerpt || content || config.description;
- const keywords = page.keywords || (page.tags && page.tags.length ? page.tags : undefined) || config.keywords;
- const title = options.title || page.title || config.title;
- const type = options.type || (this.is_post() ? 'article' : 'website');
- const url = options.url || this.url;
- const siteName = options.site_name || config.title;
- const twitterCard = options.twitter_card || 'summary';
- const updated = options.updated !== false ? options.updated || page.updated : false;
- const language = options.language || page.lang || page.language || config.language;
- let result = '';
- if (!Array.isArray(images)) images = [images];
- if (description) {
- description = stripHTML(description).substring(0, 200)
- .trim() // Remove prefixing/trailing spaces
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(/&/g, '&')
- .replace(/"/g, '"')
- .replace(/'/g, ''')
- .replace(/\n/g, ' '); // Replace new lines by spaces
- }
- if (!images.length && content) {
- images = images.slice();
- const $ = cheerio.load(content);
- $('img').each(function() {
- const src = $(this).attr('src');
- if (src) images.push(src);
- });
- }
- if (description) {
- result += meta('description', description, false);
- }
- if (keywords) {
- if (typeof keywords === 'string') {
- result += meta('keywords', keywords);
- } else if (keywords.length) {
- result += meta('keywords', keywords.map(tag => {
- return tag.name ? tag.name : tag;
- }).filter(keyword => !!keyword).join());
- }
- }
- result += og('og:type', type);
- result += og('og:title', title);
- result += og('og:url', url, false);
- result += og('og:site_name', siteName);
- if (description) {
- result += og('og:description', description, false);
- }
- if (language) {
- result += og('og:locale', language, false);
- }
- images = images.map(path => {
- if (!urlFn.parse(path).host) {
- // resolve `path`'s absolute path relative to current page's url
- // `path` can be both absolute (starts with `/`) or relative.
- return urlFn.resolve(url || config.url, path);
- }
- return path;
- });
- images.forEach(path => {
- result += og('og:image', path, false);
- });
- if (updated) {
- if ((moment.isMoment(updated) || moment.isDate(updated)) && !isNaN(updated.valueOf())) {
- result += og('og:updated_time', updated.toISOString());
- }
- }
- result += meta('twitter:card', twitterCard);
- result += meta('twitter:title', title);
- if (description) {
- result += meta('twitter:description', description, false);
- }
- if (images.length) {
- result += meta('twitter:image', images[0], false);
- }
- if (options.twitter_id) {
- let twitterId = options.twitter_id;
- if (twitterId[0] !== '@') twitterId = `@${twitterId}`;
- result += meta('twitter:creator', twitterId);
- }
- if (options.twitter_site) {
- result += meta('twitter:site', options.twitter_site, false);
- }
- if (options.google_plus) {
- result += `${htmlTag('link', {rel: 'publisher', href: options.google_plus})}\n`;
- }
- if (options.fb_admins) {
- result += og('fb:admins', options.fb_admins);
- }
- if (options.fb_app_id) {
- result += og('fb:app_id', options.fb_app_id);
- }
- return result.trim();
- }
- module.exports = openGraphHelper;
|