2021/4/4 HTML::Pipeline
onk.icon
今日やりたいこと
markdown を HTML にするときに @onk みたいなのを見つけてリンクにしたいし、通知を飛ばしたい
code:markdown
@onk
code:html
code:markdown
`
@onk
`
code:html
<pre><code>@onk
</code></pre>
見たことあるやつ
実装していく
code:ruby
def main
puts process <<~MARKDOWN
@onk
MARKDOWN
puts process <<~MARKDOWN
`
onk
`
MARKDOWN
end
main if $0 == __FILE__
code:ruby
def process(markdown)
return markdown if markdown.blank?
doc = Nokogiri::HTML::DocumentFragment.parse(html)
MentionLink.new.call(doc)
doc.to_html
end
code:ruby
class MentionLink
def call(doc)
doc.xpath('.//text()').each do |text_node|
# pre, code を無視するのは当然として、
# リンクの無視は @foo が他サービスの URL として頻出するため (medium 等
new_html = text_node.content.gsub(PATTERN) do |mention_text|
if linkable?(mention_text) # 存在するユーザだったらリンクにする
else
mention_text
end
end
text_node.replace(new_html)
end
doc
end
# 存在するユーザだけリンクにしたいよね
def linkable?(username)
# TODO: 未実装。容易に N+1 が入り込んでくるので DataLoader 的にする
true
end
def has_ancestor?(node, tags)
return false unless node
if tags.include?(node.name)
true
else
has_ancestor?(node.parent, tags)
end
end
end
これで変換はできた
メンション一覧を取り出したい
MentionLink インスタンスに Set 用意するんだろうなぁ
code:rb
class MentionLink
attr_reader :mentions
def initialize
@mentions = []
end
def call(doc)
...
@mentions << mention_text1..-1 @mentions.uniq!
code:ruby
def process(markdown)
...
filter = MentionLink.new
filter.call(doc)
pp filter.mentions
doc.to_html
HTML を変更するフェーズと、変更後に副作用 (通知の生成とか) を行うフェーズを別に用意する?
Filter#call の中で両方やるのかなぁ、、、
HTML にリンクが含まれていれば通知する?というのも考えた (markdown の拡張記法じゃなく a タグを直接入力しているときも通知が飛んで便利)