FEATURE: add microdata prop and more links for crawler

- add microdata based on schema.org
- add breadcrumb on the top of topic
- add navigations link on the bottom of every pages
- add category description on the category list
This commit is contained in:
Erick Guan 2015-02-13 19:34:22 +08:00
parent 59a2f622c6
commit c955907f60
10 changed files with 152 additions and 87 deletions

View file

@ -62,8 +62,8 @@ class ListController < ApplicationController
list = TopicQuery.new(user, list_opts).public_send("list_#{filter}") list = TopicQuery.new(user, list_opts).public_send("list_#{filter}")
list.more_topics_url = construct_next_url_with(list_opts) list.more_topics_url = construct_url_with(:next, list_opts)
list.prev_topics_url = construct_prev_url_with(list_opts) list.prev_topics_url = construct_url_with(:prev, list_opts)
if Discourse.anonymous_filters.include?(filter) if Discourse.anonymous_filters.include?(filter)
@description = SiteSetting.site_description @description = SiteSetting.site_description
@rss = filter @rss = filter
@ -121,8 +121,8 @@ class ListController < ApplicationController
guardian.ensure_can_see_private_messages!(target_user.id) unless action == :topics_by guardian.ensure_can_see_private_messages!(target_user.id) unless action == :topics_by
list = generate_list_for(action.to_s, target_user, list_opts) list = generate_list_for(action.to_s, target_user, list_opts)
url_prefix = "topics" unless action == :topics_by url_prefix = "topics" unless action == :topics_by
list.more_topics_url = url_for(construct_next_url_with(list_opts, url_prefix)) list.more_topics_url = url_for(construct_url_with(:next, list_opts, url_prefix))
list.prev_topics_url = url_for(construct_prev_url_with(list_opts, url_prefix)) list.prev_topics_url = url_for(construct_url_with(:prev, list_opts, url_prefix))
respond_with_list(list) respond_with_list(list)
end end
end end
@ -166,8 +166,8 @@ class ListController < ApplicationController
user = list_target_user user = list_target_user
list = TopicQuery.new(user, top_options).list_top_for(period) list = TopicQuery.new(user, top_options).list_top_for(period)
list.for_period = period list.for_period = period
list.more_topics_url = construct_next_url_with(top_options) list.more_topics_url = construct_url_with(:next, top_options)
list.prev_topics_url = construct_prev_url_with(top_options) list.prev_topics_url = construct_url_with(:prev, top_options)
if use_crawler_layout? if use_crawler_layout?
@title = I18n.t("js.filters.top.#{period}.title") @title = I18n.t("js.filters.top.#{period}.title")
@ -279,14 +279,14 @@ class ListController < ApplicationController
TopicQuery.new(current_user, opts).send("list_#{action}", target_user) TopicQuery.new(current_user, opts).send("list_#{action}", target_user)
end end
def construct_next_url_with(opts, url_prefix = nil) def construct_url_with(action, opts, url_prefix = nil)
method = url_prefix.blank? ? "#{action_name}_path" : "#{url_prefix}_#{action_name}_path" method = url_prefix.blank? ? "#{action_name}_path" : "#{url_prefix}_#{action_name}_path"
public_send(method, opts.merge(next_page_params(opts))) url = if action == :prev
end public_send(method, opts.merge(prev_page_params(opts)))
else # :next
def construct_prev_url_with(opts, url_prefix = nil) public_send(method, opts.merge(next_page_params(opts)))
method = url_prefix.blank? ? "#{action_name}_path" : "#{url_prefix}_#{action_name}_path" end
public_send(method, opts.merge(prev_page_params(opts))) url.sub('.json?','?')
end end
def generate_top_lists(options) def generate_top_lists(options)

View file

@ -4,4 +4,18 @@ module TopicsHelper
link_to(topic.title,topic.relative_url) link_to(topic.title,topic.relative_url)
end end
def categories_breadcrumb(topic)
breadcrumb = [{url: categories_path,
name: I18n.t('js.filters.categories.title')}]
category = topic.category
if category
if (parent = category.parent_category)
breadcrumb.push url: parent.url, name: parent.name
end
breadcrumb.push url: category.url, name: category.name
end
breadcrumb
end
end end

View file

@ -1,14 +1,26 @@
<% @list.categories.each do |c| %> <div class='category-list' itemscope itemtype='http://schema.org/ItemList'>
<div class="category"> <meta itemprop='itemListOrder' content='http://schema.org/ItemListOrderDescending'>
<h2><a href="<%= path ("/c/" << (c.slug.blank? ? c.id : c.slug)) %>"><%= c.name %></a></h2> <% @list.categories.each do |c| %>
<div class="topic-list"> <div class='category' itemprop='itemListElement' itemscope itemtype='http://schema.org/ListItem'>
<%- if c.displayable_topics.present? %> <meta itemprop='url' content='<%= c.url %>'>
<% c.displayable_topics.each do |t| %> <h2><a href='/c/<%= c.slug.blank? ? c.id : c.slug %>' itemprop='item'>
<a href="<%= t.relative_url %>"><%= t.title %></a> <span title='<%= t 'posts' %>'>(<%= t.posts_count %>)</span><br/> <span itemprop='name'><%= c.name %></span>
<% end %> </a></h2>
<%- end %> <span itemprop='description'><%= c.description %></span>
<div class='topic-list' itemscope itemtype='http://schema.org/ItemList'>
<%- if c.displayable_topics.present? %>
<% c.displayable_topics.each do |t| %>
<div itemprop='itemListElement' itemscope itemtype='http://schema.org/ListItem'>
<meta itemprop='url' content='<%= t.url %>'>
<a href='<%= t.relative_url %>' itemprop='item'>
<span itemprop='name'><%= t.title %></span>
</a> <span title='<%= t 'posts' %>'>(<%= t.posts_count %>)</span>
</div>
<% end %>
<%- end %>
</div>
</div> </div>
</div> <% end %>
<% end %> </div>
<% content_for :title do %><%= I18n.t('js.filters.categories.title') %><% end %> <% content_for :title do %><%= I18n.t('js.filters.categories.title') %><% end %>

View file

@ -42,7 +42,17 @@
<!-- preload-content: --> <!-- preload-content: -->
<%= yield %> <%= yield %>
<!-- :preload-content --> <!-- :preload-content -->
<footer>
<nav itemscope itemtype='http://schema.org/SiteNavigationElement'>
<a href='/'><%= t 'home_title' %></a>
<%= link_to t('js.filters.categories.title'), categories_path %>
<%= link_to t('guidelines_topic.title'), guidelines_path %>
<%= link_to t('tos_topic.title'), tos_path %>
<%= link_to t('privacy_topic.title'), privacy_path %>
</nav>
</footer>
</div> </div>
<footer id='noscript-footer'> <footer id='noscript-footer'>
<p><%= t 'powered_by_html' %></p> <p><%= t 'powered_by_html' %></p>
</footer> </footer>

View file

@ -25,6 +25,13 @@
<%= yield %> <%= yield %>
</div> </div>
<footer class="container"> <footer class="container">
<nav itemscope itemtype='http://schema.org/SiteNavigationElement'>
<a href='/'><%= t 'home_title' %></a>
<%= link_to t('js.filters.categories.title'), categories_path %>
<%= link_to t('guidelines_topic.title'), guidelines_path %>
<%= link_to t('tos_topic.title'), tos_path %>
<%= link_to t('privacy_topic.title'), privacy_path %>
</nav>
<p><%= t 'powered_by_html' %></p> <p><%= t 'powered_by_html' %></p>
</footer> </footer>
<%= render_google_analytics_code %> <%= render_google_analytics_code %>

View file

@ -1,21 +1,26 @@
<div class="topic-list"> <div class='topic-list' itemscope itemtype='http://schema.org/ItemList'>
<% @list.topics.each do |t| %> <meta itemprop='itemListOrder' content='http://schema.org/ItemListOrderDescending'>
<a href="<%= t.relative_url %>"><%= t.title %></a> <% @list.topics.each_with_index do |t,i| %>
<% if !@category && t.category %> <div itemprop='itemListElement' itemscope itemtype='http://schema.org/ListItem'>
[<a href="<%= t.category.url%>"><%= t.category.name %></a>] <meta itemprop='url' content='<%= t.url %>'>
<a href='<%= t.relative_url %>' itemprop='item'>
<span itemprop='name'><%= t.title %></span>
</a>
<% if !@category && t.category %>
<span>[<a href='<%= t.category.url %>'><%= t.category.name %></a>]</span>
<% end %>
<span title='<%= t 'posts' %>'>(<%= t.posts_count %>)</span>
</div>
<% end %> <% end %>
<span title='<%= t 'posts' %>'>(<%= t.posts_count %>)</span><br/>
<% end %>
</div> </div>
<% if @list.topics.length > 0 && @list.more_topics_url %> <% if @list.topics.length > 0 && @list.more_topics_url %>
<p> <div role='navigation' itemscope itemtype='http://schema.org/SiteNavigationElement'>
<% if params[:page].to_i > 0 %> <% if params[:page].to_i > 0 %>
<a href="<%= @list.prev_topics_url.sub('.json?','?') %>" rel="prev"><%= t 'prev_page'%></a> &nbsp; <span itemprop='url'><a href='<%= @list.prev_topics_url %>' rel='prev' itemprop='name'><%= t 'prev_page' %></a> &nbsp;</span>
<% end %> <% end %>
<b><a href="<%= @list.more_topics_url.sub('.json?','?') %>" rel="next"><%= t 'next_page'%></a></b> <span itemprop='url'><b><a href='<%= @list.more_topics_url %>' rel='next' itemprop='name'><%= t 'next_page' %></a></b></span>
</p> </div>
<% end %> <% end %>
<% if @rss %> <% if @rss %>

View file

@ -1,20 +1,24 @@
<ul class="nav-pills"> <div itemscope itemtype='http://schema.org/WebPage'>
<li class="nav-item-about"><%= link_to t('about'), '/about' %></a></li> <meta itemprop='lastReviewed' content='<%= @topic.first_post.updated_at.to_date.to_formatted_s(:iso_8601) %>'>
<% if @faq_overriden %> <ul class='nav-pills' role='navigation' itemscope itemtype='http://schema.org/SiteNavigationElement'>
<li class="nav-item-guidelines"><a class="<%= @page == 'faq' ? 'active' : '' %>" href="<%=guidelines_path%>"><%=t "guidelines" %></a></li> <% if @faq_overriden %>
<li class="nav-item-faq"><a href="<%=faq_path%>"><%=t "js.faq" %></a></li> <li class='nav-item-guidelines'><a class='<%= @page == 'faq' ? 'active' : '' %>' href='<%= guidelines_path %>'><%= t 'guidelines' %></a></li>
<% else %> <li class='nav-item-faq'><a href='<%= faq_path %>'><%= t 'js.faq' %></a></li>
<li class="nav-item-faq"><a class="<%= @page == 'faq' ? 'active' : '' %>" href="<%=faq_path%>"><%=t "js.faq" %></a></li> <% else %>
<li class='nav-item-faq'><a class='<%= @page == 'faq' ? 'active' : '' %>' href='<%=faq_path%>'><%= t 'js.faq' %></a></li>
<% end %>
<li class='nav-item-tos'><a href='<%= tos_path %>' class='<%= @page == 'tos' ? 'active' : '' %>'><%= t 'terms_of_service.title' %></a></li>
<li class='nav-item-privacy'><a href='<%= privacy_path %>' class='<%= @page == 'privacy' ? 'active' : '' %>'><%= t 'privacy' %></a></li>
</ul>
<% if staff? %>
<p><a href='<%= @topic.url %>'><i class='fa fa-pencil'></i> <%= t 'edit_this_page' %></a></p>
<% end %> <% end %>
<li class="nav-item-tos"><a href="<%=tos_path%>" class="<%= @page == 'tos' ? 'active' : '' %>"><%=t "terms_of_service.title" %></a></li>
<li class="nav-item-privacy"><a href="<%=privacy_path%>" class="<%= @page == 'privacy' ? 'active' : '' %>"><%=t "privacy" %></a></li>
</ul>
<% if staff? %> <div itemprop='mainContentOfPage'>
<p><a href="<%= @topic.url %>"><i class="fa fa-pencil"></i> <%=t "edit_this_page" -%></a></p> <%= @body.html_safe %>
<% end %> </div>
</div>
<%= @body.html_safe %>
<% if @title %> <% if @title %>
<% content_for :title do %><%= @title %><% end %> <% content_for :title do %><%= @title %><% end %>

View file

@ -1,40 +1,52 @@
<h2> <h2>
<%= render_topic_title(@topic_view.topic) %> <%= render_topic_title(@topic_view.topic) %>
</h2> </h2>
<% if c = @topic_view.topic.category %>
<%= link_to c.name, c.url %> <div itemscope itemtype='http://schema.org/BreadcrumbList'>
<% end %> <% categories_breadcrumb(@topic_view.topic).each_with_index do |c,i| %>
<hr/> <span itemprop='itemListElement' itemscope itemtype='http://schema.org/ListItem'>
<%= link_to c[:url], itemprop: 'item' do %>
<span itemprop='name'><%= c[:name] %></span>
<% end %>
</span>
<meta itemprop='position' content='<%= i + 1 %>'>
<% end %>
</div>
<hr>
<% @topic_view.posts.each do |post| %> <% @topic_view.posts.each do |post| %>
<% if post.user %> <div itemscope itemtype='http://schema.org/Article'>
<div class='creator'> <% if (u = post.user) %>
<b><%= post.user.username %></b> <div class='creator'>
<%= "(#{post.user.name})" if (SiteSetting.display_name_on_posts && SiteSetting.enable_names?) %> — <span>
<%= post.created_at.to_formatted_s(:iso8601) %> — <a href='/users/<%= u.username %>'><b itemprop='author'><%= u.username %></b></a>
#<%= post.post_number %> <%= "(#{u.name})" if (SiteSetting.display_name_on_posts && SiteSetting.enable_names? && !u.name.blank?) %>
</div> <time datetime='<%= post.created_at.to_formatted_s(:iso8601) %>' itemprop='datePublished'>
<div class='post'> <%= post.created_at %>
<% if post.hidden %> </time>
<%= t('flagging.user_must_edit').html_safe %> </span>
<% else %> <span itemprop='position'>#<%= post.post_number %></span>
<%= post.cooked.html_safe %> </div>
<% end %> <div class='post' itemprop='articleBody'>
</div> <%= post.hidden ? t('flagging.user_must_edit').html_safe : post.cooked.html_safe %>
<hr/> </div>
<% end %> <meta itemprop='interactionCount' content='UserLikes:<%= post.like_count %>'>
<meta itemprop='interactionCount' content='UserComments:<%= post.reply_count %>'>
<hr>
<% end %>
</div>
<% end %> <% end %>
<% if @topic_view.prev_page || @topic_view.next_page %>
<p> <div role='navigation' itemscope itemtype='http://schema.org/SiteNavigationElement'>
<% if @topic_view.prev_page %> <% if @topic_view.prev_page %>
<%= link_to t(:prev_page), @topic_view.prev_page_path, rel: 'prev' %> <span itemprop='url'><%= link_to t(:prev_page), @topic_view.prev_page_path, rel: 'prev', itemprop: 'name' %></span>
<% end %> <% end %>
<% if @topic_view.next_page %> <% if @topic_view.next_page %>
<b><%= link_to t(:next_page), @topic_view.next_page_path, rel: 'next' %></b> <span itemprop='url'><b><%= link_to t(:next_page), @topic_view.next_page_path, rel: 'next', itemprop: 'name' %></b></span>
<% end %> <% end %>
</p> </div>
<% end %>
<% content_for :head do %> <% content_for :head do %>
<%= auto_discovery_link_tag(@topic_view, {action: :feed, slug: @topic_view.topic.slug, topic_id: @topic_view.topic.id}, title: t('rss_posts_in_topic', topic: @topic_view.title), type: 'application/rss+xml') %> <%= auto_discovery_link_tag(@topic_view, {action: :feed, slug: @topic_view.topic.slug, topic_id: @topic_view.topic.id}, title: t('rss_posts_in_topic', topic: @topic_view.title), type: 'application/rss+xml') %>

View file

@ -159,6 +159,7 @@ en:
next_page: "next page →" next_page: "next page →"
prev_page: "← previous page" prev_page: "← previous page"
page_num: "Page %{num}" page_num: "Page %{num}"
home_title: "Home"
topics_in_category: "Topics in the '%{category}' category" topics_in_category: "Topics in the '%{category}' category"
rss_posts_in_topic: "RSS feed of '%{topic}'" rss_posts_in_topic: "RSS feed of '%{topic}'"
rss_topics_in_category: "RSS feed of topics in the '%{category}' category" rss_topics_in_category: "RSS feed of topics in the '%{category}' category"

View file

@ -221,9 +221,9 @@ Discourse::Application.routes.draw do
post "login" => "static#enter" post "login" => "static#enter"
get "login" => "static#show", id: "login" get "login" => "static#show", id: "login"
get "faq" => "static#show", id: "faq" get "faq" => "static#show", id: "faq"
get "guidelines" => "static#show", id: "guidelines" get "guidelines" => "static#show", id: "guidelines", as: 'guidelines'
get "tos" => "static#show", id: "tos" get "tos" => "static#show", id: "tos", as: 'tos'
get "privacy" => "static#show", id: "privacy" get "privacy" => "static#show", id: "privacy", as: 'privacy'
get "signup" => "list#latest" get "signup" => "list#latest"
post "users/read-faq" => "users#read_faq" post "users/read-faq" => "users#read_faq"