forked from Ecodev/redmine_convert_textile_to_markown
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconvert_textile_to_markdown.rake
132 lines (108 loc) · 4.16 KB
/
convert_textile_to_markdown.rake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
task :convert_textile_to_markdown => :environment do
convert = {
Comment => [:comments],
WikiContent => [:text],
Issue => [:description],
Message => [:content],
News => [:description],
Document => [:description],
Project => [:description],
Journal => [:notes],
}
count = 0
print 'WelcomeText'
textile = Setting.welcome_text
if textile != nil
markdown = convert_textile_to_markdown(textile)
Setting.welcome_text = markdown
end
count += 1
print '.'
puts
convert.each do |the_class, attributes|
print the_class.name
the_class.find_each do |model|
attributes.each do |attribute|
textile = model[attribute]
if textile != nil
markdown = convert_textile_to_markdown(textile)
model.update_column(attribute, markdown)
end
end
count += 1
print '.'
end
puts
end
puts "Done converting #{count} models"
end
def convert_textile_to_markdown(textile)
require 'tempfile'
# Redmine support @ inside inline code marked with @ (such as "@[email protected]@"), but not pandoc.
# So we inject a placeholder that will be replaced later on with a real backtick.
tag_code = 'pandoc-unescaped-single-backtick'
textile.gsub!(/@([\S]+@[\S]+)@/, tag_code + '\\1' + tag_code)
# Drop table colspan/rowspan notation ("|\2." or "|/2.") because pandoc does not support it
# See https://github.com/jgm/pandoc/issues/22
textile.gsub!(/\|[\/\\]\d\. /, '| ')
# Drop table alignement notation ("|>." or "|<." or "|=.") because pandoc does not support it
# See https://github.com/jgm/pandoc/issues/22
textile.gsub!(/\|[<>=]\. /, '| ')
# Move the class from <code> to <pre> so pandoc can generate a code block with correct language
textile.gsub!(/(<pre)(><code)( class="[^"]*")(>)/, '\\1\\3\\2\\4')
# Remove the <code> directly inside <pre>, because pandoc would incorrectly preserve it
textile.gsub!(/(<pre[^>]*>)<code>/, '\\1')
textile.gsub!(/<\/code>(<\/pre>)/, '\\1')
# Inject a class in all <pre> that do not have a blank line before them
# This is to force pandoc to use fenced code block (```) otherwise it would
# use indented code block and would very likely need to insert an empty HTML
# comment "<!-- -->" (see http://pandoc.org/README.html#ending-a-list)
# which are unfortunately not supported by Redmine (see http://www.redmine.org/issues/20497)
tag_fenced_code_block = 'force-pandoc-to-ouput-fenced-code-block'
textile.gsub!(/([^\n]<pre)(>)/, "\\1 class=\"#{tag_fenced_code_block}\"\\2")
# Force <pre> to have a blank line before them
# Without this fix, a list of items containing <pre> would not be interpreted as a list at all.
textile.gsub!(/([^\n])(<pre)/, "\\1\n\n\\2")
# Some malformed textile content make pandoc run extremely slow,
# so we convert it to proper textile before hitting pandoc
# see https://github.com/jgm/pandoc/issues/3020
textile.gsub!(/- # (\d+)/, "* \\1")
src = Tempfile.new('src')
src.write(textile)
src.close
dst = Tempfile.new('dst')
dst.close
command = [
'pandoc',
'--wrap=preserve',
'-f',
'textile',
'-t',
'gfm+smart',
src.path,
'-o',
dst.path,
]
system(*command, :out => $stdout) or raise 'pandoc failed'
dst.open
markdown = dst.read
# Remove the \ pandoc puts before * and > at begining of lines
markdown.gsub!(/^((\\[*>])+)/) { $1.gsub("\\", "") }
# Add a blank line before lists
markdown.gsub!(/^([^*].*)\n\*/, "\\1\n\n*")
# Remove the injected tag
markdown.gsub!(' ' + tag_fenced_code_block, '')
# Replace placeholder with real backtick
markdown.gsub!(tag_code, '`')
# Un-escape Redmine link syntax to wiki pages
markdown.gsub!('\[\[', '[[')
markdown.gsub!('\]\]', ']]')
# Un-escape Redmine quotation mark "> " that pandoc is not aware of
markdown.gsub!(/(^|\n)> /, "\n> ")
# Remove <!-- end list --> injected by pandoc because Redmine incorrectly
# does not supported HTML comments: http://www.redmine.org/issues/20497
markdown.gsub!(/\n\n<!-- end list -->\n/, "\n")
# Unescape URL that could easily get mangled
markdown.gsub!(/(https?:\/\/\S+)/) { |link| link.gsub(/\\([_#])/, "\\1") }
return markdown
end