Improve support for old browsers (#9515)

* FEATURE: Improve crawler view

* FIX: Make lazyYT crawler-friendly

* DEV: Rename discourse-internet-explorer to discourse-unsupported-browser

* DEV: Detect more unsupported browsers

Follow-up to 4eebbd2212.

* FIX: Hide browser update notice in print view
This commit is contained in:
Dan Ungureanu 2020-04-29 21:40:21 +03:00 committed by GitHub
parent 402194f313
commit c85018cdfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 151 additions and 114 deletions

2
.gitignore vendored
View File

@ -54,7 +54,7 @@ bootsnap-compile-cache/
!/plugins/discourse-narrative-bot
!/plugins/discourse-presence
!/plugins/discourse-local-dates
!/plugins/discourse-internet-explorer
!/plugins/discourse-unsupported-browser
/plugins/*/auto_generated/
/spec/fixtures/plugins/my_plugin/auto_generated

View File

@ -1,3 +1,12 @@
if (!window.WeakMap || !window.Promise) {
window.unsupportedBrowser = true;
} else {
// Some implementations of `WeakMap.prototype.has` do not accept false
// values and Ember's `isClassicDecorator` sometimes does that (it only
// checks for `null` and `undefined`).
try {
new WeakMap().has(0);
} catch (err) {
window.unsupportedBrowser = true;
}
}

View File

@ -142,6 +142,12 @@
}
}
.link-bottom-line {
.category-name {
margin-right: 12px;
}
}
.unread-indicator {
&.read {
display: none;

View File

@ -21,12 +21,6 @@ body.crawler {
}
}
.raw-topic-link {
display: block;
font-weight: bold;
margin-bottom: 0.25em;
}
.topic-list {
margin-bottom: 1em;
}
@ -34,6 +28,14 @@ body.crawler {
footer {
margin-top: 4em;
}
.category-title {
color: $primary;
}
.discourse-tags {
color: $primary-medium;
}
}
.noscript-footer-nav {
@ -47,10 +49,7 @@ body.crawler {
#noscript-footer {
padding: 0 10px;
}
.crawler-topic-title {
margin-top: 0.5em;
text-align: center;
}
.crawler-post {
@ -86,27 +85,6 @@ body.crawler {
}
}
#breadcrumbs {
margin-bottom: 0.5em;
font-size: $font-up-1;
> div {
margin-bottom: 0.15em;
}
.badge-category-bg {
background-color: $secondary-high;
}
.category-title {
color: $primary;
}
}
.crawler-tags-list {
span {
display: block;
margin-bottom: 0.15em;
}
}
.crawler-linkback-list {
margin-top: 1em;
a {

View File

@ -12,9 +12,9 @@ module TopicsHelper
category = topic.category
if category && !category.uncategorized?
breadcrumb.push(url: category.url, name: category.name)
breadcrumb.push(url: category.url, name: category.name, color: category.color)
while category = category.parent_category
breadcrumb.prepend(url: category.url, name: category.name)
breadcrumb.prepend(url: category.url, name: category.name, color: category.color)
end
end

View File

@ -34,13 +34,13 @@
<%= yield %>
</div>
<footer class="container wrap">
<nav class='crawler-nav' itemscope itemtype='http://schema.org/SiteNavigationElement'>
<nav class='crawler-nav'>
<ul>
<li itemprop="name"><a href='<%= path "/" %>' itemprop="url"><%= t 'home_title' %> </a></li>
<li itemprop="name"><a href='<%= path "/categories" %>' itemprop="url"><%= t 'js.filters.categories.title' %> </a></li>
<li itemprop="name"><a href='<%= path "/guidelines" %>' itemprop="url"><%= t 'guidelines_topic.title' %> </a></li>
<li itemprop="name"><a href='<%= path "/tos" %>' itemprop="url"><%= t 'tos_topic.title' %> </a></li>
<li itemprop="name"><a href='<%= path "/privacy" %>' itemprop="url"><%= t 'privacy_topic.title' %> </a></li>
<li itemscope itemtype='http://schema.org/SiteNavigationElement' itemprop="name"><a href='<%= path "/" %>' itemprop="url"><%= t 'home_title' %> </a></li>
<li itemscope itemtype='http://schema.org/SiteNavigationElement' itemprop="name"><a href='<%= path "/categories" %>' itemprop="url"><%= t 'js.filters.categories.title' %> </a></li>
<li itemscope itemtype='http://schema.org/SiteNavigationElement' itemprop="name"><a href='<%= path "/guidelines" %>' itemprop="url"><%= t 'guidelines_topic.title' %> </a></li>
<li itemscope itemtype='http://schema.org/SiteNavigationElement' itemprop="name"><a href='<%= path "/tos" %>' itemprop="url"><%= t 'tos_topic.title' %> </a></li>
<li itemscope itemtype='http://schema.org/SiteNavigationElement' itemprop="name"><a href='<%= path "/privacy" %>' itemprop="url"><%= t 'privacy_topic.title' %> </a></li>
</ul>
</nav>
<p class='powered-by-link'><%= t 'powered_by_html' %></p>

View File

@ -44,7 +44,9 @@
<thead>
<tr>
<th><%= t 'js.topic.title' %></th>
<th></th>
<th><%= t 'js.replies' %></th>
<th><%= t 'js.views' %></th>
<th><%= t 'js.activity' %></th>
</tr>
</thead>
@ -52,25 +54,53 @@
<tbody>
<meta itemprop='itemListOrder' content='http://schema.org/ItemListOrderDescending'>
<% @list.topics.each_with_index do |t,i| %>
<tr>
<td itemprop='itemListElement' itemscope itemtype='http://schema.org/ListItem'>
<meta itemprop='position' content='<%= i %>'>
<meta itemprop='url' content='<%= t.url %>'>
<tr class="topic-list-item">
<td class="main-link" itemprop='itemListElement' itemscope itemtype='http://schema.org/ListItem'>
<meta itemprop='name' content='<%= t.title %>'>
<a href='<%= t.url %>' class='title raw-link raw-topic-link'>
<span><%= t.title %></span>
</a>
<meta itemprop='url' content='<%= t.url %>'>
<% if t.image_url.present? %>
<meta itemprop='image' content='<%= t.image_url %>'>
<% end %>
<meta itemprop='position' content='<%= i + 1 %>'>
<span class="link-top-line">
<a href='<%= t.url %>' class='title raw-link raw-topic-link'><%= t.title %></a>
</span>
<div class="link-bottom-line">
<% if (!@category || @category.has_children?) && t.category %>
<div>
<a href='<%= t.category.url %>'><span class='category-name'><%= t.category.name %></span></a>
<a href='<%= t.category.url %>' class='badge-wrapper bullet'>
<span class='badge-category-bg' style='background-color: #<%= t.category.color %>'></span>
<span class='category-title'><%= t.category.name %></span>
</a>
<% end %>
<% if t.tags %>
<div class="discourse-tags">
<% t.tags.each_with_index do |tag, index| %>
<a href='<%= tag.full_url %>' class='discourse-tag'><%= tag.name %></a>
<% if index < t.tags.size - 1 %>,&nbsp;<% end %>
<% end %>
</div>
<% end %>
</div>
<% if t.pinned_until && (t.pinned_until > Time.zone.now) && (t.pinned_globally || @list.category) && t.excerpt %>
<p class='excerpt'>
<%= t.excerpt.html_safe %>
</p>
<% end %>
</td>
<td class='posters'>
<% t.posters.each do |poster| %>
<% if poster.moreCount %>
<a class="posters-more-count"><% poster.moreCount %></a>
<% else %>
<a href="<%= Discourse.base_url %>/u/<%= poster.user.username %>" class="<%= poster.extraClasses %>">
<img width="25" height="25" src="<%= poster.user.avatar_template.gsub('{size}', '25') %>" class="avatar" title='<%= h("#{poster.user.username} - #{poster.description}") %>' aria-label='<%= h("#{poster.user.username} - #{poster.description}") %>'>
</a>
<% end %>
<% end %>
</td>
<td>
<span class='views' title='<%= t 'views' %>'><%= t.views %></span>
</td>
<td>
<span class='posts' title='<%= t 'posts' %>'><%= t.posts_count %></span>
</td>
@ -89,7 +119,9 @@
<% if params[:page].to_i > 0 %>
<span itemprop='name'><a href='<%= @list.prev_topics_url %>' rel='prev' itemprop='url'><%= t 'prev_page' %></a> &nbsp;</span>
<% end %>
<% if @list.topics.size == @list.per_page %>
<span itemprop='name'><b><a href='<%= @list.more_topics_url %>' rel='next' itemprop='url'><%= t 'next_page' %></a></b></span>
<% end %>
</div>
<% content_for :head do %>

View File

@ -1,37 +1,36 @@
<% if @topic_view %>
<h1 class="crawler-topic-title">
<div id="topic-title">
<h1>
<%= render_topic_title(@topic_view.topic) %>
</h1>
<div class="topic-category" itemscope itemtype="http://schema.org/BreadcrumbList">
<% @breadcrumbs = categories_breadcrumb(@topic_view.topic) %>
<% if @breadcrumbs.present? %>
<div id="breadcrumbs" itemscope itemtype="http://schema.org/BreadcrumbList">
<% @breadcrumbs.each_with_index do |c, i| %>
<div itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<span itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem">
<a href="<%= Discourse.base_url %><%= c[:url] %>" class="badge-wrapper bullet" itemprop="item">
<span class="badge-category-bg"></span>
<span class="badge-category-bg" style='background-color: #<%= c[:color] %>'></span>
<span class="category-title" itemprop="name"><%= c[:name] %></span>
</a>
<meta itemprop="position" content="<%= i + 1 %>" />
</div>
</span>
<% end %>
</div>
<% end %>
<% if SiteSetting.tagging_enabled %>
<% @tags = @topic_view.topic.tags %>
<% if @tags.present? %>
<div class='crawler-tags-list' itemscope itemtype='http://schema.org/DiscussionForumPosting'>
<meta itemprop='keywords' content='<%= @tags.map(&:name).join(', ') %>'>
<div class='discourse-tags list-tags'>
<% @tags.each_with_index do |tag, i| %>
<div itemprop='keywords'>
<a href='<%= "#{Discourse.base_url}/tag/#{tag.name}" %>' rel="tag">
<span itemprop='headline'><%= tag.name -%></span>
</a>
</div>
<a href='<%= "#{Discourse.base_url}/tag/#{tag.name}" %>' class='discourse-tag' rel="tag"><%= tag.name -%></a><% if i < @tags.size - 1 %>, <% end %>
<% end %>
</div>
<% end %>
<% end %>
</div>
</div>
<%= server_plugin_outlet "topic_header" %>

View File

@ -74,7 +74,7 @@ class Plugin::Metadata
"docker_manager",
"lazy-yt",
"poll",
"discourse-internet-explorer"
"discourse-unsupported-browser"
])
FIELDS ||= [:name, :about, :version, :authors, :url, :required_version, :transpile_js]

View File

@ -1,4 +0,0 @@
en:
site_settings:
discourse_internet_explorer_enabled: "Enable temporary Internet Explorer support. This plugin is an effort to maintain compatibility with older browsers and will be completely removed in the near future."
discourse_internet_explorer_deprecation_warning: "Show an Internet Explorer deprecation warning"

View File

@ -1,6 +0,0 @@
plugins:
discourse_internet_explorer_enabled:
default: true
discourse_internet_explorer_deprecation_warning:
default: true
client: true

View File

@ -2,12 +2,12 @@ import { withPluginApi } from "discourse/lib/plugin-api";
function initializeInternetExplorerDeprecation(api) {
const siteSettings = api.container.lookup("site-settings:main");
if (siteSettings.discourse_internet_explorer_deprecation_warning) {
if (siteSettings.browser_deprecation_warning) {
const { isIE11 } = api.container.lookup("capabilities:main");
if (isIE11) {
api.addGlobalNotice(
I18n.t("discourse_internet_explorer.deprecation_warning"),
"deprecate-internet-explorer",
I18n.t("discourse_unsupported_browser.deprecation_warning"),
"browser-deprecation-warning",
{ dismissable: true, dismissDuration: moment.duration(1, "week") }
);
}
@ -15,7 +15,7 @@ function initializeInternetExplorerDeprecation(api) {
}
export default {
name: "discourse-internet-explorer",
name: "discourse-unsupported-browser",
initialize() {
withPluginApi("0.8.37", initializeInternetExplorerDeprecation);

View File

@ -1,4 +1,4 @@
en:
js:
discourse_internet_explorer:
discourse_unsupported_browser:
deprecation_warning: This site will soon remove support for Internet Explorer 11 - please update your browser

View File

@ -0,0 +1,4 @@
en:
site_settings:
discourse_unsupported_browser_enabled: "Enable temporary support for old browsers. This plugin is an effort to maintain compatibility with older browsers and will be completely removed in the near future."
browser_deprecation_warning: "Show a warning to deprecated browsers"

View File

@ -0,0 +1,6 @@
plugins:
discourse_unsupported_browser_enabled:
default: true
browser_deprecation_warning:
default: true
client: true

View File

@ -1,12 +1,12 @@
# frozen_string_literal: true
# name: discourse-internet-explorer
# about: Attempts to provide backward support for internt explorer
# name: discourse-unsupported-browser
# about: Attempts to provide support for old and unsupported browser through polyfills
# version: 1.0
# authors: Joffrey Jaffeux, David Taylor, Daniel Waterworth, Robin Ward
# url: https://github.com/discourse/discourse/tree/master/plugins/discourse-internet-explorer
# url: https://github.com/discourse/discourse/tree/master/plugins/discourse-unsupported-browser
enabled_site_setting :discourse_internet_explorer_enabled
enabled_site_setting :discourse_unsupported_browser_enabled
hide_plugin if self.respond_to?(:hide_plugin)
register_asset 'stylesheets/ie.scss'
@ -15,8 +15,8 @@ register_asset 'stylesheets/ie.scss'
# been activated so it can be uploaded to CDNs.
DiscourseEvent.on(:after_plugin_activation) do ||
polyfill_path = "#{Plugin::Instance.js_path}/#{self.directory_name}-optional.js"
FileUtils.cp("#{Rails.root}/public/plugins/discourse-internet-explorer/js/ie.js", polyfill_path)
Rails.configuration.assets.precompile << "plugins/discourse-internet-explorer-optional.js"
FileUtils.cp("#{Rails.root}/public/plugins/discourse-unsupported-browser/js/ie.js", polyfill_path)
Rails.configuration.assets.precompile << "plugins/discourse-unsupported-browser-optional.js"
end
after_initialize do
@ -42,7 +42,7 @@ after_initialize do
# to be loaded before other files
register_html_builder('server:before-script-load') do |controller|
if BrowserDetection.browser(controller.request.env['HTTP_USER_AGENT']) == :ie
path = controller.helpers.script_asset_path('plugins/discourse-internet-explorer-optional')
path = controller.helpers.script_asset_path('plugins/discourse-unsupported-browser-optional')
<<~JAVASCRIPT
<script src="#{path}"></script>

View File

@ -7,31 +7,31 @@ describe 'Bootstrapping the Discourse App' do
context "when disabled" do
before do
SiteSetting.discourse_internet_explorer_enabled = false
SiteSetting.discourse_unsupported_browser_enabled = false
end
it "does not include the IE stylesheet or Javascript" do
get "/categories", headers: { "HTTP_USER_AGENT" => ie_agent }
expect(response.body).not_to match(/discourse-internet-explorer-optional.js/)
expect(response.body).not_to match(/stylesheets\/discourse-internet-explorer/)
expect(response.body).not_to match(/discourse-unsupported-browser-optional.js/)
expect(response.body).not_to match(/stylesheets\/discourse-unsupported-browser/)
end
end
context "when enabled" do
before do
SiteSetting.discourse_internet_explorer_enabled = true
SiteSetting.discourse_unsupported_browser_enabled = true
end
it "includes the IE js and css" do
get "/categories", headers: { "HTTP_USER_AGENT" => ie_agent }
expect(response.body).to match(/discourse-internet-explorer-optional.js/)
expect(response.body).to match(/stylesheets\/discourse-internet-explorer/)
expect(response.body).to match(/discourse-unsupported-browser-optional.js/)
expect(response.body).to match(/stylesheets\/discourse-unsupported-browser/)
end
it "doesn't include IE stuff for non-IE browsers" do
get "/categories", headers: { "HTTP_USER_AGENT" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36" }
expect(response.body).not_to match(/discourse-internet-explorer-optional.js/)
expect(response.body).not_to match(/stylesheets\/discourse-internet-explorer/)
expect(response.body).not_to match(/discourse-unsupported-browser-optional.js/)
expect(response.body).not_to match(/stylesheets\/discourse-unsupported-browser/)
end
end
end

View File

@ -27,7 +27,19 @@ class Onebox::Engine::YoutubeOnebox
# Put in the LazyYT div instead of the iframe
escaped_title = ERB::Util.html_escape(video_title)
"<div class=\"lazyYT\" data-youtube-id=\"#{video_id}\" data-youtube-title=\"#{escaped_title}\" data-width=\"#{video_width}\" data-height=\"#{video_height}\" data-parameters=\"#{embed_params}\"></div>"
<<~EOF
<div class="lazyYT"
data-youtube-id="#{video_id}"
data-youtube-title="#{escaped_title}"
data-width="#{video_width}"
data-height="#{video_height}"
data-parameters="#{embed_params}">
<a href="https://www.youtube.com/watch?v=#{video_id}" target="_blank">
<img src="https://img.youtube.com/vi/#{video_id}/hqdefault.jpg" width="#{video_width}" height="#{video_height}" title="#{escaped_title}">
</a>
</div>
EOF
else
yt_onebox_to_html
end

View File

@ -18,6 +18,7 @@ var $buo = function() {
return;
}
document.getElementsByTagName('body')[0].classList.add("crawler");
var mainElement = document.getElementById("main");
var noscriptElements = document.getElementsByTagName("noscript");
// noscriptElements[0].innerHTML contains encoded HTML
@ -34,7 +35,7 @@ var $buo = function() {
// create the notification div stylesheet
var sheet = document.createElement("style");
var style = ".buorg {position:absolute; z-index:111111; width:100%; top:0px; left:0px; background:#FDF2AB; text-align:left; font-family: sans-serif; color:#000; font-size: 14px;} .buorg div {padding: 8px;} .buorg a, .buorg a:visited {color:#E25600; text-decoration: underline;}";
var style = ".buorg {position:absolute; z-index:111111; width:100%; top:0px; left:0px; background:#FDF2AB; text-align:left; font-family: sans-serif; color:#000; font-size: 14px;} .buorg div {padding: 8px;} .buorg a, .buorg a:visited {color:#E25600; text-decoration: underline;} @media print { .buorg { display: none !important; } }";
// insert the div and stylesheet into the DOM
document.body.appendChild(div); // put it last in the DOM so Googlebot doesn't include it in search excerpts