FEATURE: add local onebox handler for /docs urls (#145)

This commit is contained in:
Renato Atilio 2023-07-14 10:35:11 -03:00 committed by GitHub
parent 8180b9cfb7
commit 025bf46f8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 148 additions and 9 deletions

View File

@ -47,7 +47,7 @@ module Docs
end
def get_topic(topic, current_user)
return nil unless topic_in_docs(topic.category_id, topic.tags)
return nil unless Docs.topic_in_docs(topic.category_id, topic.tags)
topic_view = TopicView.new(topic.id, current_user)
guardian = Guardian.new(current_user)
@ -73,13 +73,5 @@ module Docs
end
title
end
def topic_in_docs(category, tags)
category_match = Docs::Query.categories.include?(category.to_s)
tags = tags.pluck(:name)
tag_match = Docs::Query.tags.any? { |tag| tags.include?(tag) }
category_match || tag_match
end
end
end

View File

@ -11,4 +11,21 @@ module ::Docs
end
end
end
def self.onebox_template
@onebox_template ||=
begin
path =
"#{Rails.root}/plugins/discourse-docs/lib/onebox/templates/discourse_docs_list.mustache"
File.read(path)
end
end
def self.topic_in_docs(category, tags)
category_match = Docs::Query.categories.include?(category.to_s)
tags = tags.pluck(:name)
tag_match = Docs::Query.tags.any? { |tag| tags.include?(tag) }
category_match || tag_match
end
end

View File

@ -0,0 +1,7 @@
<aside class="onebox docs-onebox">
<article class="onebox-body docs-onebox-body">
<h3>
<a href="{{url}}">{{{name}}}</a>
</h3>
</article>
</aside>

View File

@ -50,6 +50,54 @@ after_initialize do
end
end
if Oneboxer.respond_to?(:register_local_handler)
Oneboxer.register_local_handler("docs/docs") do |url, route|
uri = URI(url)
query = URI.decode_www_form(uri.query).to_h if uri.query
if query && query["topic"]
topic = Topic.includes(:tags).find_by(id: query["topic"])
if Docs.topic_in_docs(topic.category_id, topic.tags) && Guardian.new.can_see_topic?(topic)
first_post = topic.ordered_posts.first
args = {
topic_id: topic.id,
post_number: first_post.post_number,
avatar: PrettyText.avatar_img(first_post.user.avatar_template_url, "tiny"),
original_url: url,
title: PrettyText.unescape_emoji(CGI.escapeHTML(topic.title)),
category_html: CategoryBadge.html_for(topic.category),
quote:
PrettyText.unescape_emoji(
first_post.excerpt(SiteSetting.post_onebox_maxlength, keep_svg: true),
),
}
template = Oneboxer.template("discourse_topic_onebox")
Mustache.render(template, args)
end
else
args = { url: url, name: I18n.t("js.docs.title") }
Mustache.render(Docs.onebox_template, args)
end
end
end
if InlineOneboxer.respond_to?(:register_local_handler)
InlineOneboxer.register_local_handler("docs/docs") do |url, route|
uri = URI(url)
query = URI.decode_www_form(uri.query).to_h if uri.query
if query && query["topic"]
topic = Topic.includes(:tags).find_by(id: query["topic"])
if Docs.topic_in_docs(topic.category_id, topic.tags) && Guardian.new.can_see_topic?(topic)
{ url: url, title: topic.title }
end
else
{ url: url, title: I18n.t("js.docs.title") }
end
end
end
add_to_class(:topic_query, :list_docs_topics) { default_results(@options) }
on(:robots_info) do |robots_info|

75
spec/plugin_spec.rb Normal file
View File

@ -0,0 +1,75 @@
# frozen_string_literal: true
require "rails_helper"
describe Docs do
fab!(:category) { Fabricate(:category) }
fab!(:topic) { Fabricate(:topic, category: category) }
fab!(:post) { Fabricate(:post, topic: topic) }
fab!(:non_docs_category) { Fabricate(:category) }
fab!(:non_docs_topic) { Fabricate(:topic, category: non_docs_category) }
fab!(:non_docs_post) { Fabricate(:post, topic: non_docs_topic) }
before do
SiteSetting.docs_enabled = true
SiteSetting.docs_categories = category.id.to_s
GlobalSetting.stubs(:docs_path).returns("docs")
end
describe "docs oneboxes" do
let(:docs_list_url) { "#{Discourse.base_url}/#{GlobalSetting.docs_path}" }
let(:docs_topic_url) { "#{Discourse.base_url}/#{GlobalSetting.docs_path}?topic=#{topic.id}" }
let(:non_docs_topic_url) do
"#{Discourse.base_url}/#{GlobalSetting.docs_path}?topic=#{non_docs_topic.id}"
end
context "when inline" do
it "renders docs list" do
results = InlineOneboxer.new([docs_list_url], skip_cache: true).process
expect(results).to be_present
expect(results[0][:url]).to eq(docs_list_url)
expect(results[0][:title]).to eq(I18n.t("js.docs.title"))
end
it "renders docs topic" do
results = InlineOneboxer.new([docs_topic_url], skip_cache: true).process
expect(results).to be_present
expect(results[0][:url]).to eq(docs_topic_url)
expect(results[0][:title]).to eq(topic.title)
end
it "does not render topic if not in docs" do
results = InlineOneboxer.new([non_docs_topic_url], skip_cache: true).process
expect(results).to be_empty
end
end
context "when regular" do
it "renders docs list" do
onebox = Oneboxer.preview(docs_list_url)
expect(onebox).to match_html <<~HTML
<aside class="onebox docs-onebox">
<article class="onebox-body docs-onebox-body">
<h3>
<a href="#{docs_list_url}">#{I18n.t("js.docs.title")}</a>
</h3>
</article>
</aside>
HTML
end
it "renders docs topic" do
onebox = Oneboxer.preview(docs_topic_url)
expect(onebox).to include(%{data-topic="#{topic.id}">})
expect(onebox).to include(PrettyText.avatar_img(post.user.avatar_template_url, "tiny"))
expect(onebox).to include(%{<a href="#{docs_topic_url}">#{topic.title}</a>})
expect(onebox).to include(post.excerpt)
end
it "does not onebox topic if not in docs" do
onebox = Oneboxer.preview(non_docs_topic_url)
expect(onebox).to eq(%{<a href='#{non_docs_topic_url}'>#{non_docs_topic_url}</a>})
end
end
end
end