Add support for markdown-formatted toots
parent
bfc509f44a
commit
94aef563b9
2
Gemfile
2
Gemfile
|
@ -95,6 +95,8 @@ gem 'json-ld', '~> 3.0'
|
||||||
gem 'json-ld-preloaded', '~> 3.0'
|
gem 'json-ld-preloaded', '~> 3.0'
|
||||||
gem 'rdf-normalize', '~> 0.3'
|
gem 'rdf-normalize', '~> 0.3'
|
||||||
|
|
||||||
|
gem 'redcarpet', '~> 3.4'
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
gem 'fabrication', '~> 2.20'
|
gem 'fabrication', '~> 2.20'
|
||||||
gem 'fuubar', '~> 2.3'
|
gem 'fuubar', '~> 2.3'
|
||||||
|
|
|
@ -480,6 +480,7 @@ GEM
|
||||||
link_header (~> 0.0, >= 0.0.8)
|
link_header (~> 0.0, >= 0.0.8)
|
||||||
rdf-normalize (0.3.3)
|
rdf-normalize (0.3.3)
|
||||||
rdf (>= 2.2, < 4.0)
|
rdf (>= 2.2, < 4.0)
|
||||||
|
redcarpet (3.4.0)
|
||||||
redis (4.1.1)
|
redis (4.1.1)
|
||||||
redis-actionpack (5.0.2)
|
redis-actionpack (5.0.2)
|
||||||
actionpack (>= 4.0, < 6)
|
actionpack (>= 4.0, < 6)
|
||||||
|
@ -745,6 +746,7 @@ DEPENDENCIES
|
||||||
rails-i18n (~> 5.1)
|
rails-i18n (~> 5.1)
|
||||||
rails-settings-cached (~> 0.6)
|
rails-settings-cached (~> 0.6)
|
||||||
rdf-normalize (~> 0.3)
|
rdf-normalize (~> 0.3)
|
||||||
|
redcarpet (~> 3.4)
|
||||||
redis (~> 4.1)
|
redis (~> 4.1)
|
||||||
redis-namespace (~> 1.5)
|
redis-namespace (~> 1.5)
|
||||||
redis-rails (~> 5.0)
|
redis-rails (~> 5.0)
|
||||||
|
|
|
@ -36,14 +36,52 @@ class Formatter
|
||||||
|
|
||||||
html = raw_content
|
html = raw_content
|
||||||
html = "RT @#{prepend_reblog} #{html}" if prepend_reblog
|
html = "RT @#{prepend_reblog} #{html}" if prepend_reblog
|
||||||
html = encode_and_link_urls(html, linkable_accounts)
|
html = format_markdown(html) if status.content_type == 'text/markdown'
|
||||||
|
html = encode_and_link_urls(html, linkable_accounts, keep_html: status.content_type == 'text/markdown')
|
||||||
html = encode_custom_emojis(html, status.emojis, options[:autoplay]) if options[:custom_emojify]
|
html = encode_custom_emojis(html, status.emojis, options[:autoplay]) if options[:custom_emojify]
|
||||||
html = simple_format(html, {}, sanitize: false)
|
html = simple_format(html, {}, sanitize: false) unless status.content_type == 'text/markdown'
|
||||||
html = html.delete("\n")
|
html = html.delete("\n")
|
||||||
|
|
||||||
html.html_safe # rubocop:disable Rails/OutputSafety
|
html.html_safe # rubocop:disable Rails/OutputSafety
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def format_markdown(html)
|
||||||
|
extensions = {
|
||||||
|
autolink: false,
|
||||||
|
no_intra_emphasis: true,
|
||||||
|
fenced_code_blocks: true,
|
||||||
|
disable_indented_code_blocks: true,
|
||||||
|
strikethrough: true,
|
||||||
|
lax_spacing: true,
|
||||||
|
space_after_headers: true,
|
||||||
|
superscript: true,
|
||||||
|
underline: true,
|
||||||
|
highlight: true,
|
||||||
|
footnotes: true
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer = Redcarpet::Render::HTML.new({
|
||||||
|
filter_html: false,
|
||||||
|
no_images: true,
|
||||||
|
no_styles: true,
|
||||||
|
safe_links_only: true,
|
||||||
|
hard_wrap: true,
|
||||||
|
link_attributes: { target: '_blank', rel: 'nofollow noopener' },
|
||||||
|
})
|
||||||
|
|
||||||
|
markdown = Redcarpet::Markdown.new(renderer, extensions)
|
||||||
|
|
||||||
|
html = reformat(markdown.render(html))
|
||||||
|
html = html.gsub("\r\n", "\n").gsub("\r", "\n")
|
||||||
|
code_safe_strip(html)
|
||||||
|
end
|
||||||
|
|
||||||
|
def code_safe_strip(html, char="\n")
|
||||||
|
html = html.split(/(<code[ >].*?\/code>)/m)
|
||||||
|
html.each_slice(2) { |part| part[0].delete!(char) }
|
||||||
|
html.join
|
||||||
|
end
|
||||||
|
|
||||||
def reformat(html)
|
def reformat(html)
|
||||||
sanitize(html, Sanitize::Config::MASTODON_STRICT)
|
sanitize(html, Sanitize::Config::MASTODON_STRICT)
|
||||||
end
|
end
|
||||||
|
@ -116,7 +154,7 @@ class Formatter
|
||||||
accounts = nil
|
accounts = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
rewrite(html.dup, entities) do |entity|
|
rewrite(html.dup, entities, options[:keep_html]) do |entity|
|
||||||
if entity[:url]
|
if entity[:url]
|
||||||
link_to_url(entity, options)
|
link_to_url(entity, options)
|
||||||
elsif entity[:hashtag]
|
elsif entity[:hashtag]
|
||||||
|
@ -186,7 +224,7 @@ class Formatter
|
||||||
html
|
html
|
||||||
end
|
end
|
||||||
|
|
||||||
def rewrite(text, entities)
|
def rewrite(text, entities, keep_html = false)
|
||||||
text = text.to_s
|
text = text.to_s
|
||||||
|
|
||||||
# Sort by start index
|
# Sort by start index
|
||||||
|
@ -199,12 +237,12 @@ class Formatter
|
||||||
|
|
||||||
last_index = entities.reduce(0) do |index, entity|
|
last_index = entities.reduce(0) do |index, entity|
|
||||||
indices = entity.respond_to?(:indices) ? entity.indices : entity[:indices]
|
indices = entity.respond_to?(:indices) ? entity.indices : entity[:indices]
|
||||||
result << encode(text[index...indices.first])
|
result << (keep_html ? text[index...indices.first] : encode(text[index...indices.first]))
|
||||||
result << yield(entity)
|
result << yield(entity)
|
||||||
indices.last
|
indices.last
|
||||||
end
|
end
|
||||||
|
|
||||||
result << encode(text[last_index..-1])
|
result << (keep_html ? text[last_index..-1] : encode(text[last_index..-1]))
|
||||||
|
|
||||||
result.flatten.join
|
result.flatten.join
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue