maruku 0.4.2.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. data/bin/maruku +66 -20
  2. data/bin/marutest +12 -2
  3. data/docs/changelog.html +188 -23
  4. data/docs/changelog.md +128 -5
  5. data/docs/entity_test.html +245 -240
  6. data/docs/entity_test.md +2 -0
  7. data/docs/exd.html +181 -23
  8. data/docs/index.html +130 -349
  9. data/docs/markdown_syntax.html +55 -51
  10. data/docs/maruku.html +130 -349
  11. data/docs/maruku.md +154 -339
  12. data/docs/math.md +143 -0
  13. data/docs/proposal.html +16 -12
  14. data/lib/maruku.rb +6 -3
  15. data/lib/maruku/attributes.rb +7 -2
  16. data/lib/maruku/defaults.rb +27 -27
  17. data/lib/maruku/errors_management.rb +10 -9
  18. data/lib/maruku/ext/diagrams/diagrams.rb +8 -0
  19. data/lib/maruku/ext/diagrams/grid.rb +78 -0
  20. data/lib/maruku/ext/diagrams/inspect.rb +11 -0
  21. data/lib/maruku/ext/diagrams/layout.rb +105 -0
  22. data/lib/maruku/ext/diagrams/parser.rb +219 -0
  23. data/lib/maruku/ext/diagrams/structures.rb +168 -0
  24. data/lib/maruku/ext/diagrams/to_html.rb +37 -0
  25. data/lib/maruku/ext/diagrams/to_latex.rb +308 -0
  26. data/lib/maruku/ext/diagrams/unittest.rb +123 -0
  27. data/lib/maruku/ext/math.rb +11 -0
  28. data/lib/maruku/ext/math/elements.rb +26 -0
  29. data/lib/maruku/ext/math/mathml_engines/blahtex.rb +108 -0
  30. data/lib/maruku/ext/math/mathml_engines/itex2mml.rb +29 -0
  31. data/lib/maruku/ext/math/mathml_engines/none.rb +20 -0
  32. data/lib/maruku/ext/math/mathml_engines/ritex.rb +24 -0
  33. data/lib/maruku/ext/math/parsing.rb +82 -0
  34. data/lib/maruku/ext/math/to_html.rb +178 -0
  35. data/lib/maruku/ext/math/to_latex.rb +21 -0
  36. data/lib/maruku/helpers.rb +11 -0
  37. data/lib/maruku/input/charsource.rb +1 -1
  38. data/lib/maruku/input/extensions.rb +68 -0
  39. data/lib/maruku/input/html_helper.rb +91 -60
  40. data/lib/maruku/input/parse_block.rb +10 -9
  41. data/lib/maruku/input/parse_doc.rb +21 -13
  42. data/lib/maruku/input/parse_span_better.rb +19 -8
  43. data/lib/maruku/input/type_detection.rb +5 -3
  44. data/lib/maruku/output/to_html.rb +236 -67
  45. data/lib/maruku/output/to_latex.rb +69 -26
  46. data/lib/maruku/output/to_latex_entities.rb +14 -2
  47. data/lib/maruku/output/to_s.rb +8 -0
  48. data/lib/maruku/structures.rb +1 -1
  49. data/lib/maruku/tests/benchmark.rb +2 -2
  50. data/lib/maruku/tests/new_parser.rb +13 -5
  51. data/lib/maruku/version.rb +1 -1
  52. data/lib/sort_prof.rb +22 -0
  53. data/tests/diagrams/diagrams.md +54 -0
  54. data/tests/math/syntax.md +46 -0
  55. data/tests/math_usage/document.md +13 -0
  56. data/tests/unittest/attributes/attributes.md +50 -6
  57. data/tests/unittest/easy.md +1 -1
  58. data/tests/unittest/email.md +3 -3
  59. data/tests/unittest/entities.md +12 -7
  60. data/tests/unittest/escaping.md +4 -4
  61. data/tests/unittest/extra_table1.md +3 -1
  62. data/tests/unittest/footnotes.md +5 -5
  63. data/tests/unittest/headers.md +3 -3
  64. data/tests/unittest/images.md +7 -7
  65. data/tests/unittest/inline_html.md +51 -5
  66. data/tests/unittest/links.md +7 -7
  67. data/tests/unittest/list2.md +1 -1
  68. data/tests/unittest/lists.md +1 -1
  69. data/tests/unittest/lists_after_paragraph.md +1 -1
  70. data/tests/unittest/lists_ol.md +1 -1
  71. data/tests/unittest/math/equations.md +82 -0
  72. data/tests/unittest/math/inline.md +80 -0
  73. data/tests/unittest/math/table.md +51 -0
  74. data/tests/unittest/math/table2.md +67 -0
  75. data/tests/unittest/misc_sw.md +24 -24
  76. data/tests/unittest/notyet/ticks.md +1 -1
  77. data/tests/unittest/references/long_example.md +2 -2
  78. data/tests/unittest/smartypants.md +4 -4
  79. data/tests/unittest/xml.md +68 -0
  80. data/tests/unittest/xml2.md +36 -0
  81. data/tests/unittest/xml3.md +52 -0
  82. data/tests/unittest/xml_instruction.md +5 -5
  83. metadata +33 -4
  84. data/docs/a.html +0 -6
  85. data/docs/char.html +0 -1924
@@ -0,0 +1,21 @@
1
+
2
+ module MaRuKu; module Out; module Latex
3
+
4
+ def to_latex_inline_math
5
+ "$#{self.math.strip}$"
6
+ end
7
+
8
+ def to_latex_equation
9
+ if self.label
10
+ l = "\\label{#{self.label}}"
11
+ "\\begin{equation}\n#{self.math.strip}\n#{l}\\end{equation}\n"
12
+ else
13
+ "\\begin{displaymath}\n#{self.math.strip}\n\\end{displaymath}\n"
14
+ end
15
+ end
16
+
17
+ def to_latex_eqref
18
+ "\\eqref{#{self.eqid}}"
19
+ end
20
+
21
+ end end end
@@ -30,7 +30,17 @@
30
30
  module MaRuKu
31
31
  module Helpers
32
32
 
33
+ # if the first is a md_ial, it is used as such
33
34
  def md_el(node_type, children=[], meta={}, al=nil)
35
+ if (e=children.first).kind_of?(MDElement) and
36
+ e.node_type == :ial then
37
+ if al
38
+ al += e.ial
39
+ else
40
+ al = e.ial
41
+ end
42
+ children.shift
43
+ end
34
44
  e = MDElement.new(node_type, children, meta, al)
35
45
  e.doc = @doc
36
46
  return e
@@ -173,6 +183,7 @@ module Helpers
173
183
  def md_xml_instr(target, code)
174
184
  md_el(:xml_instr, [], {:target=>target, :code=>code})
175
185
  end
186
+
176
187
  end
177
188
  end
178
189
 
@@ -33,8 +33,8 @@ class CharSourceDebug; end
33
33
 
34
34
  # Choose!
35
35
 
36
- #CharSource = CharSourceStrscan
37
36
  CharSource = CharSourceManual # faster! 58ms vs. 65ms
37
+ #CharSource = CharSourceStrscan
38
38
  #CharSource = CharSourceDebug
39
39
 
40
40
 
@@ -0,0 +1,68 @@
1
+ module MaRuKu; module In; module Markdown
2
+
3
+
4
+ # Hash Fixnum -> name
5
+ SpanExtensionsTrigger = {}
6
+
7
+
8
+ class SpanExtension
9
+ # trigging chars
10
+ attr_accessor :chars
11
+ # trigging regexp
12
+ attr_accessor :regexp
13
+ # lambda
14
+ attr_accessor :block
15
+ end
16
+
17
+ # Hash String -> Extension
18
+ SpanExtensions = {}
19
+
20
+ def check_span_extensions(src, con)
21
+ c = src.cur_char
22
+ if extensions = SpanExtensionsTrigger[c]
23
+ extensions.each do |e|
24
+ if e.regexp && (match = src.next_matches(e.regexp))
25
+ return true if e.block.call(doc, src, con)
26
+ end
27
+ end
28
+ end
29
+ return false # not special
30
+ end
31
+
32
+ def self.register_span_extension(args, &block)
33
+ e = SpanExtension.new
34
+ e.chars = [*args[:chars]]
35
+ e.regexp = args[:regexp]
36
+ e.block = block
37
+ e.chars.each do |c|
38
+ (SpanExtensionsTrigger[c] ||= []).push e
39
+ end
40
+ end
41
+
42
+ def self.register_block_extension(args, &block)
43
+ regexp = args[:regexp]
44
+ BlockExtensions[regexp] = block
45
+ end
46
+
47
+ # Hash Regexp -> Block
48
+ BlockExtensions = {}
49
+
50
+ def check_block_extensions(src, con, line)
51
+ BlockExtensions.each do |reg, block|
52
+ if m = reg.match(line)
53
+ block = BlockExtensions[reg]
54
+ return true if block.call(doc, src, con)
55
+ end
56
+ end
57
+ return false # not special
58
+ end
59
+
60
+ def any_matching_block_extension?(line)
61
+ BlockExtensions.each_key do |reg|
62
+ m = reg.match(line)
63
+ return m if m
64
+ end
65
+ return false
66
+ end
67
+
68
+ end end end
@@ -29,12 +29,13 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
29
29
  include MaRuKu::Strings
30
30
 
31
31
  Tag = %r{^<(/)?(\w+)\s*([^>]*)>}m
32
+ PartialTag = %r{^<.*}m
33
+
32
34
  EverythingElse = %r{^[^<]+}m
33
35
  CommentStart = %r{^<!--}x
34
36
  CommentEnd = %r{^.*-->}
35
37
  TO_SANITIZE = ['img','hr']
36
38
 
37
- # attr_accessor :inside_comment
38
39
  attr_reader :rest
39
40
 
40
41
  def initialize
@@ -42,72 +43,61 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
42
43
  @tag_stack = []
43
44
  @m = nil
44
45
  @already = ""
45
- @inside_comment = false
46
+ self.state = :inside_element
46
47
  end
48
+
49
+ attr_accessor :state # :inside_element, :inside_tag, :inside_comment,
47
50
 
48
51
  def eat_this(line)
49
52
  @rest = line + @rest
50
53
  things_read = 0
51
54
  until @rest.empty?
52
- if @inside_comment
53
- if @m = CommentEnd.match(@rest)
54
- @inside_comment = false
55
- @already += @m.pre_match + @m.to_s
56
- @rest = @m.post_match
57
- elsif @m = EverythingElse.match(@rest)
58
- @already += @m.pre_match + @m.to_s
59
- @rest = @m.post_match
60
- end
61
- else
62
- if @m = CommentStart.match(@rest)
63
- things_read += 1
64
- @inside_comment = true
65
- @already += @m.pre_match + @m.to_s
66
- @rest = @m.post_match
67
- elsif @m = Tag.match(@rest)
68
- things_read += 1
69
- @already += @m.pre_match
70
- @rest = @m.post_match
71
-
72
- is_closing = !!@m[1]
73
- tag = @m[2]
74
- attributes = @m[3]
75
-
76
- is_single = false
77
- if attributes =~ /\A(.*)\/\Z/
78
- attributes = $1
79
- is_single = true
55
+ case self.state
56
+ when :inside_comment
57
+ if @m = CommentEnd.match(@rest)
58
+ @already += @m.pre_match + @m.to_s
59
+ @rest = @m.post_match
60
+ self.state = :inside_element
61
+ else
62
+ @already += @rest
63
+ @rest = ""
64
+ self.state = :inside_comment
80
65
  end
81
-
82
- if TO_SANITIZE.include? tag
83
- attributes.strip!
84
- # puts "Attributes: #{attributes.inspect}"
85
- if attributes.size > 0
86
- @already += '<%s %s />' % [tag, attributes]
87
- else
88
- @already += '<%s />' % [tag]
89
- end
90
- elsif is_closing
91
- @already += @m.to_s
92
- if @tag_stack.empty?
93
- error "Malformed: closing tag #{tag.inspect} "+
94
- "in empty list"
95
- end
96
- if @tag_stack.last != tag
97
- error "Malformed: tag <#{tag}> "+
98
- "closes <#{@tag_stack.last}>"
99
- end
100
- @tag_stack.pop
101
- elsif not is_single
102
- @tag_stack.push tag
103
- @already += @m.to_s
66
+ when :inside_element
67
+ if @m = CommentStart.match(@rest)
68
+ things_read += 1
69
+ @already += @m.pre_match + @m.to_s
70
+ @rest = @m.post_match
71
+ self.state = :inside_comment
72
+ elsif @m = Tag.match(@rest) then
73
+ things_read += 1
74
+ handle_tag
75
+ self.state = :inside_element
76
+ elsif @m = PartialTag.match(@rest) then
77
+ @already += @m.pre_match
78
+ @rest = @m.post_match
79
+ @partial_tag = @m.to_s
80
+ self.state = :inside_tag
81
+ elsif @m = EverythingElse.match(@rest)
82
+ @already += @m.pre_match + @m.to_s
83
+ @rest = @m.post_match
84
+ self.state = :inside_element
85
+ else
86
+ error "Malformed HTML: not complete: #{@rest.inspect}"
87
+ end
88
+ when :inside_tag
89
+ if @m = /^[^>]*>/.match(@rest) then
90
+ @partial_tag += @m.to_s
91
+ @rest = @partial_tag + @m.post_match
92
+ @partial_tag = nil
93
+ self.state = :inside_element
94
+ else
95
+ @partial_tag += @rest
96
+ @rest = ""
97
+ self.state = :inside_tag
104
98
  end
105
- elsif @m = EverythingElse.match(@rest)
106
- @already += @m.pre_match + @m.to_s
107
- @rest = @m.post_match
108
99
  else
109
- error "Malformed HTML: not complete: #{@rest.inspect}"
110
- end
100
+ raise "Bug bug: state = #{self.state.inspect}"
111
101
  end # not inside comment
112
102
 
113
103
  # puts inspect
@@ -116,12 +106,53 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
116
106
  end
117
107
  end
118
108
 
109
+ def handle_tag()
110
+ @already += @m.pre_match
111
+ @rest = @m.post_match
112
+
113
+ is_closing = !!@m[1]
114
+ tag = @m[2]
115
+ attributes = @m[3]
116
+
117
+
118
+ is_single = false
119
+ if attributes =~ /\A(.*)\/\Z/
120
+ attributes = $1
121
+ is_single = true
122
+ end
119
123
 
124
+ # puts "READ TAG #{@m.to_s.inspect} tag = #{tag} closing? #{is_closing} single = #{is_single}"
125
+
126
+ if TO_SANITIZE.include? tag
127
+ attributes.strip!
128
+ # puts "Attributes: #{attributes.inspect}"
129
+ if attributes.size > 0
130
+ @already += '<%s %s />' % [tag, attributes]
131
+ else
132
+ @already += '<%s />' % [tag]
133
+ end
134
+ elsif is_closing
135
+ @already += @m.to_s
136
+ if @tag_stack.empty?
137
+ error "Malformed: closing tag #{tag.inspect} "+
138
+ "in empty list"
139
+ end
140
+ if @tag_stack.last != tag
141
+ error "Malformed: tag <#{tag}> "+
142
+ "closes <#{@tag_stack.last}>"
143
+ end
144
+ @tag_stack.pop
145
+ else
146
+ @already += @m.to_s
147
+
148
+ @tag_stack.push(tag) unless is_single
149
+ end
150
+ end
120
151
  def error(s)
121
152
  raise Exception, "Error: #{s} \n"+ inspect, caller
122
153
  end
123
154
 
124
- def inspect; "HTML READER\n comment=#{@inside_comment} "+
155
+ def inspect; "HTML READER\n state=#{self.state} "+
125
156
  "match=#{@m.to_s.inspect}\n"+
126
157
  "Tag stack = #{@tag_stack.inspect} \n"+
127
158
  "Before:\n"+
@@ -137,7 +168,7 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
137
168
  end
138
169
 
139
170
  def is_finished?
140
- not @inside_comment and @tag_stack.empty?
171
+ (self.state == :inside_element) and @tag_stack.empty?
141
172
  end
142
173
  end # html helper
143
174
 
@@ -47,6 +47,9 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
47
47
 
48
48
  # run state machine
49
49
  while src.cur_line
50
+
51
+ next if check_block_extensions(src, output, src.cur_line)
52
+
50
53
  # Prints detected type (useful for debugging)
51
54
  # puts "#{src.cur_line.md_type}|#{src.cur_line}"
52
55
  case src.cur_line.md_type
@@ -56,6 +59,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
56
59
  when :ial
57
60
  m = InlineAttributeList.match src.shift_line
58
61
  content = m[1] || ""
62
+ # puts "Content: #{content.inspect}"
59
63
  src2 = CharSource.new(content, src)
60
64
  interpret_extension(src2, output, [nil])
61
65
  when :ald
@@ -101,7 +105,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
101
105
  when :ref_definition; output.push read_ref_definition(src)
102
106
  when :abbreviation; output.push read_abbreviation(src)
103
107
  when :xml_instr; read_xml_instruction(src, output)
104
- # # these do not produce output
105
108
  when :metadata;
106
109
  maruku_error "Please use the new meta-data syntax: \n"+
107
110
  " http://maruku.rubyforge.org/proposal.html\n", src
@@ -145,7 +148,8 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
145
148
 
146
149
  output
147
150
  end
148
-
151
+
152
+
149
153
 
150
154
  def read_ald(src)
151
155
  if (l=src.shift_line) =~ AttributeDefinitionList
@@ -246,18 +250,15 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
246
250
  break
247
251
  when :olist,:ulist
248
252
  break if src.next_line.md_type == t
249
- else
250
- true
251
253
  end
252
-
253
- break if src.cur_line.strip.size == 0
254
-
254
+ break if src.cur_line.strip.size == 0
255
255
  break if [:header1,:header2].include? src.next_line.md_type
256
+ break if any_matching_block_extension?(src.cur_line)
256
257
 
257
258
  lines << src.shift_line
258
259
  end
259
260
  # dbg_describe_ary(lines, 'PAR')
260
- children = parse_lines_as_span(lines)
261
+ children = parse_lines_as_span(lines, src)
261
262
 
262
263
  return md_par(children)
263
264
  end
@@ -468,7 +469,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
468
469
  end
469
470
 
470
471
  id = match[1]; url = match[2]; title = match[3];
471
- id = id.strip.downcase
472
+ id = id.strip.downcase.gsub(' ','_')
472
473
 
473
474
  hash = self.refs[id] = {:url=>url,:title=>title}
474
475
 
@@ -84,7 +84,8 @@ Conversion happens using the `iconv` library.
84
84
  end
85
85
 
86
86
  =begin maruku_doc
87
- Variable: Maruku::Globals[:unsafe_features]
87
+ Attribute: unsafe_features
88
+ Scope: global
88
89
  Summary: Enables execution of XML instructions.
89
90
 
90
91
  Disabled by default because of security concerns.
@@ -181,6 +182,7 @@ Disabled by default because of security concerns.
181
182
  end
182
183
  end
183
184
 
185
+ include REXML
184
186
  # (PHP Markdown extra) Search for elements that have
185
187
  # markdown=1 or markdown=block defined
186
188
  def substitute_markdown_inside_raw_html
@@ -189,27 +191,33 @@ Disabled by default because of security concerns.
189
191
  if doc # valid html
190
192
  # parse block-level markdown elements in these HTML tags
191
193
  block_tags = ['div']
194
+
192
195
  # use xpath to find elements with 'markdown' attribute
193
- doc.elements.to_a( "//*[attribute::markdown]" ).each do |e|
196
+ XPath.match(doc, "//*[attribute::markdown]" ).each do |e|
197
+ # puts "Found #{e}"
194
198
  # should we parse block-level or span-level?
195
199
  parse_blocks = (e.attributes['markdown'] == 'block') ||
196
200
  block_tags.include?(e.name)
197
201
  # remove 'markdown' attribute
198
202
  e.delete_attribute 'markdown'
199
203
  # Select all text elements of e
200
- e.texts.each do |original_text|
201
- # puts "parse_blocks = #{parse_blocks} found = #{original_text} "
202
- s = original_text.to_s.strip # XXX
203
- el = md_el(:dummy,
204
- parse_blocks ? parse_text_as_markdown(s) :
205
- parse_lines_as_span([s]) )
206
- el.children_to_html.each do |x|
207
- e.insert_before(original_text, x)
204
+ XPath.match(e, "//text()" ).each { |original_text|
205
+ s = original_text.value.strip
206
+ if s.size > 0
207
+ el = md_el(:dummy,
208
+ parse_blocks ? parse_text_as_markdown(s) :
209
+ parse_lines_as_span([s]) )
210
+ p = original_text.parent
211
+ el.children_to_html.each do |x|
212
+ p.insert_before(original_text, x)
213
+ end
214
+ p.delete(original_text)
215
+
208
216
  end
209
- e.delete(original_text)
210
- end
211
-
217
+ }
218
+
212
219
  end
220
+
213
221
  end
214
222
  end
215
223
  end