Skip to content

Commit bbc43e9

Browse files
authored
Merge pull request increments#34 from increments/group-mention
Support group mention
2 parents 008a237 + 90d811e commit bbc43e9

File tree

4 files changed

+135
-0
lines changed

4 files changed

+135
-0
lines changed

lib/qiita/markdown.rb

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
require "qiita/markdown/filters/emoji"
1313
require "qiita/markdown/filters/footnote"
1414
require "qiita/markdown/filters/greenmat"
15+
require "qiita/markdown/filters/group_mention"
1516
require "qiita/markdown/filters/image_link"
1617
require "qiita/markdown/filters/mention"
1718
require "qiita/markdown/filters/sanitize"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
module Qiita
2+
module Markdown
3+
module Filters
4+
class GroupMention < HTML::Pipeline::Filter
5+
# @note Override
6+
def call
7+
if context[:group_mention_url_generator]
8+
result[:mentioned_groups] ||= []
9+
doc.search(".//text()").each do |node|
10+
mentionable_node = MentionableNode.new(node, context[:group_mention_url_generator])
11+
unless mentionable_node.ignorable?
12+
result[:mentioned_groups] |= mentionable_node.groups
13+
node.replace(mentionable_node.replaced_html)
14+
end
15+
end
16+
end
17+
doc
18+
end
19+
20+
class MentionableNode
21+
GROUP_IDENTIFIER_PATTERN = %r{
22+
(?:^|\W)
23+
@((?>[a-z\d][a-z\d-]{2,31}))
24+
\/
25+
([A-Za-z\d][A-Za-z\d-]{0,14}[A-Za-z\d])
26+
(?!\/)
27+
(?=
28+
\.+[ \t\W]|
29+
\.+$|
30+
[^0-9a-zA-Z_.]|
31+
$
32+
)
33+
}x
34+
35+
IGNORED_ANCESTOR_ELEMENT_NAMES = %w(
36+
a
37+
blockquote
38+
code
39+
pre
40+
style
41+
).freeze
42+
43+
# @param node [Nokogiri::XML::Node]
44+
# @param group_mention_url_generator [Proc]
45+
def initialize(node, group_mention_url_generator)
46+
@group_mention_url_generator = group_mention_url_generator
47+
@node = node
48+
end
49+
50+
# @return [Array<Hash>]
51+
def groups
52+
@groups ||= []
53+
end
54+
55+
# @return [false, true]
56+
def ignorable?
57+
!has_at_mark? || has_any_ignored_ancestor? || !replaced?
58+
end
59+
60+
# @return [String]
61+
def replaced_html
62+
@replaced_html ||= html.gsub(GROUP_IDENTIFIER_PATTERN) do |_match|
63+
team_url_name = ::Regexp.last_match(1)
64+
group_url_name = ::Regexp.last_match(2)
65+
group = { group_url_name: group_url_name, team_url_name: team_url_name }
66+
groups << group
67+
%(<a href="#{@group_mention_url_generator.call(group)}">) +
68+
%(@#{team_url_name}/#{group_url_name}</a>)
69+
end
70+
end
71+
72+
private
73+
74+
# @return [false, true]
75+
def has_any_ignored_ancestor?
76+
@node.ancestors.any? do |node|
77+
IGNORED_ANCESTOR_ELEMENT_NAMES.include?(node.name.downcase)
78+
end
79+
end
80+
81+
# @return [false, true]
82+
def has_at_mark?
83+
html.include?("@")
84+
end
85+
86+
# @return [String]
87+
def html
88+
@html ||= @node.to_html
89+
end
90+
91+
# @return [false, true]
92+
def replaced?
93+
html != replaced_html
94+
end
95+
end
96+
end
97+
end
98+
end
99+
end

lib/qiita/markdown/processor.rb

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class Processor
1414
Filters::Emoji,
1515
Filters::SyntaxHighlight,
1616
Filters::Mention,
17+
Filters::GroupMention,
1718
Filters::Sanitize,
1819
]
1920

spec/qiita/markdown/processor_spec.rb

+34
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,40 @@
457457
end
458458
end
459459

460+
context "with group mention" do
461+
let(:markdown) do
462+
"@alice/bob"
463+
end
464+
465+
it "does not replace it" do
466+
is_expected.to eq <<-EOS.strip_heredoc
467+
<p>@alice/bob</p>
468+
EOS
469+
end
470+
end
471+
472+
context "with group mention" do
473+
let(:context) do
474+
super().merge(group_mention_url_generator: lambda do |group|
475+
"https://#{group[:team_url_name]}.example.com/groups/#{group[:group_url_name]}"
476+
end)
477+
end
478+
479+
let(:markdown) do
480+
"@alice/bob"
481+
end
482+
483+
it "replaces it with preferred link and updates :mentioned_groups" do
484+
is_expected.to eq <<-EOS.strip_heredoc
485+
<p><a href="https://alice.example.com/groups/bob">@alice/bob</a></p>
486+
EOS
487+
expect(result[:mentioned_groups]).to eq [{
488+
group_url_name: "bob",
489+
team_url_name: "alice",
490+
}]
491+
end
492+
end
493+
460494
context "with normal link" do
461495
let(:markdown) do
462496
"[](/example)"

0 commit comments

Comments
 (0)