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></td><td></td></tr> |
|
| 60 |
<tr><th></th><td></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></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></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("", :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 |
|