Merge pull request #1085 from Retrospring/fix/markdown-rendering

Markdown rendering fixes
This commit is contained in:
Karina Kwiatek 2023-02-18 21:00:40 +01:00 committed by GitHub
commit 61b7281544
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 51 additions and 48 deletions

View File

@ -1,37 +1,43 @@
module MarkdownHelper # frozen_string_literal: true
module MarkdownHelper
def markdown(content) def markdown(content)
md = Redcarpet::Markdown.new(FlavoredMarkdown, MARKDOWN_OPTS) renderer = FlavoredMarkdown.new(**MARKDOWN_RENDERER_OPTS)
Sanitize.fragment(md.render(content), EVIL_TAGS).html_safe 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 end
def strip_markdown(content) 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 CGI.unescape_html(Sanitize.fragment(CGI.escape_html(md.render(content)), EVIL_TAGS)).strip
end end
def twitter_markdown(content) 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 CGI.unescape_html(Sanitize.fragment(CGI.escape_html(md.render(content)), EVIL_TAGS)).strip
end end
def question_markdown(content) def question_markdown(content)
md = Redcarpet::Markdown.new(QuestionMarkdown.new, MARKDOWN_OPTS) renderer = QuestionMarkdown.new
Sanitize.fragment(md.render(content), EVIL_TAGS).html_safe 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 end
def raw_markdown(content) 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 raw md.render content
end end
def get_markdown(path, relative_to = Rails.root) def get_markdown(path, relative_to = Rails.root)
begin
File.read relative_to.join(path) File.read relative_to.join(path)
rescue Errno::ENOENT rescue Errno::ENOENT
"# Error reading #{relative_to.join(path)}" "# Error reading #{relative_to.join(path)}"
end end
end
def markdown_io(path, relative_to = Rails.root) def markdown_io(path, relative_to = Rails.root)
markdown get_markdown path, relative_to markdown get_markdown path, relative_to

View File

@ -18,10 +18,6 @@ class FlavoredMarkdown < Redcarpet::Render::HTML
paragraph text paragraph text
end end
def paragraph(text)
"<p>#{text}</p>"
end
def raw_html(raw_html) def raw_html(raw_html)
Rack::Utils.escape_html raw_html Rack::Utils.escape_html raw_html
end end

View File

@ -6,9 +6,7 @@ class QuestionMarkdown < Redcarpet::Render::StripDown
include Rails.application.routes.url_helpers include Rails.application.routes.url_helpers
include SharedMarkers include SharedMarkers
def paragraph(text) def paragraph(text) = "<p>#{text.gsub("\n", '<br>')}</p>"
"<p>#{text}</p>"
end
def link(link, _title, _content) def link(link, _title, _content)
process_link(link) process_link(link)

View File

@ -1,6 +1,18 @@
require 'redcarpet/render_strip' # frozen_string_literal: true
require "redcarpet/render_strip"
MARKDOWN_OPTS = { MARKDOWN_OPTS = {
no_intra_emphasis: true,
tables: true,
fenced_code_blocks: true,
autolink: true,
disable_indented_code_blocks: true,
strikethrough: true,
superscript: false,
}.freeze
MARKDOWN_RENDERER_OPTS = {
filter_html: true, filter_html: true,
escape_html: true, escape_html: true,
no_images: true, no_images: true,
@ -8,25 +20,9 @@ MARKDOWN_OPTS = {
safe_links_only: true, safe_links_only: true,
xhtml: false, xhtml: false,
hard_wrap: true, hard_wrap: true,
no_intra_emphasis: true, }.freeze
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,
disable_indented_code_blocks: true,
strikethrough: true,
superscript: false
}
ALLOWED_HOSTS_IN_MARKDOWN = [ ALLOWED_HOSTS_IN_MARKDOWN = [
APP_CONFIG['hostname'], APP_CONFIG["hostname"],
*APP_CONFIG['allowed_hosts_in_markdown'] *APP_CONFIG["allowed_hosts_in_markdown"]
] ].freeze

View File

@ -567,7 +567,6 @@ en:
formatting: formatting:
body_html: | body_html: |
<p>%{app_name} uses <b>Markdown</b> for formatting</p> <p>%{app_name} uses <b>Markdown</b> for formatting</p>
<p>A blank line starts a new paragraph</p>
<p><code>*italic text*</code> for <i>italic text</i></p> <p><code>*italic text*</code> for <i>italic text</i></p>
<p><code>**bold text**</code> for <b>bold text</b></p> <p><code>**bold text**</code> for <b>bold text</b></p>
<p><code>[link](https://example.com)</code> for <a href="https://example.com">link</a></p> <p><code>[link](https://example.com)</code> for <a href="https://example.com">link</a></p>

View File

@ -31,6 +31,10 @@ describe MarkdownHelper, type: :helper do
it "should escape HTML tags" do it "should escape HTML tags" do
expect(markdown("I'm <h1>a test</h1>")).to eq("<p>I'm &lt;h1&gt;a test&lt;/h1&gt;</p>") expect(markdown("I'm <h1>a test</h1>")).to eq("<p>I'm &lt;h1&gt;a test&lt;/h1&gt;</p>")
end end
it "should turn line breaks into <br> tags" do
expect(markdown("Some\ntext")).to eq("<p>Some<br>\ntext</p>")
end
end end
describe "#strip_markdown" do describe "#strip_markdown" do
@ -70,6 +74,10 @@ describe MarkdownHelper, type: :helper do
it "should not process invalid links" do it "should not process invalid links" do
expect(question_markdown("https://example.com/example.質問")).to eq("<p>https://example.com/example.質問</p>") expect(question_markdown("https://example.com/example.質問")).to eq("<p>https://example.com/example.質問</p>")
end end
it "should turn line breaks into <br> tags" do
expect(markdown("Some\ntext")).to eq("<p>Some<br>\ntext</p>")
end
end end
describe "#raw_markdown" do describe "#raw_markdown" do