Feature #32424 » 0001-Adds-CommonMark-Markdown-GitHub-Flavored-as-third-te.patch
Gemfile | ||
---|---|---|
46 | 46 |
gem 'redcarpet', '~> 3.5.1' |
47 | 47 |
end |
48 | 48 | |
49 |
# Optional CommonMark support, not for JRuby |
|
50 |
group :common_mark do |
|
51 |
gem "html-pipeline", "~> 2.12" |
|
52 |
gem "commonmarker", "~> 0.20" |
|
53 |
gem "sanitize", "~> 5.1" |
|
54 |
end |
|
55 | ||
49 | 56 |
# Include database gems for the adapters found in the database |
50 | 57 |
# configuration file |
51 | 58 |
require 'erb' |
lib/redmine.rb | ||
---|---|---|
29 | 29 |
rescue LoadError |
30 | 30 |
# Redcarpet is not available |
31 | 31 |
end |
32 |
begin |
|
33 |
require 'commonmarker' unless Object.const_defined?(:CommonMarker) |
|
34 |
rescue LoadError |
|
35 |
# CommonMarker is not available |
|
36 |
end |
|
32 | 37 | |
33 | 38 |
require 'redmine/acts/positioned' |
34 | 39 | |
... | ... | |
442 | 447 |
Redmine::WikiFormatting.map do |format| |
443 | 448 |
format.register :textile |
444 | 449 |
format.register :markdown if Object.const_defined?(:Redcarpet) |
450 |
if Object.const_defined?(:CommonMarker) |
|
451 |
format.register :common_mark, label: 'CommonMark Markdown (GitHub Flavored)' |
|
452 |
end |
|
445 | 453 |
end |
446 | 454 | |
447 | 455 |
ActionView::Template.register_template_handler :rsb, Redmine::Views::ApiTemplateHandler |
lib/redmine/wiki_formatting/common_mark/external_links_filter.rb | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
# Redmine - project management software |
|
4 |
# Copyright (C) 2006-2021 Jean-Philippe Lang |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | ||
20 |
require 'uri' |
|
21 | ||
22 |
module Redmine |
|
23 |
module WikiFormatting |
|
24 |
module CommonMark |
|
25 |
# adds class="external" to external links, and class="email" to mailto |
|
26 |
# links |
|
27 |
class ExternalLinksFilter < HTML::Pipeline::Filter |
|
28 |
def call |
|
29 |
doc.search("a").each do |node| |
|
30 |
url = node["href"] |
|
31 |
next unless url |
|
32 |
next if url.starts_with?("/") || url.starts_with?("#") || !url.include?(':') |
|
33 | ||
34 |
scheme = URI.parse(url).scheme |
|
35 |
next if scheme.blank? |
|
36 | ||
37 |
klass = node["class"].presence |
|
38 |
node["class"] = [ |
|
39 |
klass, |
|
40 |
(scheme == "mailto" ? "email" : "external") |
|
41 |
].compact.join " " |
|
42 |
end |
|
43 |
doc |
|
44 |
end |
|
45 |
end |
|
46 |
end |
|
47 |
end |
|
48 |
end |
lib/redmine/wiki_formatting/common_mark/fixup_auto_links_filter.rb | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
# Redmine - project management software |
|
4 |
# Copyright (C) 2006-2021 Jean-Philippe Lang |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | ||
20 |
module Redmine |
|
21 |
module WikiFormatting |
|
22 |
module CommonMark |
|
23 |
# fixes: |
|
24 |
# - autolinked email addresses that are actually references to users: |
|
25 |
# user:<a href="mailto:user@example.org">user@example.org</a> |
|
26 |
# @<a href="mailto:user@example.org">user@example.org</a> |
|
27 |
# - autolinked hi res image names that look like email addresses: |
|
28 |
# <a href="mailto:printscreen@2x.png">printscreen@2x.png</a> |
|
29 |
class FixupAutoLinksFilter < HTML::Pipeline::Filter |
|
30 |
USER_LINK_PREFIX = /(@|user:)\z/.freeze |
|
31 |
HIRES_IMAGE = /.+@\dx\.(bmp|gif|jpg|jpe|jpeg|png)\z/.freeze |
|
32 | ||
33 |
def call |
|
34 |
doc.search("a").each do |node| |
|
35 |
unless (url = node['href']) && url.starts_with?('mailto:') |
|
36 |
next |
|
37 |
end |
|
38 | ||
39 |
if ((p = node.previous) && p.text? && |
|
40 |
p.text =~(USER_LINK_PREFIX)) || |
|
41 |
(node.text =~ HIRES_IMAGE) |
|
42 | ||
43 |
node.replace node.text |
|
44 |
end |
|
45 |
end |
|
46 |
doc |
|
47 |
end |
|
48 |
end |
|
49 |
end |
|
50 |
end |
|
51 |
end |
lib/redmine/wiki_formatting/common_mark/formatter.rb | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
# Redmine - project management software |
|
4 |
# Copyright (C) 2006-2021 Jean-Philippe Lang |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | ||
20 |
require 'html/pipeline' |
|
21 | ||
22 |
module Redmine |
|
23 |
module WikiFormatting |
|
24 |
module CommonMark |
|
25 |
# configuration of the rendering pipeline |
|
26 |
PIPELINE_CONFIG = { |
|
27 |
# https://github.com/gjtorikian/commonmarker#extensions |
|
28 |
commonmarker_extensions: [ |
|
29 |
:table, |
|
30 |
:strikethrough, |
|
31 |
:tagfilter, |
|
32 |
:autolink |
|
33 |
].freeze, |
|
34 | ||
35 |
# https://github.com/gjtorikian/commonmarker#parse-options |
|
36 |
commonmarker_parse_options: [ |
|
37 |
:FOOTNOTES, |
|
38 |
:STRIKETHROUGH_DOUBLE_TILDE, |
|
39 |
:UNSAFE, |
|
40 |
:VALIDATE_UTF8 |
|
41 |
].freeze, |
|
42 | ||
43 |
# https://github.com/gjtorikian/commonmarker#render-options |
|
44 |
commonmarker_render_options: [ |
|
45 |
:UNSAFE |
|
46 |
].freeze, |
|
47 |
}.freeze |
|
48 | ||
49 |
MarkdownPipeline = HTML::Pipeline.new [ |
|
50 |
MarkdownFilter, |
|
51 |
SanitizationFilter, |
|
52 |
SyntaxHighlightFilter, |
|
53 |
FixupAutoLinksFilter, |
|
54 |
ExternalLinksFilter, |
|
55 |
], PIPELINE_CONFIG |
|
56 | ||
57 |
class Formatter < Redmine::WikiFormatting::Markdown::Formatter |
|
58 |
def to_html(*args) |
|
59 |
result = MarkdownPipeline.call @text |
|
60 |
result[:output].to_s |
|
61 |
end |
|
62 |
end |
|
63 |
end |
|
64 |
end |
|
65 |
end |
lib/redmine/wiki_formatting/common_mark/helper.rb | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
# Redmine - project management software |
|
4 |
# Copyright (C) 2006-2021 Jean-Philippe Lang |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | ||
20 |
module Redmine |
|
21 |
module WikiFormatting |
|
22 |
module CommonMark |
|
23 |
module Helper |
|
24 |
include Redmine::WikiFormatting::Markdown::Helper |
|
25 | ||
26 |
def wikitoolbar_for(field_id, preview_url = preview_text_path) |
|
27 |
heads_for_wiki_formatter |
|
28 |
help_file = "/help/#{current_language.to_s.downcase}/wiki_syntax_common_mark.html" |
|
29 |
# fall back to the english help page if there is none for the current |
|
30 |
# language |
|
31 |
unless File.readable? Rails.root.join("public", help_file) |
|
32 |
help_file = "/help/en/wiki_syntax_common_mark.html" |
|
33 |
end |
|
34 |
url = "#{Redmine::Utils.relative_url_root}#{help_file}" |
|
35 |
javascript_tag( |
|
36 |
"var wikiToolbar = new jsToolBar(document.getElementById('#{field_id}')); " \ |
|
37 |
"wikiToolbar.setHelpLink('#{escape_javascript url}'); " \ |
|
38 |
"wikiToolbar.setPreviewUrl('#{escape_javascript preview_url}'); " \ |
|
39 |
"wikiToolbar.draw();" |
|
40 |
) |
|
41 |
end |
|
42 | ||
43 |
# removes the 'underline' icon from the markdown toolbar since there |
|
44 |
# is no such thing in CommonMark |
|
45 |
def heads_for_wiki_formatter |
|
46 |
unless @common_mark_heads_for_wiki_formatter_included |
|
47 |
super |
|
48 |
content_for :header_tags do |
|
49 |
javascript_tag(%[delete jsToolBar.prototype.elements.ins;]) |
|
50 |
end |
|
51 |
@common_mark_heads_for_wiki_formatter_included = true |
|
52 |
end |
|
53 |
end |
|
54 |
end |
|
55 |
end |
|
56 |
end |
|
57 |
end |
lib/redmine/wiki_formatting/common_mark/html_parser.rb | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
# Redmine - project management software |
|
4 |
# Copyright (C) 2006-2021 Jean-Philippe Lang |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | ||
20 |
module Redmine |
|
21 |
module WikiFormatting |
|
22 |
module CommonMark |
|
23 |
HtmlParser = Redmine::WikiFormatting::Markdown::HtmlParser |
|
24 |
end |
|
25 |
end |
|
26 |
end |
lib/redmine/wiki_formatting/common_mark/markdown_filter.rb | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
# Redmine - project management software |
|
4 |
# Copyright (C) 2006-2021 Jean-Philippe Lang |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | ||
20 |
module Redmine |
|
21 |
module WikiFormatting |
|
22 |
module CommonMark |
|
23 |
# Converts Markdown to HTML using CommonMarker |
|
24 |
# |
|
25 |
# We do not use the stock HTML::Pipeline::MarkdownFilter because this |
|
26 |
# does not allow for straightforward configuration of render and parsing |
|
27 |
# options |
|
28 |
class MarkdownFilter < HTML::Pipeline::TextFilter |
|
29 |
def initialize(text, context = nil, result = nil) |
|
30 |
super text, context, result |
|
31 |
@text = @text.delete "\r" |
|
32 |
end |
|
33 | ||
34 |
def call |
|
35 |
doc = CommonMarker.render_doc(@text, parse_options, extensions) |
|
36 |
html = doc.to_html render_options, extensions |
|
37 |
html.rstrip! |
|
38 |
html |
|
39 |
end |
|
40 | ||
41 |
private |
|
42 | ||
43 |
def extensions |
|
44 |
context.fetch :commonmarker_extensions, [] |
|
45 |
end |
|
46 | ||
47 |
def parse_options |
|
48 |
context.fetch :commonmarker_parse_options, :DEFAULT |
|
49 |
end |
|
50 | ||
51 |
def render_options |
|
52 |
context.fetch :commonmarker_render_options, :DEFAULT |
|
53 |
end |
|
54 |
end |
|
55 |
end |
|
56 |
end |
|
57 |
end |
lib/redmine/wiki_formatting/common_mark/sanitization_filter.rb | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
# Redmine - project management software |
|
4 |
# Copyright (C) 2006-2021 Jean-Philippe Lang |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | ||
20 |
module Redmine |
|
21 |
module WikiFormatting |
|
22 |
module CommonMark |
|
23 |
# sanitizes rendered HTML using the Sanitize gem |
|
24 |
class SanitizationFilter < HTML::Pipeline::SanitizationFilter |
|
25 |
def whitelist |
|
26 |
@@whitelist ||= customize_whitelist(super.deep_dup) |
|
27 |
end |
|
28 | ||
29 |
private |
|
30 | ||
31 |
# customizes the whitelist defined in |
|
32 |
# https://github.com/jch/html-pipeline/blob/master/lib/html/pipeline/sanitization_filter.rb |
|
33 |
def customize_whitelist(whitelist) |
|
34 |
# Disallow `name` attribute globally, allow on `a` |
|
35 |
whitelist[:attributes][:all].delete("name") |
|
36 |
whitelist[:attributes]["a"].push("name") |
|
37 | ||
38 |
# allow class on code tags (this holds the language info from fenced |
|
39 |
# code bocks and has the format language-foo) |
|
40 |
whitelist[:attributes]["code"] = %w(class) |
|
41 |
whitelist[:transformers].push lambda{|env| |
|
42 |
node = env[:node] |
|
43 |
return unless node.name == "code" |
|
44 |
return unless node.has_attribute?("class") |
|
45 | ||
46 |
unless /\Alanguage-(\w+)\z/.match?(node["class"]) |
|
47 |
node.remove_attribute("class") |
|
48 |
end |
|
49 |
} |
|
50 | ||
51 |
# Allow table cell alignment by style attribute |
|
52 |
# |
|
53 |
# Only necessary if we used the TABLE_PREFER_STYLE_ATTRIBUTES |
|
54 |
# commonmarker option (which we do not, currently). |
|
55 |
# By default, the align attribute is used (which is allowed on all |
|
56 |
# elements). |
|
57 |
# whitelist[:attributes]["th"] = %w(style) |
|
58 |
# whitelist[:attributes]["td"] = %w(style) |
|
59 |
# whitelist[:css] = { properties: ["text-align"] } |
|
60 | ||
61 |
# Allow `id` in a and li elements for footnotes |
|
62 |
# and remove any `id` properties not matching for footnotes |
|
63 |
whitelist[:attributes]["a"].push "id" |
|
64 |
whitelist[:attributes]["li"] = %w(id) |
|
65 |
whitelist[:transformers].push lambda{|env| |
|
66 |
node = env[:node] |
|
67 |
return unless node.name == "a" || node.name == "li" |
|
68 |
return unless node.has_attribute?("id") |
|
69 |
return if node.name == "a" && node["id"] =~ /\Afnref\d+\z/ |
|
70 |
return if node.name == "li" && node["id"] =~ /\Afn\d+\z/ |
|
71 | ||
72 |
node.remove_attribute("id") |
|
73 |
} |
|
74 | ||
75 |
# allow the same set of URL schemes for links as is the default in |
|
76 |
# Redmine::Helpers::URL#uri_with_safe_scheme? |
|
77 |
whitelist[:protocols]["a"]["href"] = [ |
|
78 |
'http', 'https', 'ftp', 'mailto', :relative |
|
79 |
] |
|
80 | ||
81 |
whitelist |
|
82 |
end |
|
83 |
end |
|
84 |
end |
|
85 |
end |
|
86 |
end |
lib/redmine/wiki_formatting/common_mark/syntax_highlight_filter.rb | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
# Redmine - project management software |
|
4 |
# Copyright (C) 2006-2021 Jean-Philippe Lang |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | ||
20 |
module Redmine |
|
21 |
module WikiFormatting |
|
22 |
module CommonMark |
|
23 |
# Redmine Syntax highlighting for <pre><code class="language-foo"> |
|
24 |
# blocks as generated by commonmarker |
|
25 |
class SyntaxHighlightFilter < HTML::Pipeline::Filter |
|
26 |
def call |
|
27 |
doc.search("pre > code").each do |node| |
|
28 |
next unless lang = node["class"].presence |
|
29 |
next unless lang =~ /\Alanguage-(\w+)\z/ |
|
30 | ||
31 |
lang = $1 |
|
32 |
text = node.inner_text |
|
33 | ||
34 |
if Redmine::SyntaxHighlighting.language_supported?(lang) |
|
35 |
html = Redmine::SyntaxHighlighting.highlight_by_language(text, lang) |
|
36 |
next if html.nil? |
|
37 | ||
38 |
node.inner_html = html |
|
39 |
node["class"] = "#{lang} syntaxhl" |
|
40 |
else |
|
41 |
# unsupported language, strip out the code tag |
|
42 |
node.parent.inner_html = text |
|
43 |
end |
|
44 |
end |
|
45 |
doc |
|
46 |
end |
|
47 |
end |
|
48 |
end |
|
49 |
end |
|
50 |
end |
public/help/en/wiki_syntax_common_mark.html | ||
---|---|---|
1 |
<html xmlns="http://www.w3.org/1999/xhtml"> |
|
2 |
<head> |
|
3 |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
|
4 |
<title>Wiki formatting</title> |
|
5 |
<link rel="stylesheet" type="text/css" href="../wiki_syntax.css" /> |
|
6 |
</head> |
|
7 |
<body> |
|
8 | ||
9 |
<h1>Wiki Syntax Quick Reference (CommonMark Markdown (GitHub Flavored))</h1> |
|
10 | ||
11 |
<table style="width:100%"> |
|
12 |
<tr><th colspan="3">Font Styles <span class="more_info">(<a href="wiki_syntax_detailed_common_mark.html#5" target="_blank">more</a>)</span></th></tr> |
|
13 |
<tr><th><img src="../../images/jstoolbar/bt_strong.png" style="border: 1px solid #bbb;" alt="Strong" /></th><td style="width:50%;">**Strong**</td><td style="width:50%;"><strong>Strong</strong></td></tr> |
|
14 |
<tr><th><img src="../../images/jstoolbar/bt_em.png" style="border: 1px solid #bbb;" alt="Italic" /></th><td>*Italic*</td><td><em>Italic</em></td></tr> |
|
15 |
<tr><th><img src="../../images/jstoolbar/bt_del.png" style="border: 1px solid #bbb;" alt="Deleted" /></th><td>~~Deleted~~</td><td><del>Deleted</del></td></tr> |
|
16 |
<tr><th><img src="../../images/jstoolbar/bt_code.png" style="border: 1px solid #bbb;" alt="Inline Code" /></th><td>`Inline Code`</td><td><code>Inline Code</code></td></tr> |
|
17 |
<tr><th><img src="../../images/jstoolbar/bt_pre.png" style="border: 1px solid #bbb;" alt="Preformatted text" /></th><td>```<br /> lines<br /> of code<br />```</td><td> |
|
18 |
<pre> |
|
19 |
lines |
|
20 |
of code |
|
21 |
</pre> |
|
22 |
</td></tr> |
|
23 | ||
24 |
<tr><th colspan="3">Highlighted code <span class="more_info">(<a href="wiki_syntax_detailed_common_mark.html#13" target="_blank">more</a>)</span></th></tr> |
|
25 |
<tr><th><img src="../../images/jstoolbar/bt_precode.png" style="border: 1px solid #bbb;" alt="Highlighted code" /></th><td>```ruby<br />3.times do<br /> puts 'Hello'<br />end<br />```</td><td> |
|
26 |
<pre><code class="ruby syntaxhl"><span class="mi">3</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span> |
|
27 |
<span class="nb">puts</span> <span class="s1">'Hello'</span> |
|
28 |
<span class="k">end</span> |
|
29 |
</code></pre> |
|
30 |
</td></tr> |
|
31 | ||
32 |
<tr><th colspan="3">Line breaks and Paragraphs</th></tr> |
|
33 |
<tr><th></th><td>An empty line<br><br>creates<br>a new paragraph.</td><td><p>An empty line</p><p>creates a new paragraph.</p></td></tr> |
|
34 |
<tr><th></th><td>End a line with a backslash\<br> or two spaces to insert a manual line break.</td><td><p>End a line with a backslash<br>or two spaces to insert a manual line break.</p></td></tr> |
|
35 | ||
36 |
<tr><th colspan="3">Lists</th></tr> |
|
37 |
<tr><th><img src="../../images/jstoolbar/bt_ul.png" style="border: 1px solid #bbb;" alt="Unordered list" /></th><td>* Item 1<br /> * Sub<br />* Item 2</td><td><ul><li>Item 1<ul><li>Sub</li></ul></li><li>Item 2</li></ul></td></tr> |
|
38 |
<tr><th><img src="../../images/jstoolbar/bt_ol.png" style="border: 1px solid #bbb;" alt="Ordered list" /></th><td>1. Item 1<br /> 1. Sub<br />2. Item 2</td><td><ol><li>Item 1<ol><li>Sub</li></ol></li><li>Item 2</li></ol></td></tr> |
|
39 | ||
40 |
<tr><th colspan="3">Headings <span class="more_info">(<a href="wiki_syntax_detailed_common_mark.html#8" target="_blank">more</a>)</span></th></tr> |
|
41 |
<tr><th><img src="../../images/jstoolbar/bt_h1.png" style="border: 1px solid #bbb;" alt="Heading 1" /></th><td># Title 1</td><td><h1>Title 1</h1></td></tr> |
|
42 |
<tr><th><img src="../../images/jstoolbar/bt_h2.png" style="border: 1px solid #bbb;" alt="Heading 2" /></th><td>## Title 2</td><td><h2>Title 2</h2></td></tr> |
|
43 |
<tr><th><img src="../../images/jstoolbar/bt_h3.png" style="border: 1px solid #bbb;" alt="Heading 3" /></th><td>### Title 3</td><td><h3>Title 3</h3></td></tr> |
|
44 | ||
45 |
<tr><th colspan="3">Links <span class="more_info">(<a href="wiki_syntax_detailed_common_mark.html#4" target="_blank">more</a>)</span></th></tr> |
|
46 |
<tr><th></th><td>www.foo.bar</td><td><a href="#">www.foo.bar</a></td></tr> |
|
47 |
<tr><th></th><td>http://foo.bar</td><td><a href="#">http://foo.bar</a></td></tr> |
|
48 |
<tr><th></th><td>[Foo](http://foo.bar)</td><td><a href="#">Foo</a></td></tr> |
|
49 | ||
50 |
<tr><th colspan="3">Redmine links <span class="more_info">(<a href="wiki_syntax_detailed_common_mark.html#3" target="_blank">more</a>)</span></th></tr> |
|
51 |
<tr><th><img src="../../images/jstoolbar/bt_link.png" style="border: 1px solid #bbb;" alt="Link to a Wiki page" /></th><td>[[Wiki page]]</td><td><a href="#">Wiki page</a></td></tr> |
|
52 |
<tr><th></th><td>Issue #12</td><td>Issue <a href="#">#12</a></td></tr> |
|
53 |
<tr><th></th><td>##12</td><td><a href="#">Bug #12</a>: The issue subject</td></tr> |
|
54 |
<tr><th></th><td>Revision r43</td><td>Revision <a href="#">r43</a></td></tr> |
|
55 |
<tr><th></th><td>commit:f30e13e43</td><td><a href="#">f30e13e4</a></td></tr> |
|
56 |
<tr><th></th><td>source:some/file</td><td><a href="#">source:some/file</a></td></tr> |
|
57 | ||
58 |
<tr><th colspan="3">Inline images <span class="more_info">(<a href="wiki_syntax_detailed_common_mark.html#7" target="_blank">more</a>)</span></th></tr> |
|
59 |
<tr><th><img src="../../images/jstoolbar/bt_img.png" style="border: 1px solid #bbb;" alt="Image" /></th><td>![](<em>image_url</em>)</td><td></td></tr> |
|
60 |
<tr><th></th><td>![](<em>attached_image</em>)</td><td></td></tr> |
|
61 | ||
62 |
<tr><th colspan="3">Tables</th></tr> |
|
63 |
<tr> |
|
64 |
<th></th> |
|
65 |
<td>| A | B | C |<br />|---|---|---|<br />| A | B | C |<br />| D | E | F |</td> |
|
66 |
<td> |
|
67 |
<table class="sample"> |
|
68 |
<tbody> |
|
69 |
<th>A</th><th>B</th><th>C</th> |
|
70 |
<tr><td>A</td><td>B</td><td>C</td></tr> |
|
71 |
<tr><td>D</td><td>E</td><td>F</td></tr> |
|
72 |
</tbody> |
|
73 |
</table> |
|
74 |
</td> |
|
75 |
</tr> |
|
76 | ||
77 |
<tr><th colspan="3">Raw HTML <span class="more_info">(<a href="wiki_syntax_detailed_common_mark.html#15" target="_blank">more</a>)</span></th></tr> |
|
78 |
<tr> |
|
79 |
<th></th><td>HTML is <del>not</del> <u>allowed</u>.</td><td>HTML is <del>not</del> <u>allowed</u>.<td> |
|
80 |
</tr> |
|
81 | ||
82 |
</table> |
|
83 | ||
84 |
<p><a href="wiki_syntax_detailed_common_mark.html" onclick="window.open('wiki_syntax_detailed_common_mark.html', '', ''); return false;">More Information</a></p> |
|
85 |
</body> |
|
86 |
</html> |
|
87 |
public/help/en/wiki_syntax_detailed_common_mark.html | ||
---|---|---|
1 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> |
|
2 |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> |
|
3 |
<head> |
|
4 |
<title>RedmineWikiFormatting (CommonMark Markdown (GitHub Flavored))</title> |
|
5 |
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> |
|
6 |
<link rel="stylesheet" type="text/css" href="../wiki_syntax_detailed.css" /> |
|
7 |
</head> |
|
8 | ||
9 |
<body> |
|
10 |
<h1><a name="1" class="wiki-page"></a>Wiki formatting (CommonMark Markdown (GitHub Flavored))</h1> |
|
11 | ||
12 |
<ul class='toc'> |
|
13 |
<li><a href='#2'>Links</a></li> |
|
14 |
<ul> |
|
15 |
<li><a href='#3'>Redmine links</a></li> |
|
16 |
<li><a href='#4'>External links</a></li> |
|
17 |
</ul> |
|
18 |
<li><a href='#5'>Text formatting</a></li> |
|
19 |
<ul> |
|
20 |
<li><a href='#6'>Font style</a></li> |
|
21 |
<li><a href='#7'>Inline images</a></li> |
|
22 |
<li><a href='#8'>Headings</a></li> |
|
23 |
<li><a href='#10'>Blockquotes</a></li> |
|
24 |
<li><a href='#11'>Table of content</a></li> |
|
25 |
<li><a href='#14'>Horizontal Rule</a></li> |
|
26 |
</ul> |
|
27 |
<li><a href='#12'>Macros</a></li> |
|
28 |
<li><a href='#13'>Code highlighting</a></li> |
|
29 |
<li><a href='#15'>Raw HTML</a></li> |
|
30 |
</ul> |
|
31 | ||
32 |
<h2><a name="2" class="wiki-page"></a>Links</h2> |
|
33 | ||
34 |
<h3><a name="3" class="wiki-page"></a>Redmine links</h3> |
|
35 | ||
36 |
<p>Redmine allows hyperlinking between resources (issues, changesets, wiki pages...) from anywhere wiki formatting is used.</p> |
|
37 |
<ul> |
|
38 |
<li>Link to an issue: <strong>#124</strong> (displays <del><a href="#" class="issue" title="bulk edit doesn't change the category or fixed version properties (Closed)">#124</a></del>, link is striked-through if the issue is closed)</li> |
|
39 |
<li>Link to an issue including tracker name and subject: <strong>##124</strong> (displays <a href="#" class="issue" title="bulk edit doesn't change the category or fixed version properties (New)">Bug #124</a>: bulk edit doesn't change the category or fixed version properties)</li> |
|
40 |
<li>Link to an issue note: <strong>#124-6</strong>, or <strong>#124#note-6</strong></li> |
|
41 |
<li>Link to an issue note within the same issue: <strong>#note-6</strong></li> |
|
42 |
</ul> |
|
43 | ||
44 |
<p>Wiki links:</p> |
|
45 | ||
46 |
<ul> |
|
47 |
<li><strong>[[Guide]]</strong> displays a link to the page named 'Guide': <a href="#" class="wiki-page">Guide</a></li> |
|
48 |
<li><strong>[[Guide#further-reading]]</strong> takes you to the anchor "further-reading". Headings get automatically assigned anchors so that you can refer to them: <a href="#" class="wiki-page">Guide</a></li> |
|
49 |
<li><strong>[[#further-reading]]</strong> link to the anchor "further-reading" of the current page: <a href="#" class="wiki-page">#further-reading</a></li> |
|
50 |
<li><strong>[[Guide|User manual]]</strong> displays a link to the same page but with a different text: <a href="#" class="wiki-page">User manual</a></li> |
|
51 |
</ul> |
|
52 | ||
53 |
<p>You can also link to pages of an other project wiki:</p> |
|
54 | ||
55 |
<ul> |
|
56 |
<li><strong>[[sandbox:some page]]</strong> displays a link to the page named 'Some page' of the Sandbox wiki</li> |
|
57 |
<li><strong>[[sandbox:]]</strong> displays a link to the Sandbox wiki main page</li> |
|
58 |
</ul> |
|
59 | ||
60 |
<p>Wiki links are displayed in red if the page doesn't exist yet, eg: <a href="#" class="wiki-page new">Nonexistent page</a>.</p> |
|
61 | ||
62 |
<p>Links to other resources:</p> |
|
63 | ||
64 |
<ul> |
|
65 |
<li>Documents: |
|
66 |
<ul> |
|
67 |
<li><strong>document#17</strong> (link to document with id 17)</li> |
|
68 |
<li><strong>document:Greetings</strong> (link to the document with title "Greetings")</li> |
|
69 |
<li><strong>document:"Some document"</strong> (double quotes can be used when document title contains spaces)</li> |
|
70 |
<li><strong>sandbox:document:"Some document"</strong> (link to a document with title "Some document" in other project "sandbox")</li> |
|
71 |
</ul> |
|
72 |
</li> |
|
73 |
</ul> |
|
74 | ||
75 |
<ul> |
|
76 |
<li>Versions: |
|
77 |
<ul> |
|
78 |
<li><strong>version#3</strong> (link to version with id 3)</li> |
|
79 |
<li><strong>version:1.0.0</strong> (link to version named "1.0.0")</li> |
|
80 |
<li><strong>version:"1.0 beta 2"</strong></li> |
|
81 |
<li><strong>sandbox:version:1.0.0</strong> (link to version "1.0.0" in the project "sandbox")</li> |
|
82 |
</ul> |
|
83 |
</li> |
|
84 |
</ul> |
|
85 | ||
86 |
<ul> |
|
87 |
<li>Attachments: |
|
88 |
<ul> |
|
89 |
<li><strong>attachment:file.zip</strong> (link to the attachment of the current object named file.zip)</li> |
|
90 |
<li>For now, attachments of the current object can be referenced only (if you're on an issue, it's possible to reference attachments of this issue only)</li> |
|
91 |
</ul> |
|
92 |
</li> |
|
93 |
</ul> |
|
94 | ||
95 |
<ul> |
|
96 |
<li>Changesets: |
|
97 |
<ul> |
|
98 |
<li><strong>r758</strong> (link to a changeset)</li> |
|
99 |
<li><strong>commit:c6f4d0fd</strong> (link to a changeset with a non-numeric hash)</li> |
|
100 |
<li><strong>svn1|r758</strong> (link to a changeset of a specific repository, for projects with multiple repositories)</li> |
|
101 |
<li><strong>commit:hg|c6f4d0fd</strong> (link to a changeset with a non-numeric hash of a specific repository)</li> |
|
102 |
<li><strong>sandbox:r758</strong> (link to a changeset of another project)</li> |
|
103 |
<li><strong>sandbox:commit:c6f4d0fd</strong> (link to a changeset with a non-numeric hash of another project)</li> |
|
104 |
</ul> |
|
105 |
</li> |
|
106 |
</ul> |
|
107 | ||
108 |
<ul> |
|
109 |
<li>Repository files: |
|
110 |
<ul> |
|
111 |
<li><strong>source:some/file</strong> (link to the file located at /some/file in the project's repository)</li> |
|
112 |
<li><strong>source:some/file@52</strong> (link to the file's revision 52)</li> |
|
113 |
<li><strong>source:some/file#L120</strong> (link to line 120 of the file)</li> |
|
114 |
<li><strong>source:some/file@52#L120</strong> (link to line 120 of the file's revision 52)</li> |
|
115 |
<li><strong>source:"some file@52#L120"</strong> (use double quotes when the URL contains spaces</li> |
|
116 |
<li><strong>export:some/file</strong> (force the download of the file)</li> |
|
117 |
<li><strong>source:svn1|some/file</strong> (link to a file of a specific repository, for projects with multiple repositories)</li> |
|
118 |
<li><strong>sandbox:source:some/file</strong> (link to the file located at /some/file in the repository of the project "sandbox")</li> |
|
119 |
<li><strong>sandbox:export:some/file</strong> (force the download of the file)</li> |
|
120 |
</ul> |
|
121 |
</li> |
|
122 |
</ul> |
|
123 | ||
124 |
<ul> |
|
125 |
<li>Forums: |
|
126 |
<ul> |
|
127 |
<li><strong>forum#1</strong> (link to forum with id 1</li> |
|
128 |
<li><strong>forum:Support</strong> (link to forum named Support)</li> |
|
129 |
<li><strong>forum:"Technical Support"</strong> (use double quotes if forum name contains spaces)</li> |
|
130 |
</ul> |
|
131 |
</li> |
|
132 |
</ul> |
|
133 | ||
134 |
<ul> |
|
135 |
<li>Forum messages: |
|
136 |
<ul> |
|
137 |
<li><strong>message#1218</strong> (link to message with id 1218)</li> |
|
138 |
</ul> |
|
139 |
</li> |
|
140 |
</ul> |
|
141 | ||
142 |
<ul> |
|
143 |
<li>Projects: |
|
144 |
<ul> |
|
145 |
<li><strong>project#3</strong> (link to project with id 3)</li> |
|
146 |
<li><strong>project:some-project</strong> (link to project with name or slug of "some-project")</li> |
|
147 |
<li><strong>project:"Some Project"</strong> (use double quotes for project name containing spaces)</li> |
|
148 |
</ul> |
|
149 |
</li> |
|
150 |
</ul> |
|
151 | ||
152 |
<ul> |
|
153 |
<li>News: |
|
154 |
<ul> |
|
155 |
<li><strong>news#2</strong> (link to news item with id 2)</li> |
|
156 |
<li><strong>news:Greetings</strong> (link to news item named "Greetings")</li> |
|
157 |
<li><strong>news:"First Release"</strong> (use double quotes if news item name contains spaces)</li> |
|
158 |
</ul> |
|
159 |
</li> |
|
160 |
</ul> |
|
161 | ||
162 |
<ul> |
|
163 |
<li>Users: |
|
164 |
<ul> |
|
165 |
<li><strong>user#2</strong> (link to user with id 2)</li> |
|
166 |
<li><strong>user:jsmith</strong> (Link to user with login jsmith)</li> |
|
167 |
<li><strong>@jsmith</strong> (Link to user with login jsmith)</li> |
|
168 |
</ul> |
|
169 |
</li> |
|
170 |
</ul> |
|
171 | ||
172 |
<p>Escaping:</p> |
|
173 | ||
174 |
<ul> |
|
175 |
<li>You can prevent Redmine links from being parsed by preceding them with an exclamation mark: !</li> |
|
176 |
</ul> |
|
177 | ||
178 | ||
179 |
<h3><a name="4" class="wiki-page"></a>External links</h3> |
|
180 | ||
181 |
<p>URLs (starting with: www, http, https, ftp, ftps, sftp and sftps) and email addresses are automatically turned into clickable links:</p> |
|
182 | ||
183 |
<pre> |
|
184 |
http://www.redmine.org, someone@foo.bar |
|
185 |
</pre> |
|
186 | ||
187 |
<p>displays: <a class="external" href="http://www.redmine.org">http://www.redmine.org</a>, <a href="mailto:someone@foo.bar" class="email">someone@foo.bar</a></p> |
|
188 | ||
189 |
<p>If you want to display a specific text instead of the URL, you can use the standard markdown syntax:</p> |
|
190 | ||
191 |
<pre> |
|
192 |
[Redmine web site](http://www.redmine.org) |
|
193 |
</pre> |
|
194 | ||
195 |
<p>displays: <a href="http://www.redmine.org" class="external">Redmine web site</a></p> |
|
196 | ||
197 | ||
198 |
<h2><a name="5" class="wiki-page"></a>Text formatting</h2> |
|
199 | ||
200 |
<p>For things such as headlines, bold, tables, lists, Redmine supports Markdown syntax according to <a class="external" href="https://commonmark.org/">CommonMark</a> including some extensions commonly referred to as <em>GitHub flavored Markdown</em>. See the <a class="external" href="https://github.github.com/gfm">GitHub Flavored Markdown Spec</a> for information on using any of these features. A few samples are included below, but the engine is capable of much more of that.</p> |
|
201 | ||
202 |
<h3><a name="6" class="wiki-page"></a>Font style</h3> |
|
203 | ||
204 |
<pre> |
|
205 |
* **bold** |
|
206 |
* *Italic* |
|
207 |
* ***bold italic*** |
|
208 |
* ~~strike-through~~ |
|
209 |
</pre> |
|
210 | ||
211 |
<p>Display:</p> |
|
212 | ||
213 |
<ul> |
|
214 |
<li><strong>bold</strong></li> |
|
215 |
<li><em>italic</em></li> |
|
216 |
<li><em><strong>bold italic</strong></em></li> |
|
217 |
<li><del>strike-through</del></li> |
|
218 |
</ul> |
|
219 | ||
220 |
<h3><a name="7" class="wiki-page"></a>Inline images</h3> |
|
221 | ||
222 |
<ul> |
|
223 |
<li><strong>![](image_url)</strong> displays an image located at image_url (markdown syntax)</li> |
|
224 |
<li>If you have an image attached to your wiki page, it can be displayed inline using its filename: <strong>![](attached_image)</strong></li> |
|
225 |
<li>Images in your computer's clipboard can be pasted directly using Ctrl-v or Command-v.</li> |
|
226 |
<li>Image files can be dragged onto the text area in order to be uploaded and embedded.</li> |
|
227 |
</ul> |
|
228 | ||
229 |
<h3><a name="8" class="wiki-page"></a>Headings</h3> |
|
230 | ||
231 |
<pre> |
|
232 |
# Heading |
|
233 |
## Subheading |
|
234 |
### Subsubheading |
|
235 |
</pre> |
|
236 | ||
237 |
<p>Redmine assigns an anchor to each of those headings thus you can link to them with "#Heading", "#Subheading" and so forth.</p> |
|
238 | ||
239 | ||
240 |
<h3><a name="10" class="wiki-page"></a>Blockquotes</h3> |
|
241 | ||
242 |
<p>Start the paragraph with <strong>></strong></p> |
|
243 | ||
244 |
<pre> |
|
245 |
> Rails is a full-stack framework for developing database-backed web applications according to the Model-View-Control pattern. |
|
246 |
To go live, all you need to add is a database and a web server. |
|
247 |
</pre> |
|
248 | ||
249 |
<p>Display:</p> |
|
250 | ||
251 |
<blockquote> |
|
252 |
<p>Rails is a full-stack framework for developing database-backed web applications according to the Model-View-Control pattern.<br />To go live, all you need to add is a database and a web server.</p> |
|
253 |
</blockquote> |
|
254 | ||
255 | ||
256 |
<h3><a name="11" class="wiki-page"></a>Table of content</h3> |
|
257 | ||
258 |
<pre> |
|
259 |
{{toc}} => left aligned toc |
|
260 |
{{>toc}} => right aligned toc |
|
261 |
</pre> |
|
262 | ||
263 |
<h3><a name="14" class="wiki-page"></a>Horizontal Rule</h3> |
|
264 | ||
265 |
<pre> |
|
266 |
--- |
|
267 |
</pre> |
|
268 | ||
269 |
<h2><a name="12" class="wiki-page"></a>Macros</h2> |
|
270 | ||
271 |
<p>Redmine has the following builtin macros:</p> |
|
272 | ||
273 |
<p> |
|
274 |
<dl> |
|
275 |
<dt><code>hello_world</code></dt> |
|
276 |
<dd><p>Sample macro.</p></dd> |
|
277 | ||
278 |
<dt><code>macro_list</code></dt> |
|
279 |
<dd><p>Displays a list of all available macros, including description if available.</p></dd> |
|
280 | ||
281 |
<dt><code>child_pages</code></dt> |
|
282 |
<dd><p>Displays a list of child pages. With no argument, it displays the child pages of the current wiki page. Examples:</p> |
|
283 |
<pre><code>{{child_pages}} -- can be used from a wiki page only |
|
284 |
{{child_pages(depth=2)}} -- display 2 levels nesting only</code></pre></dd> |
|
285 | ||
286 |
<dt><code>include</code></dt> |
|
287 |
<dd><p>Include a wiki page. Example:</p> |
|
288 |
<pre><code>{{include(Foo)}}</code></pre> |
|
289 |
<p>or to include a page of a specific project wiki:</p> |
|
290 |
<pre><code>{{include(projectname:Foo)}}</code></pre></dd> |
|
291 | ||
292 |
<dt><code>collapse</code></dt> |
|
293 |
<dd><p>Inserts of collapsed block of text. Example:</p> |
|
294 |
<pre><code>{{collapse(View details...) |
|
295 |
This is a block of text that is collapsed by default. |
|
296 |
It can be expanded by clicking a link. |
|
297 |
}}</code></pre></dd> |
|
298 | ||
299 |
<dt><code>thumbnail</code></dt> |
|
300 |
<dd><p>Displays a clickable thumbnail of an attached image. Examples:</p> |
|
301 |
<pre>{{thumbnail(image.png)}} |
|
302 |
{{thumbnail(image.png, size=300, title=Thumbnail)}}</pre></dd> |
|
303 | ||
304 |
<dt><code>issue</code></dt> |
|
305 |
<dd><p>Inserts a link to an issue with flexible text. Examples:</p> |
|
306 |
<pre>{{issue(123)}} -- Issue #123: Enhance macro capabilities |
|
307 |
{{issue(123, project=true)}} -- Andromeda - Issue #123:Enhance macro capabilities |
|
308 |
{{issue(123, tracker=false)}} -- #123: Enhance macro capabilities |
|
309 |
{{issue(123, subject=false, project=true)}} -- Andromeda - Issue #123</pre></dd> |
|
310 |
</dl> |
|
311 |
</p> |
|
312 | ||
313 |
<h2><a name="13" class="wiki-page"></a>Code highlighting</h2> |
|
314 | ||
315 |
<p>Default code highlighting relies on <a href="http://rouge.jneen.net/" class="external">Rouge</a>, a syntax highlighting library written in pure Ruby. It supports many commonly used languages such as <strong>c</strong>, <strong>cpp</strong> (c++), <strong>csharp</strong> (c#, cs), <strong>css</strong>, <strong>diff</strong> (patch, udiff), <strong>go</strong> (golang), <strong>groovy</strong>, <strong>html</strong>, <strong>java</strong>, <strong>javascript</strong> (js), <strong>kotlin</strong>, <strong>objective_c</strong> (objc), <strong>perl</strong> (pl), <strong>php</strong>, <strong>python</strong> (py), <strong>r</strong>, <strong>ruby</strong> (rb), <strong>sass</strong>, <strong>scala</strong>, <strong>shell</strong> (bash, zsh, ksh, sh), <strong>sql</strong>, <strong>swift</strong>, <strong>xml</strong> and <strong>yaml</strong> (yml) languages, where the names inside parentheses are aliases. Please refer to <a href="https://www.redmine.org/projects/redmine/wiki/RedmineCodeHighlightingLanguages" class="external">https://www.redmine.org/projects/redmine/wiki/RedmineCodeHighlightingLanguages</a> for the full list of supported languages.</p> |
|
316 | ||
317 |
<p>You can highlight code at any place that supports wiki formatting using this syntax (note that the language name or alias is case-insensitive):</p> |
|
318 | ||
319 |
<pre> |
|
320 |
```ruby |
|
321 |
Place your code here. |
|
322 |
``` |
|
323 |
</pre> |
|
324 | ||
325 |
<p>Example:</p> |
|
326 | ||
327 |
<pre><code class="ruby syntaxhl"><span class="c1"># The Greeter class</span> |
|
328 |
<span class="k">class</span> <span class="nc">Greeter</span> |
|
329 |
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span> |
|
330 |
<span class="vi">@name</span> <span class="o">=</span> <span class="nb">name</span><span class="p">.</span><span class="nf">capitalize</span> |
|
331 |
<span class="k">end</span> |
|
332 | ||
333 |
<span class="k">def</span> <span class="nf">salute</span> |
|
334 |
<span class="nb">puts</span> <span class="s2">"Hello </span><span class="si">#{</span><span class="vi">@name</span><span class="si">}</span><span class="s2">!"</span> |
|
335 |
<span class="k">end</span> |
|
336 |
<span class="k">end</span> |
|
337 |
</code></pre> |
|
338 | ||
339 |
<h2><a name="15" class="wiki-page"></a>Raw HTML</h2> |
|
340 | ||
341 |
<p>You may use raw HTML for more complex formatting tasks, i.e. complex tables with cells spanning multiple rows or columns:</p> |
|
342 | ||
343 |
<pre><code> |
|
344 |
<table width="50%"> |
|
345 |
<tr><td rowspan="2">Two rows</td><td>foo</td></tr> |
|
346 |
<tr><td>bar</td></tr> |
|
347 |
<tr><td align="center" colspan="2">bar</td></tr> |
|
348 |
</table> |
|
349 |
</code></pre> |
|
350 | ||
351 |
<p>yields</p> |
|
352 | ||
353 |
<table width="50%" class="sample"> |
|
354 |
<tr><td rowspan="2">Two rows</td><td>foo</td></tr> |
|
355 |
<tr><td>bar</td></tr> |
|
356 |
<tr><td align="center" colspan="2">bar</td></tr> |
|
357 |
</table> |
|
358 | ||
359 |
</body> |
|
360 |
</html> |
|
361 |
public/help/wiki_syntax_detailed.css | ||
---|---|---|
15 | 15 |
a:hover, a:active{ color: #c61a1a; text-decoration: underline;} |
16 | 16 |
a.new { color: #b73535; } |
17 | 17 | |
18 |
table.sample { border-collapse: collapse; border-spacing: 0; margin: 4px; margin-left: 30px;} |
|
19 |
table.sample th, table.sample td { border: solid 1px #bbb; padding: 4px; height: 1em; } |
|
20 | ||
18 | 21 |
.syntaxhl .c1 { color: #888888 } |
19 | 22 |
.syntaxhl .k { color: #008800; font-weight: bold } |
20 | 23 |
.syntaxhl .nc { color: #BB0066; font-weight: bold } |
test/unit/lib/redmine/wiki_formatting/common_mark/application_helper_test.rb | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
# Redmine - project management software |
|
4 |
# Copyright (C) 2006-2021 Jean-Philippe Lang |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | ||
20 |
require File.expand_path('../../../../../../test_helper', __FILE__) |
|
21 | ||
22 |
class Redmine::WikiFormatting::CommonMark::ApplicationHelperTest < Redmine::HelperTest |
|
23 |
if Object.const_defined?(:CommonMarker) |
|
24 | ||
25 |
include ERB::Util |
|
26 |
include Rails.application.routes.url_helpers |
|
27 | ||
28 |
fixtures :projects, :enabled_modules, |
|
29 |
:users, :email_addresses, |
|
30 |
:members, :member_roles, :roles, |
|
31 |
:repositories, :changesets, |
|
32 |
:projects_trackers, |
|
33 |
:trackers, :issue_statuses, :issues, :versions, :documents, :journals, |
|
34 |
:wikis, :wiki_pages, :wiki_contents, |
|
35 |
:boards, :messages, :news, |
|
36 |
:attachments, :enumerations, |
|
37 |
:custom_values, :custom_fields, :custom_fields_projects |
|
38 | ||
39 |
def setup |
|
40 |
super |
|
41 |
set_tmp_attachments_directory |
|
42 |
end |
|
43 | ||
44 |
def test_attached_images_with_markdown_and_non_ascii_filename |
|
45 |
to_test = { |
|
46 |
'CAFÉ.JPG' => 'CAF%C3%89.JPG', |
|
47 |
'crème.jpg' => 'cr%C3%A8me.jpg', |
|
48 |
} |
|
49 |
with_settings :text_formatting => 'common_mark' do |
|
50 |
to_test.each do |filename, result| |
|
51 |
attachment = Attachment.generate!(:filename => filename) |
|
52 |
assert_include %(<img src="/attachments/download/#{attachment.id}/#{result}" alt="">), textilizable("![](#{filename})", :attachments => [attachment]) |
|
53 |
end |
|
54 |
end |
|
55 |
end |
|
56 | ||
57 |
def test_toc_with_markdown_formatting_should_be_parsed |
|
58 |
with_settings :text_formatting => 'common_mark' do |
|
59 |
assert_select_in textilizable("{{toc}}\n\n# Heading"), 'ul.toc li', :text => 'Heading' |
|
60 |
assert_select_in textilizable("{{<toc}}\n\n# Heading"), 'ul.toc.left li', :text => 'Heading' |
|
61 |
assert_select_in textilizable("{{>toc}}\n\n# Heading"), 'ul.toc.right li', :text => 'Heading' |
|
62 |
end |
|
63 |
end |
|
64 | ||
65 |
end |
|
66 |
end |
test/unit/lib/redmine/wiki_formatting/common_mark/external_links_filter_test.rb | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
# Redmine - project management software |
|
4 |
# Copyright (C) 2006-2021 Jean-Philippe Lang |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | ||
20 |
require File.expand_path('../../../../../../test_helper', __FILE__) |
|
21 | ||
22 |
if Object.const_defined?(:CommonMarker) |
|
23 |
require 'redmine/wiki_formatting/common_mark/external_links_filter' |
|
24 | ||
25 |
class Redmine::WikiFormatting::CommonMark::ExternalLinksFilterTest < ActiveSupport::TestCase |
|
26 |
def filter(html) |
|
27 |
Redmine::WikiFormatting::CommonMark::ExternalLinksFilter.to_html(html, @options) |
|
28 |
end |
|
29 | ||
30 |
def setup |
|
31 |
@options = { } |
|
32 |
end |
|
33 | ||
34 |
def test_external_links_should_have_external_css_class |
|
35 |
assert_equal %(<a href="http://example.net/" class="external">link</a>), filter(%(<a href="http://example.net/">link</a>)) |
|
36 |
end |
|
37 | ||
38 |
def test_locals_links_should_not_have_external_css_class |
|
39 |
assert_equal %(<a href="/">home</a>), filter(%(<a href="/">home</a>)) |
|
40 |
assert_equal %(<a href="relative">relative</a>), filter(%(<a href="relative">relative</a>)) |
|
41 |
assert_equal %(<a href="#anchor">anchor</a>), filter(%(<a href="#anchor">anchor</a>)) |
|
42 |
end |
|
43 | ||
44 |
def test_mailto_links_should_have_email_class |
|
45 |
assert_equal %(<a href="mailto:user@example.org" class="email">user</a>), filter(%(<a href="mailto:user@example.org">user</a>)) |
|
46 |
end |
|
47 |
end |
|
48 |
end |
test/unit/lib/redmine/wiki_formatting/common_mark/fixup_auto_links_filter_test.rb | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
# Redmine - project management software |
|
4 |
# Copyright (C) 2006-2021 Jean-Philippe Lang |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | ||
20 |
require File.expand_path('../../../../../../test_helper', __FILE__) |
|
21 | ||
22 |
if Object.const_defined?(:CommonMarker) |
|
23 |
require 'redmine/wiki_formatting/common_mark/fixup_auto_links_filter' |
|
24 | ||
25 |
class Redmine::WikiFormatting::CommonMark::FixupAutoLinksFilterTest < ActiveSupport::TestCase |
|
26 |
def filter(html) |
|
27 |
Redmine::WikiFormatting::CommonMark::FixupAutoLinksFilter.to_html(html, @options) |
|
28 |
end |
|
29 | ||
30 |
def format(markdown) |
|
31 |
Redmine::WikiFormatting::CommonMark::MarkdownFilter.to_html(markdown, Redmine::WikiFormatting::CommonMark::PIPELINE_CONFIG) |
|
32 |
end |
|
33 | ||
34 |
def setup |
|
35 |
@options = { } |
|
36 |
end |
|
37 | ||
38 |
def test_should_fixup_autolinked_user_references |
|
39 |
text = "user:user@example.org" |
|
40 |
assert_equal "<p>#{text}</p>", filter(format(text)) |
|
41 |
text = "@user@example.org" |
|
42 |
assert_equal "<p>#{text}</p>", filter(format(text)) |
|
43 |
end |
|
44 | ||
45 |
def test_should_fixup_autolinked_hires_files |
|
46 |
text = "printscreen@2x.png" |
|
47 |
assert_equal "<p>#{text}</p>", filter(format(text)) |
|
48 |
end |
|
49 |
end |
|
50 |
end |
test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb | ||
---|---|---|
1 |
# frozen_string_literal: true |
|
2 | ||
3 |
# Redmine - project management software |
|
4 |
# Copyright (C) 2006-2021 Jean-Philippe Lang |
|
5 |
# |
|
6 |
# This program is free software; you can redistribute it and/or |
|
7 |
# modify it under the terms of the GNU General Public License |
|
8 |
# as published by the Free Software Foundation; either version 2 |
|
9 |
# of the License, or (at your option) any later version. |
|
10 |
# |
|
11 |
# This program is distributed in the hope that it will be useful, |
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
# GNU General Public License for more details. |
|
15 |
# |
|
16 |
# You should have received a copy of the GNU General Public License |
|
17 |
# along with this program; if not, write to the Free Software |
|
18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | ||
20 |
require File.expand_path('../../../../../../test_helper', __FILE__) |
|
21 | ||
22 |
class Redmine::WikiFormatting::CommonMark::FormatterTest < ActionView::TestCase |
|
23 |
if Object.const_defined?(:CommonMarker) |
|
24 | ||
25 |
def setup |
|
26 |
@formatter = Redmine::WikiFormatting::CommonMark::Formatter |
|
27 |
end |
|
28 | ||
29 |
def format(text) |
|
30 |
@formatter.new(text).to_html |
|
31 |
end |
|
32 | ||
33 |
def test_should_render_hard_breaks |
|
34 |
html ="<p>foo<br>\nbar</p>" |
|
35 |
assert_equal html, format("foo\\\nbar") |
|
36 |
assert_equal html, format("foo \nbar") |
|
37 |
end |
|
38 | ||
39 |
def test_should_ignore_soft_breaks |
|
40 |
assert_equal "<p>foo\nbar</p>", format("foo\nbar") |
|
41 |
end |
|
42 | ||
43 |
def test_syntax_error_in_image_reference_should_not_raise_exception |
|
44 |
assert format("!>[](foo.png)") |
|
45 |
end |
|
46 | ||
47 |
def test_empty_image_should_not_raise_exception |
|
48 |
assert format("![]()") |
|
49 |
end |
|
50 | ||
51 |
def test_inline_style |
|
52 |
assert_equal "<p><strong>foo</strong></p>", format("**foo**") |
|
53 |
end |
|
54 | ||
55 |
def test_not_set_intra_emphasis |
|
56 |
assert_equal "<p>foo_bar_baz</p>", format("foo_bar_baz") |
|
57 |
end |
|
58 | ||
59 |
def test_wiki_links_should_be_preserved |
|
60 |
text = 'This is a wiki link: [[Foo]]' |
|
61 |
assert_include '[[Foo]]', format(text) |
|
62 |
end |
|
63 | ||
64 |
def test_redmine_links_with_double_quotes_should_be_preserved |
|
65 |
text = 'This is a redmine link: version:"1.0"' |
|
66 |
assert_include 'version:"1.0"', format(text) |
|
67 |
end |
|
68 | ||
69 |
def test_links_by_id_should_be_preserved |
|
70 |
text = "[project#3]" |
|
71 |
assert_equal "<p>#{text}</p>", format(text) |
|
72 |
end |
|
73 | ||
74 |
def test_links_to_users_should_be_preserved |
|
75 |
text = "[@login]" |
|
76 |
assert_equal "<p>#{text}</p>", format(text) |
|
77 |
text = "[user:login]" |
|
78 |
assert_equal "<p>#{text}</p>", format(text) |
|
79 |
text = "user:user@example.org" |
|
80 |
assert_equal "<p>#{text}</p>", format(text) |
|
81 |
text = "[user:user@example.org]" |
|
82 |
assert_equal "<p>#{text}</p>", format(text) |
|
83 |
text = "@user@example.org" |
|
84 |
assert_equal "<p>#{text}</p>", format(text) |
|
85 |
text = "[@user@example.org]" |
|
86 |
assert_equal "<p>#{text}</p>", format(text) |
|
87 |
end |
|
88 | ||
89 |
def test_files_with_at_should_not_end_up_as_mailto_links |
|
90 |
text = "printscreen@2x.png" |
|
91 |
assert_equal "<p>#{text}</p>", format(text) |
|
92 |
text = "[printscreen@2x.png]" |
|
93 |
assert_equal "<p>#{text}</p>", format(text) |
|
94 |
end |
|
95 | ||
96 |
def test_should_support_syntax_highlight |
|
97 |
text = <<-STR |
|
98 |
~~~ruby |
|
99 |
def foo |
|
100 |
end |
|
101 |
~~~ |
|
102 |
STR |
|
103 |
assert_select_in format(text), 'pre code.ruby.syntaxhl' do |
|
104 |
assert_select 'span.k', :text => 'def' |
|
105 |
end |
|
106 |
end |
|
107 | ||
108 |
def test_should_not_allow_invalid_language_for_code_blocks |
|
109 |
text = <<-STR |
|
110 |
~~~foo |
|
111 |
test |
|
112 |
~~~ |
|
113 |
STR |
|
114 |
assert_equal "<pre>test\n</pre>", format(text) |
|
115 |
end |
|
116 | ||
117 |
def test_external_links_should_have_external_css_class |
|
118 |
text = 'This is a [link](http://example.net/)' |
|
119 |
assert_equal '<p>This is a <a href="http://example.net/" class="external">link</a></p>', format(text) |
|
120 |
end |
|
121 | ||
122 |
def test_locals_links_should_not_have_external_css_class |
|
123 |
text = 'This is a [link](/issues)' |
|
124 |
assert_equal '<p>This is a <a href="/issues">link</a></p>', format(text) |
|
125 |
end |
|
126 | ||
127 |
def test_markdown_should_not_require_surrounded_empty_line |
|
128 |
text = <<-STR |
|
129 |
This is a list: |
|
130 |
* One |
|
131 |
* Two |
|
132 |
STR |
|
133 |
assert_equal "<p>This is a list:</p>\n<ul>\n<li>One</li>\n<li>Two</li>\n</ul>", format(text) |
|
134 |
end |
|
135 | ||
136 |
def test_footnotes |
|
137 |
text = <<-STR |
|
138 |
This is some text[^1]. |
|
139 |
|
|
140 |
[^1]: This is the foot note |
|
141 |
STR |
|
142 | ||
143 |
expected = <<-EXPECTED |
|
144 |
<p>This is some text<sup><a href="#fn1" id="fnref1">1</a></sup>.</p> |
|
145 |
<ol> |
|
146 |
<li id="fn1"> |
|
147 |
<p>This is the foot note <a href="#fnref1">↩</a></p> |
|
148 |
</li> |
|
149 |
</ol> |
|
150 |
EXPECTED |
|
151 | ||
152 |
assert_equal expected.gsub(%r{[\r\n\t]}, ''), format(text).gsub(%r{[\r\n\t]}, '') |
|
153 |
end |
|
154 | ||
155 |
STR_WITH_PRE = [ |
|
156 |
# 0 |
|
157 |
<<~STR.chomp, |
|
158 |
# Title |
|
159 |
|
|
160 |
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero. |
|
161 |
STR |
|
162 |
# 1 |
|
163 |
<<~STR.chomp, |
|
164 |
## Heading 2 |
|
165 |
|
|
166 |
~~~ruby |
|
167 |
def foo |
|
168 |
end |
|
169 |
~~~ |
|
170 |
|
|
171 |
Morbi facilisis accumsan orci non pharetra. |
|
172 |
|
|
173 |
~~~ ruby |
|
174 |
def foo |
|
175 |
end |
|
176 |
~~~ |
|
177 |
|
|
178 |
``` |
|
179 |
Pre Content: |
|
180 |
|
|
181 |
## Inside pre |
|
182 |
|
|
183 |
<tag> inside pre block |
|
184 |
|
|
185 |
Morbi facilisis accumsan orci non pharetra. |
|
186 |
``` |
|
187 |
STR |
|
188 |
# 2 |
|
189 |
<<~STR.chomp, |
|
190 |
### Heading 3 |
|
191 |
|
|
192 |
Nulla nunc nisi, egestas in ornare vel, posuere ac libero. |
|
193 |
STR |
|
194 |
] |
|
195 | ||
196 |
def test_get_section_should_ignore_pre_content |
|
197 |
text = STR_WITH_PRE.join("\n\n") |
|
198 | ||
199 |
assert_section_with_hash STR_WITH_PRE[1..2].join("\n\n"), text, 2 |
|
200 |
assert_section_with_hash STR_WITH_PRE[2], text, 3 |
|
201 |
end |
|
202 | ||
203 |
def test_update_section_should_not_escape_pre_content_outside_section |
|
204 |
text = STR_WITH_PRE.join("\n\n") |
|
205 |
replacement = "New text" |
|
206 | ||
207 |
assert_equal [STR_WITH_PRE[0..1], "New text"].flatten.join("\n\n"), |
|
208 |
@formatter.new(text).update_section(3, replacement) |
|
209 |
end |
|
210 | ||
211 |
def test_should_emphasize_text |
|
212 |
text = 'This _text_ should be emphasized' |
|
213 |
assert_equal '<p>This <em>text</em> should be emphasized</p>', format(text) |
|
214 |
end |
|
215 | ||
216 |
def test_should_strike_through_text |
|
217 |
text = 'This ~~text~~ should be striked through' |
|
218 |
assert_equal '<p>This <del>text</del> should be striked through</p>', format(text) |
|
219 |
end |
|
220 | ||
221 |
def test_should_autolink_urls_and_emails |
|
222 |
[ |
|
223 |
["http://example.org", '<p><a href="http://example.org" class="external">http://example.org</a></p>'], |
|
224 |
["http://www.redmine.org/projects/redmine/issues?utf8=✓", |
|
225 |
'<p><a href="http://www.redmine.org/projects/redmine/issues?utf8=%E2%9C%93" class="external">http://www.redmine.org/projects/redmine/issues?utf8=✓</a></p>'], |
|
226 |
['[Letters](https://yandex.ru/search/?text=кол-во)', '<p><a href="https://yandex.ru/search/?text=%D0%BA%D0%BE%D0%BB-%D0%B2%D0%BE" class="external">Letters</a></p>'], |
|
227 |
["www.example.org", '<p><a href="http://www.example.org" class="external">www.example.org</a></p>'], |
|
228 |
["user@example.org", '<p><a href="mailto:user@example.org" class="email">user@example.org</a></p>'] |
|
229 |
].each do |text, html| |
|
230 |
assert_equal html, format(text) |
|
231 |
end |
|
232 |
end |
|
233 | ||
234 |
def test_should_support_html_tables |
|
235 |
text = '<table style="background: red"><tr><td>Cell</td></tr></table>' |
|
236 |
assert_equal '<table><tr><td>Cell</td></tr></table>', format(text) |
|
237 |
end |
|
238 | ||
239 |
def test_should_remove_unsafe_uris |
|
240 |
[ |
|
241 |
['<img src="data:foobar">', '<img>'], |
|
242 |
['<a href="javascript:bla">click me</a>', '<p><a>click me</a></p>'], |
|
243 |
].each do |text, html| |
|
244 |
assert_equal html, format(text) |
|
245 |
end |
|
246 |
end |
|
247 | ||
248 |
def test_should_escape_unwanted_tags |
|
249 |
[ |
|
250 |
[ |
|
251 |
%[<p>sit<br>amet <style>.foo { color: #fff; }</style> <script>alert("hello world");</script></p>], |
|
252 |
%[sit<br/>amet <style>.foo { color: #fff; }</style> <script>alert("hello world");</script>] |
|
253 |
] |
|
254 |
].each do |expected, input| |
|
255 |
assert_equal expected, format(input) |
|
256 |
end |
|
257 |
end |