1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | 1× 1× 1× 1× 1× | 'use strict'; var nconf = require('nconf'), validator = require('validator'), async = require('async'), winston = require('winston'), plugins = require('../plugins'); module.exports = function(Meta) { Meta.tags = {}; Meta.tags.parse = function(meta, link, callback) { async.parallel({ tags: function(next) { var defaultTags = [{ name: 'viewport', content: 'width=device-width, initial-scale=1.0, user-scalable=no' }, { name: 'content-type', content: 'text/html; charset=UTF-8', noEscape: true }, { name: 'apple-mobile-web-app-capable', content: 'yes' }, { name: 'mobile-web-app-capable', content: 'yes' }, { property: 'og:site_name', content: Meta.config.title || 'NodeBB' }, { name: 'keywords', content: Meta.config.keywords || '' }, { name: 'msapplication-badge', content: 'frequency=30; polling-uri=' + nconf.get('url') + '/sitemap.xml', noEscape: true }, { name: 'msapplication-square150x150logo', content: Meta.config['brand:logo'] || '', noEscape: true }]; plugins.fireHook('filter:meta.getMetaTags', defaultTags, next); }, links: function(next) { var defaultLinks = [{ rel: "icon", type: "image/x-icon", href: nconf.get('relative_path') + '/favicon.ico?' + Meta.config['cache-buster'] }, { rel: "manifest", href: nconf.get('relative_path') + '/manifest.json' }]; // Touch icons for mobile-devices if (Meta.config['brand:touchIcon']) { defaultLinks.push({ rel: 'apple-touch-icon', href: nconf.get('relative_path') + '/apple-touch-icon' }, { rel: 'icon', sizes: '36x36', href: nconf.get('relative_path') + '/uploads/system/touchicon-36.png' }, { rel: 'icon', sizes: '48x48', href: nconf.get('relative_path') + '/uploads/system/touchicon-48.png' }, { rel: 'icon', sizes: '72x72', href: nconf.get('relative_path') + '/uploads/system/touchicon-72.png' }, { rel: 'icon', sizes: '96x96', href: nconf.get('relative_path') + '/uploads/system/touchicon-96.png' }, { rel: 'icon', sizes: '144x144', href: nconf.get('relative_path') + '/uploads/system/touchicon-144.png' }, { rel: 'icon', sizes: '192x192', href: nconf.get('relative_path') + '/uploads/system/touchicon-192.png' }); } plugins.fireHook('filter:meta.getLinkTags', defaultLinks, next); } }, function(err, results) { meta = results.tags.concat(meta || []).map(function(tag) { if (!tag || typeof tag.content !== 'string') { winston.warn('Invalid meta tag. ', tag); return tag; } if (!tag.noEscape) { tag.content = validator.escape(tag.content); } return tag; }); addDescription(meta); link = results.links.concat(link || []); callback(null, { meta: meta, link: link }); }); }; function addDescription(meta) { var hasDescription = false; meta.forEach(function(tag) { if (tag.name === 'description') { hasDescription = true; } }); if (!hasDescription) { meta.push({ name: 'description', content: validator.escape(Meta.config.description || '') }); } } }; |