kramdown 1.4.2 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of kramdown might be problematic. Click here for more details.

Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTERS +2 -1
  3. data/Rakefile +3 -0
  4. data/VERSION +1 -1
  5. data/doc/documentation.template +7 -0
  6. data/doc/sidebar.template +2 -2
  7. data/doc/virtual +9 -0
  8. data/lib/kramdown/converter.rb +39 -0
  9. data/lib/kramdown/converter/base.rb +28 -0
  10. data/lib/kramdown/converter/html.rb +25 -31
  11. data/lib/kramdown/converter/math_engine/itex2mml.rb +39 -0
  12. data/lib/kramdown/converter/math_engine/mathjax.rb +33 -0
  13. data/lib/kramdown/converter/math_engine/ritex.rb +38 -0
  14. data/lib/kramdown/converter/syntax_highlighter/coderay.rb +78 -0
  15. data/lib/kramdown/converter/syntax_highlighter/rouge.rb +37 -0
  16. data/lib/kramdown/element.rb +5 -5
  17. data/lib/kramdown/options.rb +96 -11
  18. data/lib/kramdown/parser/gfm.rb +5 -2
  19. data/lib/kramdown/parser/html.rb +3 -2
  20. data/lib/kramdown/utils.rb +18 -0
  21. data/lib/kramdown/utils/configurable.rb +44 -0
  22. data/lib/kramdown/version.rb +1 -1
  23. data/man/man1/kramdown.1 +62 -0
  24. data/test/test_files.rb +80 -56
  25. data/test/testcases/block/06_codeblock/highlighting-opts.html +6 -0
  26. data/test/testcases/block/06_codeblock/highlighting-opts.options +7 -0
  27. data/test/testcases/block/06_codeblock/highlighting-opts.text +4 -0
  28. data/test/testcases/block/06_codeblock/highlighting-rouge.html +6 -0
  29. data/test/testcases/block/06_codeblock/highlighting-rouge.options +3 -0
  30. data/test/testcases/block/06_codeblock/highlighting-rouge.text +4 -0
  31. data/test/testcases/block/06_codeblock/highlighting.html +2 -2
  32. data/test/testcases/block/12_extension/options3.html +2 -2
  33. data/test/testcases/block/15_math/itex2mml.html +1 -0
  34. data/test/testcases/block/15_math/itex2mml.options +1 -0
  35. data/test/testcases/block/15_math/itex2mml.text +1 -0
  36. data/test/testcases/block/15_math/ritex.html +1 -0
  37. data/test/testcases/block/15_math/ritex.options +1 -0
  38. data/test/testcases/block/15_math/ritex.text +1 -0
  39. data/test/testcases/span/03_codespan/highlighting-rouge.html +1 -0
  40. data/test/testcases/span/03_codespan/highlighting-rouge.options +1 -0
  41. data/test/testcases/span/03_codespan/highlighting-rouge.text +1 -0
  42. data/test/testcases/span/03_codespan/highlighting.html +1 -1
  43. data/test/testcases/span/05_html/button.html +7 -0
  44. data/test/testcases/span/05_html/button.text +7 -0
  45. data/test/testcases/span/math/itex2mml.html +1 -0
  46. data/test/testcases/span/math/itex2mml.options +1 -0
  47. data/test/testcases/span/math/itex2mml.text +1 -0
  48. data/test/testcases/span/math/ritex.html +1 -0
  49. data/test/testcases/span/math/ritex.options +1 -0
  50. data/test/testcases/span/math/ritex.text +1 -0
  51. data/test/testcases_gfm/backticks_syntax.html +2 -2
  52. data/test/testcases_gfm/hard_line_breaks.html +3 -0
  53. data/test/testcases_gfm/hard_line_breaks.text +3 -0
  54. metadata +75 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d76ec0e7087a62788b9eb1d27027b1d4b4a2610e
4
- data.tar.gz: 4b6fcefcd89fd851be053d975cdd825e07278c58
3
+ metadata.gz: 7dfcfddc0bd28ea18be74a4f72d5a0f9549fdbfa
4
+ data.tar.gz: 419c886d8df8aa564eae484b89f3c7faceb259a7
5
5
  SHA512:
6
- metadata.gz: 9c34e8bb6438d78c04d45c4237856530669933add8620ce12e3847729d6a49429b114be6dc00dcefe3ff2b450a4f947bfc36c2854dbb6c43799437f5429efbb8
7
- data.tar.gz: 902838d7ee4add0e5dc66e67899b75fd9f44dddfff181eb6c99b20ffebd1af97c920f15bf6a87317c410ffef89f57ba28d9b6e48bbf1bc7de714389833ffee6a
6
+ metadata.gz: 93aba2d37108f5e0651d66ee8ac3361440616414fb48e88c80fe20bdc46b93d5f6a8e392800c6c00bfc91aaf473501cbfb246d4f63985f6fafa366e18af80529
7
+ data.tar.gz: b50d2da0703b9fabc8a81064ea019038d85bf8e61986b411bbec27af28024c53701dfa06126294f1ef1c3aa1dc175d699253f5d892c19fb8cacaa34ac56ddd24
@@ -1,6 +1,6 @@
1
1
  Count Name
2
2
  ======= ====
3
- 700 Thomas Leitner <t_leitner@gmx.at>
3
+ 720 Thomas Leitner <t_leitner@gmx.at>
4
4
  6 Gioele Barabucci <gioele@svario.it>
5
5
  4 Ted Pak <powerpak006@gmail.com>
6
6
  4 Arne Brasseur <arne@arnebrasseur.net>
@@ -30,5 +30,6 @@
30
30
  1 Luca Barbato <luca.barbato@gmail.com>
31
31
  1 John Croisant <jacius@gmail.com>
32
32
  1 Joe Fiorini <joe@faithfulgeek.org>
33
+ 1 Floreal Morandat florealm@gmail.com <florealm@gmail.com>
33
34
  1 Damien Pollet <damien.pollet@gmail.com>
34
35
  1 Alex Tomlins <alex.tomlins@digital.cabinet-office.gov.uk>
data/Rakefile CHANGED
@@ -177,8 +177,11 @@ EOF
177
177
  s.default_executable = 'kramdown'
178
178
  s.add_development_dependency 'minitest', '~> 5.0'
179
179
  s.add_development_dependency 'coderay', '~> 1.0.0'
180
+ s.add_development_dependency 'rouge', '~> 1.7'
180
181
  s.add_development_dependency 'stringex', '~> 1.5.1'
181
182
  s.add_development_dependency 'prawn', '~> 0.13'
183
+ s.add_development_dependency 'ritex', '~> 1.0'
184
+ s.add_development_dependency 'itextomml', '~> 1.5'
182
185
 
183
186
  #### Documentation
184
187
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.2
1
+ 1.5.0
@@ -11,6 +11,13 @@
11
11
  * [LaTeX](converter/latex.html)
12
12
  * [kramdown](converter/kramdown.html)
13
13
  * [RemoveHtmlTags](converter/remove_html_tags.html)
14
+ * Syntax Highlighters
15
+ * [Coderay](syntax_highlighter/coderay.html)
16
+ * [Rouge](syntax_highlighter/rouge.html)
17
+ * Math Engines
18
+ * [MathJax](math_engine/mathjax.html)
19
+ * [Ritex](math_engine/ritex.html)
20
+ * [itex2MML](math_engine/itex2mml.html)
14
21
  * [Configuration Options](options.html)
15
22
  * [Tests](tests.html)
16
23
 
@@ -1,7 +1,7 @@
1
1
  <h2>News</h2>
2
2
 
3
- <p>The latest version of kramdown is <span class="inline-important">1.4.2</span> and it was released
4
- on <span class="inline-important">2014-09-16</span></p>
3
+ <p>The latest version of kramdown is <span class="inline-important">1.5.0</span> and it was released
4
+ on <span class="inline-important">2014-10-25</span></p>
5
5
 
6
6
  <p>More <a href="{relocatable: news.html}">news</a>…</p>
7
7
 
@@ -1,2 +1,11 @@
1
1
  rdoc/index.html:
2
2
  title: API Documentation
3
+
4
+ /options.en.html#option-syntax-highlighter:
5
+ dest_path: options.html#option-syntax-highlighter
6
+
7
+ /options.en.html#option-syntax-highlighter-opts:
8
+ dest_path: options.html#option-syntax-highlighter-opts
9
+
10
+ /options.en.html#option-math-engine:
11
+ dest_path: options.html#option-math-engine
@@ -7,6 +7,8 @@
7
7
  #++
8
8
  #
9
9
 
10
+ require 'kramdown/utils'
11
+
10
12
  module Kramdown
11
13
 
12
14
  # This module contains all available converters, i.e. classes that take a root Element and convert
@@ -25,6 +27,43 @@ module Kramdown
25
27
  autoload :RemoveHtmlTags, 'kramdown/converter/remove_html_tags'
26
28
  autoload :Pdf, 'kramdown/converter/pdf'
27
29
 
30
+ extend ::Kramdown::Utils::Configurable
31
+
32
+ configurable(:syntax_highlighter)
33
+
34
+ ["Coderay", "Rouge"].each do |klass_name|
35
+ kn_down = klass_name.downcase.intern
36
+ add_syntax_highlighter(kn_down) do |converter, text, lang, type, opts|
37
+ require "kramdown/converter/syntax_highlighter/#{kn_down}"
38
+ klass = ::Kramdown::Utils.deep_const_get("::Kramdown::Converter::SyntaxHighlighter::#{klass_name}")
39
+ if klass::AVAILABLE
40
+ add_syntax_highlighter(kn_down, klass)
41
+ else
42
+ add_syntax_highlighter(kn_down) {|*args| nil}
43
+ end
44
+ syntax_highlighter(kn_down).call(converter, text, lang, type, opts)
45
+ end
46
+ end
47
+
48
+ configurable(:math_engine)
49
+
50
+ require 'kramdown/converter/math_engine/mathjax'
51
+ add_math_engine(:mathjax, ::Kramdown::Converter::MathEngine::Mathjax)
52
+
53
+ ["Ritex", "Itex2MML"].each do |klass_name|
54
+ kn_down = klass_name.downcase.intern
55
+ add_math_engine(kn_down) do |converter, el, opts|
56
+ require "kramdown/converter/math_engine/#{kn_down}"
57
+ klass = ::Kramdown::Utils.deep_const_get("::Kramdown::Converter::MathEngine::#{klass_name}")
58
+ if klass::AVAILABLE
59
+ add_math_engine(kn_down, klass)
60
+ else
61
+ add_math_engine(kn_down) {|*args| nil}
62
+ end
63
+ math_engine(kn_down).call(converter, el, opts)
64
+ end
65
+ end
66
+
28
67
  end
29
68
 
30
69
  end
@@ -196,6 +196,34 @@ module Kramdown
196
196
  lang
197
197
  end
198
198
 
199
+ # Highlight the given +text+ in the language +lang+ with the syntax highlighter configured
200
+ # through the option 'syntax_highlighter'.
201
+ def highlight_code(text, lang, type, opts = {})
202
+ return nil unless @options[:syntax_highlighter]
203
+
204
+ highlighter = ::Kramdown::Converter.syntax_highlighter(@options[:syntax_highlighter])
205
+ if highlighter
206
+ highlighter.call(self, text, lang, type, opts)
207
+ else
208
+ warning("The configured syntax highlighter #{@options[:syntax_highlighter]} is not available.")
209
+ nil
210
+ end
211
+ end
212
+
213
+ # Format the given math element with the math engine configured through the option
214
+ # 'math_engine'.
215
+ def format_math(el, opts = {})
216
+ return nil unless @options[:math_engine]
217
+
218
+ engine = ::Kramdown::Converter.math_engine(@options[:math_engine])
219
+ if engine
220
+ engine.call(self, el, opts)
221
+ else
222
+ warning("The configured math engine #{@options[:math_engine]} is not available.")
223
+ nil
224
+ end
225
+ end
226
+
199
227
  # Generate an unique alpha-numeric ID from the the string +str+ for use as a header ID.
200
228
  #
201
229
  # Uses the option +auto_id_prefix+: the value of this option is prepended to every generated
@@ -28,15 +28,6 @@ module Kramdown
28
28
  # HTML element.
29
29
  class Html < Base
30
30
 
31
- begin
32
- require 'coderay'
33
-
34
- # Highlighting via coderay is available if this constant is +true+.
35
- HIGHLIGHTING_AVAILABLE = true
36
- rescue LoadError
37
- HIGHLIGHTING_AVAILABLE = false # :nodoc:
38
- end
39
-
40
31
  include ::Kramdown::Utils::Html
41
32
  include ::Kramdown::Parser::Html::Constants
42
33
 
@@ -54,7 +45,6 @@ module Kramdown
54
45
  @toc_code = nil
55
46
  @indent = 2
56
47
  @stack = []
57
- @coderay_enabled = @options[:enable_coderay] && HIGHLIGHTING_AVAILABLE
58
48
  end
59
49
 
60
50
  # The mapping of element type to conversion method.
@@ -101,13 +91,11 @@ module Kramdown
101
91
  def convert_codeblock(el, indent)
102
92
  attr = el.attr.dup
103
93
  lang = extract_code_language!(attr)
104
- if @coderay_enabled && (lang || @options[:coderay_default_lang])
105
- opts = {:wrap => @options[:coderay_wrap], :line_numbers => @options[:coderay_line_numbers],
106
- :line_number_start => @options[:coderay_line_number_start], :tab_width => @options[:coderay_tab_width],
107
- :bold_every => @options[:coderay_bold_every], :css => @options[:coderay_css]}
108
- lang = (lang || @options[:coderay_default_lang]).to_sym
109
- result = CodeRay.scan(el.value, lang).html(opts).chomp << "\n"
110
- "#{' '*indent}<div#{html_attributes(attr)}>#{result}#{' '*indent}</div>\n"
94
+ highlighted_code = highlight_code(el.value, lang, :block)
95
+
96
+ if highlighted_code
97
+ add_syntax_highlighter_to_class_attr(attr)
98
+ "#{' '*indent}<div#{html_attributes(attr)}>#{highlighted_code}#{' '*indent}</div>\n"
111
99
  else
112
100
  result = escape_html(el.value)
113
101
  result.chomp!
@@ -261,13 +249,16 @@ module Kramdown
261
249
  end
262
250
 
263
251
  def convert_codespan(el, indent)
264
- lang = extract_code_language(el.attr)
265
- result = if @coderay_enabled && lang
266
- CodeRay.scan(el.value, lang.to_sym).html(:wrap => :span, :css => @options[:coderay_css]).chomp
267
- else
268
- escape_html(el.value)
269
- end
270
- format_as_span_html('code', el.attr, result)
252
+ attr = el.attr.dup
253
+ lang = extract_code_language(attr)
254
+ result = highlight_code(el.value, lang, :span)
255
+ if result
256
+ add_syntax_highlighter_to_class_attr(attr)
257
+ else
258
+ result = escape_html(el.value)
259
+ end
260
+
261
+ format_as_span_html('code', attr, result)
271
262
  end
272
263
 
273
264
  def convert_footnote(el, indent)
@@ -319,14 +310,12 @@ module Kramdown
319
310
  end
320
311
 
321
312
  def convert_math(el, indent)
322
- block = (el.options[:category] == :block)
323
- value = (el.value =~ /<|&/ ? "% <![CDATA[\n#{el.value} %]]>" : el.value)
324
- value.gsub!(/<\/?script>?/, '')
325
- type = {:type => "math/tex#{block ? '; mode=display' : ''}"}
326
- if block
327
- format_as_block_html('script', type, value, indent)
313
+ if (result = format_math(el, :indent => indent))
314
+ result
315
+ elsif el.options[:category] == :block
316
+ format_as_block_html('pre', el.attr, "$$\n#{el.value}\n$$", indent)
328
317
  else
329
- format_as_span_html('script', type, value)
318
+ format_as_span_html('span', el.attr, "$#{el.value}$")
330
319
  end
331
320
  end
332
321
 
@@ -370,6 +359,11 @@ module Kramdown
370
359
  "#{' '*indent}<#{name}#{html_attributes(attr)}>\n#{body}#{' '*indent}</#{name}>\n"
371
360
  end
372
361
 
362
+ # Add the syntax highlighter name to the 'class' attribute of the given attribute hash.
363
+ def add_syntax_highlighter_to_class_attr(attr)
364
+ (attr['class'] = (attr['class'] || '') + " highlighter-#{@options[:syntax_highlighter]}").lstrip!
365
+ end
366
+
373
367
  # Generate and return an element tree for the table of contents.
374
368
  def generate_toc_tree(toc, type, attr)
375
369
  sections = Element.new(type, nil, attr)
@@ -0,0 +1,39 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ module Kramdown::Converter::MathEngine
11
+
12
+ # Uses the Itex2MML library for converting math formulas to MathML.
13
+ module Itex2MML
14
+
15
+ begin
16
+ require 'itextomml'
17
+
18
+ # Itex2MML is available if this constant is +true+.
19
+ AVAILABLE = true
20
+ rescue LoadError
21
+ AVAILABLE = false # :nodoc:
22
+ end
23
+
24
+ def self.call(converter, el, opts)
25
+ type = el.options[:category]
26
+ parser = ::Itex2MML::Parser.new
27
+ result = (type == :block ? parser.block_filter(el.value) : parser.inline_filter(el.value))
28
+
29
+ attr = el.attr.dup
30
+ attr.delete('xmlns')
31
+ attr.delete('display')
32
+ result.insert("<math".length, converter.html_attributes(attr))
33
+
34
+ (type == :block ? "#{' '*opts[:indent]}#{result}\n" : result)
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ module Kramdown::Converter::MathEngine
11
+
12
+ # Uses the MathJax javascript library for displaying math.
13
+ #
14
+ # Note that the javascript library itself is not include or linked, this has to be done
15
+ # separately. Only the math content is marked up correctly.
16
+ module Mathjax
17
+
18
+ def self.call(converter, el, opts)
19
+ type = el.options[:category]
20
+ text = (el.value =~ /<|&/ ? "% <![CDATA[\n#{el.value} %]]>" : el.value)
21
+ text.gsub!(/<\/?script>?/, '')
22
+
23
+ attr = {:type => "math/tex#{type == :block ? '; mode=display' : ''}"}
24
+ if type == :block
25
+ converter.format_as_block_html('script', attr, text, opts[:indent])
26
+ else
27
+ converter.format_as_span_html('script', attr, text)
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,38 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ module Kramdown::Converter::MathEngine
11
+
12
+ # Uses the Ritex library for converting math formulas to MathML.
13
+ module Ritex
14
+
15
+ begin
16
+ require 'ritex'
17
+
18
+ # Ritex is available if this constant is +true+.
19
+ AVAILABLE = true
20
+ rescue LoadError
21
+ AVAILABLE = false # :nodoc:
22
+ end
23
+
24
+ def self.call(converter, el, opts)
25
+ type = el.options[:category]
26
+ result = ::Ritex::Parser.new.parse(el.value, :display => (type == :block))
27
+
28
+ attr = el.attr.dup
29
+ attr.delete('xmlns')
30
+ attr.delete('display')
31
+ result.insert("<math".length, converter.html_attributes(attr))
32
+
33
+ (type == :block ? "#{' '*opts[:indent]}#{result}\n" : result)
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,78 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ #--
4
+ # Copyright (C) 2009-2014 Thomas Leitner <t_leitner@gmx.at>
5
+ #
6
+ # This file is part of kramdown which is licensed under the MIT.
7
+ #++
8
+ #
9
+
10
+ module Kramdown::Converter::SyntaxHighlighter
11
+
12
+ # Uses Coderay to highlight code blocks and code spans.
13
+ module Coderay
14
+
15
+ begin
16
+ require 'coderay'
17
+
18
+ # Highlighting via coderay is available if this constant is +true+.
19
+ AVAILABLE = true
20
+ rescue LoadError
21
+ AVAILABLE = false # :nodoc:
22
+ end
23
+
24
+ def self.call(converter, text, lang, type, _unused_opts)
25
+ return nil unless converter.options[:enable_coderay]
26
+
27
+ if type == :span && lang
28
+ ::CodeRay.scan(text, lang.to_sym).html(options(converter, :span)).chomp
29
+ elsif type == :block && (lang || options(converter, :default_lang))
30
+ lang = (lang || options(converter, :default_lang)).to_sym
31
+ ::CodeRay.scan(text, lang).html(options(converter, :block)).chomp << "\n"
32
+ else
33
+ nil
34
+ end
35
+ end
36
+
37
+ def self.options(converter, type)
38
+ prepare_options(converter)
39
+ converter.data[:syntax_highlighter_coderay][type]
40
+ end
41
+
42
+ def self.prepare_options(converter)
43
+ return if converter.data.key?(:syntax_highlighter_coderay)
44
+
45
+ cache = converter.data[:syntax_highlighter_coderay] = {}
46
+
47
+ opts = converter.options[:syntax_highlighter_opts].dup
48
+ span_opts = (opts.delete(:span) || {}).dup
49
+ block_opts = (opts.delete(:block) || {}).dup
50
+ [span_opts, block_opts].each do |hash|
51
+ hash.keys.each do |k|
52
+ hash[k.kind_of?(String) ? Kramdown::Options.str_to_sym(k) : k] = hash.delete(k)
53
+ end
54
+ end
55
+
56
+ cache[:default_lang] = converter.options[:coderay_default_lang] || opts.delete(:default_lang)
57
+ cache[:span] = {
58
+ :css => converter.options[:coderay_css]
59
+ }.update(opts).update(span_opts).update(:wrap => :span)
60
+ cache[:block] = {
61
+ :wrap => converter.options[:coderay_wrap],
62
+ :line_numbers => converter.options[:coderay_line_numbers],
63
+ :line_number_start => converter.options[:coderay_line_number_start],
64
+ :tab_width => converter.options[:coderay_tab_width],
65
+ :bold_every => converter.options[:coderay_bold_every],
66
+ :css => converter.options[:coderay_css]
67
+ }.update(opts).update(block_opts)
68
+
69
+ [:css, :wrap, :line_numbers].each do |key|
70
+ [:block, :span].each do |type|
71
+ cache[type][key] = cache[type][key].to_sym if cache[type][key].kind_of?(String)
72
+ end
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ end