diff --git a/app/helpers/markdown_helper.rb b/app/helpers/markdown_helper.rb index 6d80f255..ef634209 100644 --- a/app/helpers/markdown_helper.rb +++ b/app/helpers/markdown_helper.rb @@ -1,36 +1,42 @@ -module MarkdownHelper +# frozen_string_literal: true +module MarkdownHelper def markdown(content) - md = Redcarpet::Markdown.new(FlavoredMarkdown, MARKDOWN_OPTS) - Sanitize.fragment(md.render(content), EVIL_TAGS).html_safe + renderer = FlavoredMarkdown.new(**MARKDOWN_RENDERER_OPTS) + md = Redcarpet::Markdown.new(renderer, **MARKDOWN_OPTS) + # As the string has been sanitized we can mark it as HTML safe + Sanitize.fragment(md.render(content), EVIL_TAGS).strip.html_safe # rubocop:disable Rails/OutputSafety end def strip_markdown(content) - md = Redcarpet::Markdown.new(Redcarpet::Render::StripDown, MARKDOWN_OPTS) + renderer = Redcarpet::Render::StripDown.new + md = Redcarpet::Markdown.new(renderer, **MARKDOWN_OPTS) CGI.unescape_html(Sanitize.fragment(CGI.escape_html(md.render(content)), EVIL_TAGS)).strip end def twitter_markdown(content) - md = Redcarpet::Markdown.new(TwitteredMarkdown, MARKDOWN_OPTS) + renderer = TwitteredMarkdown.new + md = Redcarpet::Markdown.new(renderer, **MARKDOWN_OPTS) CGI.unescape_html(Sanitize.fragment(CGI.escape_html(md.render(content)), EVIL_TAGS)).strip end def question_markdown(content) - md = Redcarpet::Markdown.new(QuestionMarkdown.new, MARKDOWN_OPTS) - Sanitize.fragment(md.render(content), EVIL_TAGS).html_safe + renderer = QuestionMarkdown.new + md = Redcarpet::Markdown.new(renderer, **MARKDOWN_OPTS) + # As the string has been sanitized we can mark it as HTML safe + Sanitize.fragment(md.render(content), EVIL_TAGS).strip.html_safe # rubocop:disable Rails/OutputSafety end def raw_markdown(content) - md = Redcarpet::Markdown.new(Redcarpet::Render::HTML, RAW_MARKDOWN_OPTS) + renderer = Redcarpet::Render::HTML.new(**MARKDOWN_RENDERER_OPTS) + md = Redcarpet::Markdown.new(renderer, **MARKDOWN_OPTS) raw md.render content end def get_markdown(path, relative_to = Rails.root) - begin - File.read relative_to.join(path) - rescue Errno::ENOENT - "# Error reading #{relative_to.join(path)}" - end + File.read relative_to.join(path) + rescue Errno::ENOENT + "# Error reading #{relative_to.join(path)}" end def markdown_io(path, relative_to = Rails.root) diff --git a/app/services/flavored_markdown.rb b/app/services/flavored_markdown.rb index a6ecde56..26ee6af6 100644 --- a/app/services/flavored_markdown.rb +++ b/app/services/flavored_markdown.rb @@ -18,10 +18,6 @@ class FlavoredMarkdown < Redcarpet::Render::HTML paragraph text end - def paragraph(text) - "

#{text}

" - end - def raw_html(raw_html) Rack::Utils.escape_html raw_html end diff --git a/app/services/question_markdown.rb b/app/services/question_markdown.rb index 6ae585ea..6a251641 100644 --- a/app/services/question_markdown.rb +++ b/app/services/question_markdown.rb @@ -6,9 +6,7 @@ class QuestionMarkdown < Redcarpet::Render::StripDown include Rails.application.routes.url_helpers include SharedMarkers - def paragraph(text) - "

#{text}

" - end + def paragraph(text) = "

#{text.gsub("\n", '
')}

" def link(link, _title, _content) process_link(link) diff --git a/config/initializers/redcarpet.rb b/config/initializers/redcarpet.rb index aed5e5ff..484a8b18 100644 --- a/config/initializers/redcarpet.rb +++ b/config/initializers/redcarpet.rb @@ -1,32 +1,28 @@ -require 'redcarpet/render_strip' +# frozen_string_literal: true + +require "redcarpet/render_strip" MARKDOWN_OPTS = { - filter_html: true, - escape_html: true, - no_images: true, - no_styles: true, - safe_links_only: true, - xhtml: false, - hard_wrap: true, - no_intra_emphasis: true, - tables: true, - fenced_code_blocks: true, - autolink: true, - disable_indented_code_blocks: true, - strikethrough: true, - superscript: false -} - -RAW_MARKDOWN_OPTS = { - tables: true, - fenced_code_blocks: true, - autolink: true, + no_intra_emphasis: true, + tables: true, + fenced_code_blocks: true, + autolink: true, disable_indented_code_blocks: true, - strikethrough: true, - superscript: false -} + strikethrough: true, + superscript: false, +}.freeze + +MARKDOWN_RENDERER_OPTS = { + filter_html: true, + escape_html: true, + no_images: true, + no_styles: true, + safe_links_only: true, + xhtml: false, + hard_wrap: true, +}.freeze ALLOWED_HOSTS_IN_MARKDOWN = [ - APP_CONFIG['hostname'], - *APP_CONFIG['allowed_hosts_in_markdown'] -] \ No newline at end of file + APP_CONFIG["hostname"], + *APP_CONFIG["allowed_hosts_in_markdown"] +].freeze diff --git a/config/locales/views.en.yml b/config/locales/views.en.yml index 351e2c03..d16c9ce5 100644 --- a/config/locales/views.en.yml +++ b/config/locales/views.en.yml @@ -567,7 +567,6 @@ en: formatting: body_html: |

%{app_name} uses Markdown for formatting

-

A blank line starts a new paragraph

*italic text* for italic text

**bold text** for bold text

[link](https://example.com) for link

diff --git a/spec/helpers/markdown_helper_spec.rb b/spec/helpers/markdown_helper_spec.rb index 177b42c7..b4c22b76 100644 --- a/spec/helpers/markdown_helper_spec.rb +++ b/spec/helpers/markdown_helper_spec.rb @@ -31,6 +31,10 @@ describe MarkdownHelper, type: :helper do it "should escape HTML tags" do expect(markdown("I'm

a test

")).to eq("

I'm <h1>a test</h1>

") end + + it "should turn line breaks into
tags" do + expect(markdown("Some\ntext")).to eq("

Some
\ntext

") + end end describe "#strip_markdown" do @@ -70,6 +74,10 @@ describe MarkdownHelper, type: :helper do it "should not process invalid links" do expect(question_markdown("https://example.com/example.質問")).to eq("

https://example.com/example.質問

") end + + it "should turn line breaks into
tags" do + expect(markdown("Some\ntext")).to eq("

Some
\ntext

") + end end describe "#raw_markdown" do