Commit 7d5b51f3 authored by Douwe Maan's avatar Douwe Maan

Merge branch 'rs-opengraph' into 'master'

Add Open Graph meta tags



See merge request !2192
parents 9dc1a53b 6d385e33
...@@ -8,6 +8,80 @@ module PageLayoutHelper ...@@ -8,6 +8,80 @@ module PageLayoutHelper
@page_title.join(" \u00b7 ") @page_title.join(" \u00b7 ")
end end
# Define or get a description for the current page
#
# description - String (default: nil)
#
# If this helper is called multiple times with an argument, only the last
# description will be returned when called without an argument. Descriptions
# have newlines replaced with spaces and all HTML tags are sanitized.
#
# Examples:
#
# page_description # => "GitLab Community Edition"
# page_description("Foo")
# page_description # => "Foo"
#
# page_description("<b>Bar</b>\nBaz")
# page_description # => "Bar Baz"
#
# Returns an HTML-safe String.
def page_description(description = nil)
@page_description ||= page_description_default
if description.present?
@page_description = description.squish
else
sanitize(@page_description, tags: []).truncate_words(30)
end
end
# Default value for page_description when one hasn't been defined manually by
# a view
def page_description_default
if @project
@project.description || brand_title
else
brand_title
end
end
def page_image
default = image_url('gitlab_logo.png')
if @project
@project.avatar_url || default
elsif @user
avatar_icon(@user)
else
default
end
end
# Define or get attributes to be used as Twitter card metadata
#
# map - Hash of label => data pairs. Keys become labels, values become data
#
# Raises ArgumentError if given more than two attributes
def page_card_attributes(map = {})
raise ArgumentError, 'cannot provide more than two attributes' if map.length > 2
@page_card_attributes ||= {}
@page_card_attributes = map.reject { |_,v| v.blank? } if map.present?
@page_card_attributes
end
def page_card_meta_tags
tags = ''
page_card_attributes.each_with_index do |pair, i|
tags << tag(:meta, property: "twitter:label#{i + 1}", content: pair[0])
tags << tag(:meta, property: "twitter:data#{i + 1}", content: pair[1])
end
tags.html_safe
end
def header_title(title = nil, title_url = nil) def header_title(title = nil, title_url = nil)
if title if title
@header_title = title @header_title = title
......
...@@ -161,6 +161,14 @@ module Issuable ...@@ -161,6 +161,14 @@ module Issuable
self.class.to_s.underscore self.class.to_s.underscore
end end
# Returns a Hash of attributes to be used for Twitter card metadata
def card_attributes
{
'Author' => author.try(:name),
'Assignee' => assignee.try(:name)
}
end
def notes_with_associations def notes_with_associations
notes.includes(:author, :project) notes.includes(:author, :project)
end end
......
- page_title "GitLab" %head{prefix: "og: http://ogp.me/ns#"}
%head
%meta{charset: "utf-8"} %meta{charset: "utf-8"}
%meta{'http-equiv' => 'X-UA-Compatible', content: 'IE=edge'} %meta{'http-equiv' => 'X-UA-Compatible', content: 'IE=edge'}
%meta{content: "GitLab Community Edition", name: "description"}
%meta{name: 'referrer', content: 'origin-when-cross-origin'} %meta{name: 'referrer', content: 'origin-when-cross-origin'}
%meta{name: "description", content: page_description}
-# Open Graph - http://ogp.me/
%meta{property: 'og:type', content: "object"}
%meta{property: 'og:site_name', content: "GitLab"}
%meta{property: 'og:title', content: page_title}
%meta{property: 'og:description', content: page_description}
%meta{property: 'og:image', content: page_image}
%meta{property: 'og:url', content: request.base_url + request.fullpath}
-# Twitter Card - https://dev.twitter.com/cards/types/summary
%meta{property: 'twitter:card', content: "summary"}
%meta{property: 'twitter:title', content: page_title}
%meta{property: 'twitter:description', content: page_description}
%meta{property: 'twitter:image', content: page_image}
= page_card_meta_tags
- page_title "GitLab"
%title= page_title %title= page_title
= favicon_link_tag 'favicon.ico' = favicon_link_tag 'favicon.ico'
......
- page_title "#{@issue.title} (##{@issue.iid})", "Issues" - page_title "#{@issue.title} (##{@issue.iid})", "Issues"
- page_description @issue.description
- page_card_attributes @issue.card_attributes
= render "header_title" = render "header_title"
.issue .issue
......
- page_title "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests" - page_title "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests"
- page_description @merge_request.description
- page_card_attributes @merge_request.card_attributes
= render "header_title" = render "header_title"
- if params[:view] == 'parallel' - if params[:view] == 'parallel'
......
- page_title @milestone.title, "Milestones" - page_title @milestone.title, "Milestones"
- page_description @milestone.description
= render "header_title" = render "header_title"
.detail-page-header .detail-page-header
......
- page_title @user.name - page_title @user.name
- page_description @user.bio
- header_title @user.name, user_path(@user) - header_title @user.name, user_path(@user)
= content_for :meta_tags do = content_for :meta_tags do
......
require 'rails_helper'
describe PageLayoutHelper do
describe 'page_description' do
it 'defaults to value returned by page_description_default helper' do
allow(helper).to receive(:page_description_default).and_return('Foo')
expect(helper.page_description).to eq 'Foo'
end
it 'returns the last-pushed description' do
helper.page_description('Foo')
helper.page_description('Bar')
helper.page_description('Baz')
expect(helper.page_description).to eq 'Baz'
end
it 'squishes multiple newlines' do
helper.page_description("Foo\nBar\nBaz")
expect(helper.page_description).to eq 'Foo Bar Baz'
end
it 'truncates' do
helper.page_description <<-LOREM.strip_heredoc
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo
ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis
dis parturient montes, nascetur ridiculus mus. Donec quam felis,
ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa
quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget,
arcu.
LOREM
expect(helper.page_description).to end_with 'quam felis,...'
end
it 'sanitizes all HTML' do
helper.page_description("<b>Bold</b> <h1>Header</h1>")
expect(helper.page_description).to eq 'Bold Header'
end
end
describe 'page_description_default' do
it 'uses Project description when available' do
project = double(description: 'Project Description')
helper.instance_variable_set(:@project, project)
expect(helper.page_description_default).to eq 'Project Description'
end
it 'uses brand_title when Project description is nil' do
project = double(description: nil)
helper.instance_variable_set(:@project, project)
expect(helper).to receive(:brand_title).and_return('Brand Title')
expect(helper.page_description_default).to eq 'Brand Title'
end
it 'falls back to brand_title' do
allow(helper).to receive(:brand_title).and_return('Brand Title')
expect(helper.page_description_default).to eq 'Brand Title'
end
end
describe 'page_image' do
it 'defaults to the GitLab logo' do
expect(helper.page_image).to end_with 'assets/gitlab_logo.png'
end
context 'with @project' do
it 'uses Project avatar if available' do
project = double(avatar_url: 'http://example.com/uploads/avatar.png')
helper.instance_variable_set(:@project, project)
expect(helper.page_image).to eq project.avatar_url
end
it 'falls back to the default' do
project = double(avatar_url: nil)
helper.instance_variable_set(:@project, project)
expect(helper.page_image).to end_with 'assets/gitlab_logo.png'
end
end
context 'with @user' do
it 'delegates to avatar_icon helper' do
user = double('User')
helper.instance_variable_set(:@user, user)
expect(helper).to receive(:avatar_icon).with(user)
helper.page_image
end
end
end
describe 'page_card_attributes' do
it 'raises ArgumentError when given more than two attributes' do
map = { foo: 'foo', bar: 'bar', baz: 'baz' }
expect { helper.page_card_attributes(map) }.
to raise_error(ArgumentError, /more than two attributes/)
end
it 'rejects blank values' do
map = { foo: 'foo', bar: '' }
helper.page_card_attributes(map)
expect(helper.page_card_attributes).to eq({ foo: 'foo' })
end
end
describe 'page_card_meta_tags' do
it 'returns the twitter:label and twitter:data tags' do
allow(helper).to receive(:page_card_attributes).and_return(foo: 'bar')
tags = helper.page_card_meta_tags
aggregate_failures do
expect(tags).to include %q(<meta property="twitter:label1" content="foo" />)
expect(tags).to include %q(<meta property="twitter:data1" content="bar" />)
end
end
end
end
...@@ -81,4 +81,22 @@ describe Issue, "Issuable" do ...@@ -81,4 +81,22 @@ describe Issue, "Issuable" do
expect(hook_data[:object_attributes]).to eq(issue.hook_attrs) expect(hook_data[:object_attributes]).to eq(issue.hook_attrs)
end end
end end
describe '#card_attributes' do
it 'includes the author name' do
allow(issue).to receive(:author).and_return(double(name: 'Robert'))
allow(issue).to receive(:assignee).and_return(nil)
expect(issue.card_attributes).
to eq({ 'Author' => 'Robert', 'Assignee' => nil })
end
it 'includes the assignee name' do
allow(issue).to receive(:author).and_return(double(name: 'Robert'))
allow(issue).to receive(:assignee).and_return(double(name: 'Douwe'))
expect(issue.card_attributes).
to eq({ 'Author' => 'Robert', 'Assignee' => 'Douwe' })
end
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment