From 0b16ceb36b3ff85583a8fde903e32f0c6eb4c2ca Mon Sep 17 00:00:00 2001
From: Jens Kraemer
Date: Fri, 25 Oct 2019 06:34:50 +0000
Subject: [PATCH] CommonMark Markdown text formatter
---
Gemfile | 7 +
lib/redmine.rb | 8 +
.../common_mark/external_links_filter.rb | 50 +++
.../common_mark/fixup_auto_links_filter.rb | 55 ++++
.../wiki_formatting/common_mark/formatter.rb | 68 ++++
lib/redmine/wiki_formatting/common_mark/helper.rb | 54 +++
.../wiki_formatting/common_mark/html_parser.rb | 27 ++
.../wiki_formatting/common_mark/markdown_filter.rb | 60 ++++
.../common_mark/sanitization_filter.rb | 87 +++++
.../common_mark/syntax_highlight_filter.rb | 52 +++
public/help/en/wiki_syntax_common_mark.html | 87 +++++
.../help/en/wiki_syntax_detailed_common_mark.html | 361 +++++++++++++++++++++
public/help/wiki_syntax_detailed.css | 3 +
.../common_mark/application_helper_test.rb | 49 +++
.../common_mark/external_links_filter_test.rb | 35 ++
.../common_mark/fixup_auto_links_filter_test.rb | 38 +++
.../wiki_formatting/common_mark/formatter_test.rb | 270 +++++++++++++++
.../common_mark/markdown_filter_test.rb | 22 ++
.../common_mark/sanitization_filter_test.rb | 193 +++++++++++
.../common_mark/syntax_highlight_filter_test.rb | 61 ++++
20 files changed, 1587 insertions(+)
create mode 100644 lib/redmine/wiki_formatting/common_mark/external_links_filter.rb
create mode 100644 lib/redmine/wiki_formatting/common_mark/fixup_auto_links_filter.rb
create mode 100644 lib/redmine/wiki_formatting/common_mark/formatter.rb
create mode 100644 lib/redmine/wiki_formatting/common_mark/helper.rb
create mode 100644 lib/redmine/wiki_formatting/common_mark/html_parser.rb
create mode 100644 lib/redmine/wiki_formatting/common_mark/markdown_filter.rb
create mode 100644 lib/redmine/wiki_formatting/common_mark/sanitization_filter.rb
create mode 100644 lib/redmine/wiki_formatting/common_mark/syntax_highlight_filter.rb
create mode 100644 public/help/en/wiki_syntax_common_mark.html
create mode 100644 public/help/en/wiki_syntax_detailed_common_mark.html
create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/application_helper_test.rb
create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/external_links_filter_test.rb
create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/fixup_auto_links_filter_test.rb
create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb
create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/markdown_filter_test.rb
create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/sanitization_filter_test.rb
create mode 100644 test/unit/lib/redmine/wiki_formatting/common_mark/syntax_highlight_filter_test.rb
diff --git a/Gemfile b/Gemfile
index 587bdb101..fd96b8987 100644
--- a/Gemfile
+++ b/Gemfile
@@ -39,6 +39,13 @@ group :markdown do
gem "redcarpet", "~> 3.5.0"
end
+# Optional CommonMark support, not for JRuby
+group :common_mark do
+ gem "html-pipeline", "~> 2.12"
+ gem "commonmarker", "~> 0.20"
+ gem "sanitize", "~> 5.1"
+end
+
# Include database gems for the adapters found in the database
# configuration file
require 'erb'
diff --git a/lib/redmine.rb b/lib/redmine.rb
index 31a62c0a8..19f57edc6 100644
--- a/lib/redmine.rb
+++ b/lib/redmine.rb
@@ -29,6 +29,11 @@ begin
rescue LoadError
# Redcarpet is not available
end
+begin
+ require 'commonmarker' unless Object.const_defined?(:CommonMarker)
+rescue LoadError
+ # CommonMarker is not available
+end
require 'redmine/acts/positioned'
@@ -328,6 +333,9 @@ end
Redmine::WikiFormatting.map do |format|
format.register :textile
format.register :markdown if Object.const_defined?(:Redcarpet)
+ if Object.const_defined?(:CommonMarker)
+ format.register :common_mark, label: 'CommonMark Markdown (GitHub Flavored)'
+ end
end
ActionView::Template.register_template_handler :rsb, Redmine::Views::ApiTemplateHandler
diff --git a/lib/redmine/wiki_formatting/common_mark/external_links_filter.rb b/lib/redmine/wiki_formatting/common_mark/external_links_filter.rb
new file mode 100644
index 000000000..4e575e3d4
--- /dev/null
+++ b/lib/redmine/wiki_formatting/common_mark/external_links_filter.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+# Redmine - project management software
+# Copyright (C) 2006-2019 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require 'uri'
+
+module Redmine
+ module WikiFormatting
+ module CommonMark
+
+ # adds class="external" to external links, and class="email" to mailto
+ # links
+ class ExternalLinksFilter < HTML::Pipeline::Filter
+ def call
+ doc.search("a").each do |node|
+ url = node["href"]
+ next unless url
+ next if url.starts_with?("/") || url.starts_with?("#") || !url.include?(':')
+
+ scheme = URI.parse(url).scheme
+ next if scheme.blank?
+
+ klass = node["class"].presence
+ node["class"] = [
+ klass,
+ (scheme == "mailto" ? "email" : "external")
+ ].compact.join " "
+ end
+ doc
+ end
+ end
+
+ end
+ end
+end
diff --git a/lib/redmine/wiki_formatting/common_mark/fixup_auto_links_filter.rb b/lib/redmine/wiki_formatting/common_mark/fixup_auto_links_filter.rb
new file mode 100644
index 000000000..fae8dc7a0
--- /dev/null
+++ b/lib/redmine/wiki_formatting/common_mark/fixup_auto_links_filter.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+# Redmine - project management software
+# Copyright (C) 2006-2019 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+module Redmine
+ module WikiFormatting
+ module CommonMark
+
+ # fixes:
+ # - autolinked email addresses that are actually references to users:
+ # user:user@example.org
+ # @user@example.org
+ # - autolinked hi res image names that look like email addresses:
+ # printscreen@2x.png
+ class FixupAutoLinksFilter < HTML::Pipeline::Filter
+ USER_LINK_PREFIX = /(@|user:)\z/.freeze
+ HIRES_IMAGE = /.+@\dx\.(bmp|gif|jpg|jpe|jpeg|png)\z/.freeze
+
+ def call
+ doc.search("a").each do |node|
+ unless url = node['href'] and url.starts_with?('mailto:')
+ next
+ end
+
+ if (p = node.previous and p.text? and
+ p.text =~ USER_LINK_PREFIX) or
+ (node.text =~ HIRES_IMAGE)
+
+ node.replace node.text
+ end
+ end
+ doc
+ end
+ end
+
+ end
+ end
+end
+
diff --git a/lib/redmine/wiki_formatting/common_mark/formatter.rb b/lib/redmine/wiki_formatting/common_mark/formatter.rb
new file mode 100644
index 000000000..4960b187d
--- /dev/null
+++ b/lib/redmine/wiki_formatting/common_mark/formatter.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+# Redmine - project management software
+# Copyright (C) 2006-2019 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require 'html/pipeline'
+
+module Redmine
+ module WikiFormatting
+ module CommonMark
+
+ # configuration of the rendering pipeline
+ PIPELINE_CONFIG = {
+ # https://github.com/gjtorikian/commonmarker#extensions
+ commonmarker_extensions: %i(
+ table
+ strikethrough
+ tagfilter
+ autolink
+ ).freeze,
+
+ # https://github.com/gjtorikian/commonmarker#parse-options
+ commonmarker_parse_options: %i(
+ FOOTNOTES
+ STRIKETHROUGH_DOUBLE_TILDE
+ UNSAFE
+ VALIDATE_UTF8
+ ).freeze,
+
+ # https://github.com/gjtorikian/commonmarker#render-options
+ commonmarker_render_options: %i(
+ UNSAFE
+ ).freeze,
+ }.freeze
+
+
+ MarkdownPipeline = HTML::Pipeline.new [
+ MarkdownFilter,
+ SanitizationFilter,
+ SyntaxHighlightFilter,
+ FixupAutoLinksFilter,
+ ExternalLinksFilter,
+ ], PIPELINE_CONFIG
+
+ class Formatter < Redmine::WikiFormatting::Markdown::Formatter
+ def to_html(*args)
+ result = MarkdownPipeline.call @text
+ result[:output].to_s
+ end
+ end
+
+ end
+ end
+end
diff --git a/lib/redmine/wiki_formatting/common_mark/helper.rb b/lib/redmine/wiki_formatting/common_mark/helper.rb
new file mode 100644
index 000000000..70aa4bc2b
--- /dev/null
+++ b/lib/redmine/wiki_formatting/common_mark/helper.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+# Redmine - project management software
+# Copyright (C) 2006-2019 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+module Redmine
+ module WikiFormatting
+ module CommonMark
+ module Helper
+ include Redmine::WikiFormatting::Markdown::Helper
+
+ def wikitoolbar_for(field_id, preview_url = preview_text_path)
+ heads_for_wiki_formatter
+ help_file = "/help/#{current_language.to_s.downcase}/wiki_syntax_common_mark.html"
+ # fall back to the english help page if there is none for the current
+ # language
+ unless File.readable? Rails.root.join("public", help_file)
+ help_file = "/help/en/wiki_syntax_common_mark.html"
+ end
+ url = "#{Redmine::Utils.relative_url_root}#{help_file}"
+ javascript_tag("var wikiToolbar = new jsToolBar(document.getElementById('#{field_id}')); wikiToolbar.setHelpLink('#{escape_javascript url}'); wikiToolbar.setPreviewUrl('#{escape_javascript preview_url}'); wikiToolbar.draw();")
+ end
+
+ # removes the 'underline' icon from the markdown toolbar since there
+ # is no such thing in CommonMark
+ def heads_for_wiki_formatter
+ unless @common_mark_heads_for_wiki_formatter_included
+ super
+ content_for :header_tags do
+ javascript_tag(%[delete jsToolBar.prototype.elements.ins;])
+ end
+ @common_mark_heads_for_wiki_formatter_included = true
+ end
+ end
+ end
+ end
+ end
+end
+
diff --git a/lib/redmine/wiki_formatting/common_mark/html_parser.rb b/lib/redmine/wiki_formatting/common_mark/html_parser.rb
new file mode 100644
index 000000000..4548ecc28
--- /dev/null
+++ b/lib/redmine/wiki_formatting/common_mark/html_parser.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+# Redmine - project management software
+# Copyright (C) 2006-2019 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+module Redmine
+ module WikiFormatting
+ module CommonMark
+ HtmlParser = Redmine::WikiFormatting::Markdown::HtmlParser
+ end
+ end
+end
diff --git a/lib/redmine/wiki_formatting/common_mark/markdown_filter.rb b/lib/redmine/wiki_formatting/common_mark/markdown_filter.rb
new file mode 100644
index 000000000..6f6cdfb47
--- /dev/null
+++ b/lib/redmine/wiki_formatting/common_mark/markdown_filter.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+# Redmine - project management software
+# Copyright (C) 2006-2019 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+module Redmine
+ module WikiFormatting
+ module CommonMark
+
+ # Converts Markdown to HTML using CommonMarker
+ #
+ # We do not use the stock HTML::Pipeline::MarkdownFilter because this
+ # does not allow for straightforward configuration of render and parsing
+ # options
+ class MarkdownFilter < HTML::Pipeline::TextFilter
+ def initialize(text, context = nil, result = nil)
+ super text, context, result
+ @text = @text.delete "\r"
+ end
+
+ def call
+ doc = CommonMarker.render_doc(@text, parse_options, extensions)
+ html = doc.to_html render_options, extensions
+ html.rstrip!
+ html
+ end
+
+ private
+
+ def extensions
+ context.fetch :commonmarker_extensions, []
+ end
+
+ def parse_options
+ context.fetch :commonmarker_parse_options, :DEFAULT
+ end
+
+ def render_options
+ context.fetch :commonmarker_render_options, :DEFAULT
+ end
+ end
+
+ end
+ end
+end
diff --git a/lib/redmine/wiki_formatting/common_mark/sanitization_filter.rb b/lib/redmine/wiki_formatting/common_mark/sanitization_filter.rb
new file mode 100644
index 000000000..98a049070
--- /dev/null
+++ b/lib/redmine/wiki_formatting/common_mark/sanitization_filter.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+# Redmine - project management software
+# Copyright (C) 2006-2019 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+module Redmine
+ module WikiFormatting
+ module CommonMark
+
+ # sanitizes rendered HTML using the Sanitize gem
+ class SanitizationFilter < HTML::Pipeline::SanitizationFilter
+ def whitelist
+ @@whitelist ||= customize_whitelist(super.deep_dup)
+ end
+
+ private
+
+ # customizes the whitelist defined in
+ # https://github.com/jch/html-pipeline/blob/master/lib/html/pipeline/sanitization_filter.rb
+ def customize_whitelist(whitelist)
+ # Disallow `name` attribute globally, allow on `a`
+ whitelist[:attributes][:all].delete("name")
+ whitelist[:attributes]["a"].push("name")
+
+ # allow class on code tags (this holds the language info from fenced
+ # code bocks and has the format language-foo)
+ whitelist[:attributes]["code"] = %w(class)
+ whitelist[:transformers].push lambda{|env|
+ node = env[:node]
+ return unless node.name == "code"
+ return unless node.has_attribute?("class")
+ unless node["class"] =~ /\Alanguage-(\w+)\z/
+ node.remove_attribute("class")
+ end
+ }
+
+ # Allow table cell alignment by style attribute
+ #
+ # Only necessary if we used the TABLE_PREFER_STYLE_ATTRIBUTES
+ # commonmarker option (which we do not, currently).
+ # By default, the align attribute is used (which is allowed on all
+ # elements).
+ # whitelist[:attributes]["th"] = %w(style)
+ # whitelist[:attributes]["td"] = %w(style)
+ # whitelist[:css] = { properties: ["text-align"] }
+
+ # Allow `id` in a and li elements for footnotes
+ # and remove any `id` properties not matching for footnotes
+ whitelist[:attributes]["a"].push "id"
+ whitelist[:attributes]["li"] = %w(id)
+ whitelist[:transformers].push lambda{|env|
+ node = env[:node]
+ return unless node.name == "a" || node.name == "li"
+ return unless node.has_attribute?("id")
+ return if node.name == "a" && node["id"] =~ /\Afnref\d+\z/
+ return if node.name == "li" && node["id"] =~ /\Afn\d+\z/
+ node.remove_attribute("id")
+ }
+
+ # allw the same set of URL schemes for links as is the default in
+ # Redmine::Helpers::URL#uri_with_safe_scheme?
+ whitelist[:protocols][:a] = [
+ 'http', 'https', 'ftp', 'mailto', :relative
+ ]
+
+ whitelist
+ end
+ end
+
+ end
+ end
+end
diff --git a/lib/redmine/wiki_formatting/common_mark/syntax_highlight_filter.rb b/lib/redmine/wiki_formatting/common_mark/syntax_highlight_filter.rb
new file mode 100644
index 000000000..3f46f466b
--- /dev/null
+++ b/lib/redmine/wiki_formatting/common_mark/syntax_highlight_filter.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+# Redmine - project management software
+# Copyright (C) 2006-2019 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+module Redmine
+ module WikiFormatting
+ module CommonMark
+
+ # Redmine Syntax highlighting for
+ # blocks as generated by commonmarker
+ class SyntaxHighlightFilter < HTML::Pipeline::Filter
+ def call
+ doc.search("pre > code").each do |node|
+ next unless lang = node["class"].presence
+ next unless lang =~ /\Alanguage-(\w+)\z/
+
+ lang = $1
+ text = node.inner_text
+
+ if Redmine::SyntaxHighlighting.language_supported?(lang)
+ html = Redmine::SyntaxHighlighting.highlight_by_language(text, lang)
+ next if html.nil?
+ node.inner_html = html
+ node["class"] = "#{lang} syntaxhl"
+ else
+ # unsupported language, strip out the code tag
+ node.parent.inner_html = text
+ end
+ end
+ doc
+ end
+ end
+
+ end
+ end
+end
diff --git a/public/help/en/wiki_syntax_common_mark.html b/public/help/en/wiki_syntax_common_mark.html
new file mode 100644
index 000000000..bda25b13b
--- /dev/null
+++ b/public/help/en/wiki_syntax_common_mark.html
@@ -0,0 +1,87 @@
+
+
+
+Wiki formatting
+
+
+
+
+
Wiki Syntax Quick Reference (CommonMark Markdown (GitHub Flavored))
For things such as headlines, bold, tables, lists, Redmine supports Markdown syntax according to CommonMark including some extensions commonly referred to as GitHub flavored Markdown. See the GitHub Flavored Markdown Spec for information on using any of these features. A few samples are included below, but the engine is capable of much more of that.
 displays an image located at image_url (markdown syntax)
+
If you have an image attached to your wiki page, it can be displayed inline using its filename: 
+
Images in your computer's clipboard can be pasted directly using Ctrl-v or Command-v.
+
Image files can be dragged onto the text area in order to be uploaded and embedded.
+
+
+
Headings
+
+
+# Heading
+## Subheading
+### Subsubheading
+
+
+
Redmine assigns an anchor to each of those headings thus you can link to them with "#Heading", "#Subheading" and so forth.
+
+
+
Blockquotes
+
+
Start the paragraph with >
+
+
+> Rails is a full-stack framework for developing database-backed web applications according to the Model-View-Control pattern.
+To go live, all you need to add is a database and a web server.
+
+
+
Display:
+
+
+
Rails is a full-stack framework for developing database-backed web applications according to the Model-View-Control pattern. To go live, all you need to add is a database and a web server.
+
+
+
+
Table of content
+
+
+{{toc}} => left aligned toc
+{{>toc}} => right aligned toc
+
+
+
Horizontal Rule
+
+
+---
+
+
+
Macros
+
+
Redmine has the following builtin macros:
+
+
+
+
hello_world
+
Sample macro.
+
+
macro_list
+
Displays a list of all available macros, including description if available.
+
+
child_pages
+
Displays a list of child pages. With no argument, it displays the child pages of the current wiki page. Examples:
+
{{child_pages}} -- can be used from a wiki page only
+{{child_pages(depth=2)}} -- display 2 levels nesting only
+
+
include
+
Include a wiki page. Example:
+
{{include(Foo)}}
+
or to include a page of a specific project wiki:
+
{{include(projectname:Foo)}}
+
+
collapse
+
Inserts of collapsed block of text. Example:
+
{{collapse(View details...)
+This is a block of text that is collapsed by default.
+It can be expanded by clicking a link.
+}}
+
+
thumbnail
+
Displays a clickable thumbnail of an attached image. Examples:
Default code highlighting relies on Rouge, a syntax highlighting library written in pure Ruby. It supports many commonly used languages such as c, cpp (c++), csharp (c#, cs), css, diff (patch, udiff), go (golang), groovy, html, java, javascript (js), kotlin, objective_c (objc), perl (pl), php, python (py), r, ruby (rb), sass, scala, shell (bash, zsh, ksh, sh), sql, swift, xml and yaml (yml) languages, where the names inside parentheses are aliases. Please refer to https://www.redmine.org/projects/redmine/wiki/RedmineCodeHighlightingLanguages for the full list of supported languages.
+
+
You can highlight code at any place that supports wiki formatting using this syntax (note that the language name or alias is case-insensitive):
+
+
+```ruby
+ Place your code here.
+```
+
+
+
Example:
+
+
# The Greeter class
+classGreeter
+ definitialize(name)
+ @name=name.capitalize
+ end
+
+ defsalute
+ puts"Hello #{@name}!"
+ end
+end
+
+
+
Raw HTML
+
+
You may use raw HTML for more complex formatting tasks, i.e. complex tables with cells spanning multiple rows or columns:
", filter(format(text))
+ text = "@user@example.org"
+ assert_equal "
#{text}
", filter(format(text))
+ end
+
+ def test_should_fixup_autolinked_hires_files
+ text = "printscreen@2x.png"
+ assert_equal "
#{text}
", filter(format(text))
+ end
+
+end
+end # if Object.const_defined?(:CommonMarker)
+
+
+
diff --git a/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb b/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb
new file mode 100644
index 000000000..948981e70
--- /dev/null
+++ b/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb
@@ -0,0 +1,270 @@
+# frozen_string_literal: true
+
+# Redmine - project management software
+# Copyright (C) 2006-2019 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require File.expand_path('../../../../../../test_helper', __FILE__)
+
+class Redmine::WikiFormatting::CommonMark::FormatterTest < ActionView::TestCase
+ if Object.const_defined?(:CommonMarker)
+
+ def setup
+ @formatter = Redmine::WikiFormatting::CommonMark::Formatter
+ end
+
+ def format(text)
+ @formatter.new(text).to_html
+ end
+
+ def test_should_render_hard_breaks
+ html ="
", format("foo_bar_baz")
+ end
+
+ def test_wiki_links_should_be_preserved
+ text = 'This is a wiki link: [[Foo]]'
+ assert_include '[[Foo]]', format(text)
+ end
+
+ def test_redmine_links_with_double_quotes_should_be_preserved
+ text = 'This is a redmine link: version:"1.0"'
+ assert_include 'version:"1.0"', format(text)
+ end
+
+ def test_links_by_id_should_be_preserved
+ text = "[project#3]"
+ assert_equal "
#{text}
", format(text)
+ end
+
+ def test_links_to_users_should_be_preserved
+ text = "[@login]"
+ assert_equal "
#{text}
", format(text)
+ text = "[user:login]"
+ assert_equal "
#{text}
", format(text)
+ text = "user:user@example.org"
+ assert_equal "
#{text}
", format(text)
+ text = "[user:user@example.org]"
+ assert_equal "
#{text}
", format(text)
+ text = "@user@example.org"
+ assert_equal "
#{text}
", format(text)
+ text = "[@user@example.org]"
+ assert_equal "
#{text}
", format(text)
+ end
+
+ def test_files_with_at_should_not_end_up_as_mailto_links
+ text = "printscreen@2x.png"
+ assert_equal "
#{text}
", format(text)
+ text = "[printscreen@2x.png]"
+ assert_equal "
#{text}
", format(text)
+ end
+
+ def test_should_support_syntax_highlight
+ text = <<-STR
+~~~ruby
+def foo
+end
+~~~
+STR
+ assert_select_in format(text), 'pre code.ruby.syntaxhl' do
+ assert_select 'span.k', :text => 'def'
+ end
+ end
+
+ def test_should_not_allow_invalid_language_for_code_blocks
+ text = <<-STR
+~~~foo
+test
+~~~
+STR
+ assert_equal "
test\n
", format(text)
+ end
+
+ def test_external_links_should_have_external_css_class
+ text = 'This is a [link](http://example.net/)'
+ assert_equal '
', format(text)
+ end
+
+ def test_markdown_should_not_require_surrounded_empty_line
+ text = <<-STR
+This is a list:
+* One
+* Two
+STR
+ assert_equal "
This is a list:
\n
\n
One
\n
Two
\n
", format(text)
+ end
+
+ def test_footnotes
+ text = <<-STR
+This is some text[^1].
+
+[^1]: This is the foot note
+STR
+
+ expected = <<-EXPECTED
+