2024-04-29 00:17:15 +02:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2023-02-22 05:00:42 +01:00
|
|
|
class SimpleFormatComponent < ApplicationComponent
|
|
|
|
# see: https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
|
|
|
|
REDCARPET_EXTENSIONS = {
|
2023-07-26 18:55:02 +02:00
|
|
|
no_intra_emphasis: true,
|
|
|
|
disable_indented_code_blocks: true,
|
|
|
|
space_after_headers: true,
|
2023-02-22 05:00:42 +01:00
|
|
|
tables: false,
|
|
|
|
fenced_code_blocks: false,
|
|
|
|
autolink: false,
|
|
|
|
strikethrough: false,
|
|
|
|
lax_spacing: false,
|
|
|
|
superscript: false,
|
|
|
|
underline: false,
|
|
|
|
highlight: false,
|
|
|
|
quote: false,
|
|
|
|
footnotes: false
|
|
|
|
}
|
|
|
|
|
|
|
|
# see: https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch
|
|
|
|
REDCARPET_RENDERER_OPTS = {
|
|
|
|
no_images: true
|
|
|
|
}
|
|
|
|
|
2023-11-06 19:01:25 +01:00
|
|
|
SIMPLE_URL_REGEX = %r{https?://[^\s<>]+}
|
2024-02-13 10:37:03 +01:00
|
|
|
EMAIL_IN_TEXT_REGEX = Regexp.new(StrictEmailValidator::REGEXP.source.gsub(/\\A|\\z/, '\b'))
|
2023-04-20 13:10:45 +02:00
|
|
|
|
2023-11-06 19:01:25 +01:00
|
|
|
def initialize(text, allow_a: true, allow_autolink: true, class_names_map: {})
|
2023-04-20 13:10:45 +02:00
|
|
|
@allow_a = allow_a
|
2023-11-06 19:01:25 +01:00
|
|
|
@allow_autolink = allow_a || allow_autolink
|
|
|
|
|
|
|
|
# Logic for html links/autolinks:
|
|
|
|
# Sometimes we want to allow autolinking of urls, without allowing html/markdown links from users.
|
|
|
|
# Because we sanitize the rendered markdown, when html links are not allowed, we can't enable redcarpet autolink
|
|
|
|
# (it would be sanitized), so we manually autolink after sanitization.
|
|
|
|
# At the contrary, when links are allowed, autolinking is always made with redcarpet.
|
2023-04-20 13:10:45 +02:00
|
|
|
|
2023-07-26 18:55:02 +02:00
|
|
|
list_item = false
|
|
|
|
lines = (text || "")
|
|
|
|
.lines
|
2023-05-15 14:54:07 +02:00
|
|
|
.map(&:lstrip) # this block prevent redcarpet to consider " text" as block code by lstriping
|
2023-04-20 13:10:45 +02:00
|
|
|
|
2023-07-26 18:55:02 +02:00
|
|
|
@text = lines.map do |line|
|
|
|
|
item_number = line.match(/\A(\d+)\./)
|
|
|
|
if item_number.present?
|
|
|
|
list_item = true
|
|
|
|
"\n" + line + "[value:#{item_number[1]}]"
|
|
|
|
elsif line.match?(/\A[-*+]\s/)
|
|
|
|
list_item = true
|
|
|
|
"\n" + line
|
|
|
|
elsif line == ''
|
|
|
|
list_item = false
|
|
|
|
"\n" + line
|
|
|
|
elsif list_item
|
|
|
|
line
|
|
|
|
else
|
|
|
|
"\n" + line
|
|
|
|
end
|
|
|
|
end.join.lstrip
|
2023-04-20 13:10:45 +02:00
|
|
|
|
2023-02-22 05:00:42 +01:00
|
|
|
@renderer = Redcarpet::Markdown.new(
|
2023-07-27 05:37:27 +02:00
|
|
|
Redcarpet::BareRenderer.new(class_names_map: { list: 'fr-ol-content--override' }),
|
2023-02-22 05:00:42 +01:00
|
|
|
REDCARPET_EXTENSIONS.merge(autolink: @allow_a)
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2023-11-06 19:01:25 +01:00
|
|
|
def autolink(text)
|
|
|
|
return text if !@allow_autolink
|
|
|
|
return text if @allow_a # already autolinked
|
|
|
|
|
|
|
|
text.gsub(SIMPLE_URL_REGEX) do |url|
|
|
|
|
helpers.link_to(ERB::Util.html_escape(url), ERB::Util.html_escape(url), title: helpers.new_tab_suffix(nil), **helpers.external_link_attributes)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-02-22 05:00:42 +01:00
|
|
|
def tags
|
|
|
|
if @allow_a
|
|
|
|
Rails.configuration.action_view.sanitized_allowed_tags + ['a']
|
|
|
|
else
|
|
|
|
Rails.configuration.action_view.sanitized_allowed_tags
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def attributes
|
2023-07-26 18:55:02 +02:00
|
|
|
['target', 'rel', 'href', 'class', 'title', 'value']
|
2023-02-22 05:00:42 +01:00
|
|
|
end
|
|
|
|
end
|