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,11 @@
1
+ module Diagrams
2
+
3
+ class Arrow
4
+ def inspect
5
+ "Arrow (#{(@cap1||?-).chr},#{(@cap2||?-).chr}) "+
6
+ "from #{@start_link.class} to #{@end_link.class} "+
7
+ " #{@start_pos.inspect} -> #{@end_pos.inspect}"
8
+ end
9
+ end
10
+
11
+ end
@@ -0,0 +1,105 @@
1
+ module Diagrams
2
+
3
+ class Diagram
4
+ DIAG_TL = "tl"
5
+ DIAG_BR = "br"
6
+
7
+ def do_layout(diag_id)
8
+ def margin_con() Spring.new(30,0,30,1,1000) end
9
+ def arrow_con() Spring.new(30,1,60,100,1000) end
10
+ def zero_con() Spring.new(0,0,0,0,0) end
11
+ def positive_con(pref) Spring.new(0,1,pref,1000,1000) end
12
+
13
+ @diag_id = diag_id
14
+ assign_variables(diag_id)
15
+
16
+ l = Layout.new
17
+ @boxes.each do |b|
18
+ # size of the box is copied from b.hs and b.vs
19
+ l.add_con_h(b.v_tl, b.v_br, b.hs)
20
+ l.add_con_v(b.v_tl, b.v_br, b.vs)
21
+ # should not be outside of the diagram
22
+ l.add_con_h(DIAG_TL, b.v_tl, margin_con)
23
+ l.add_con_h(b.v_br, DIAG_BR, margin_con)
24
+ l.add_con_v(DIAG_TL, b.v_tl, margin_con)
25
+ l.add_con_v(b.v_br, DIAG_BR, margin_con)
26
+ # now, for each arrow
27
+ b.links[:N].each{|a|
28
+ l.add_con_v(a.v_end, b.v_tl, zero_con)
29
+ l.add_con_h(b.v_tl, a.v_end, positive_con(b.hs.pref/2))
30
+ l.add_con_h(a.v_end, b.v_br, positive_con(b.hs.pref/2))
31
+ }
32
+ b.links[:S].each{|a|
33
+ l.add_con_v(b.v_br, a.v_start, zero_con)
34
+ l.add_con_h(b.v_tl, a.v_start, positive_con(b.hs.pref/2))
35
+ l.add_con_h(a.v_start, b.v_br, positive_con(b.hs.pref/2))
36
+ }
37
+ b.links[:W].each{|a|
38
+ l.add_con_h(a.v_end, b.v_tl, zero_con)
39
+ l.add_con_v(b.v_tl, a.v_end, positive_con(b.vs.pref/2))
40
+ l.add_con_v(a.v_end, b.v_br, positive_con(b.vs.pref/2))
41
+ }
42
+ b.links[:E].each{|a|
43
+ l.add_con_h(b.v_br, a.v_start, zero_con)
44
+ l.add_con_v(b.v_tl, a.v_start, positive_con(b.vs.pref/2))
45
+ l.add_con_v(a.v_start, b.v_br, positive_con(b.vs.pref/2))
46
+ }
47
+
48
+ b.aligned[:t].each do |b2| l.add_con_v(b2.v_tl, b.v_tl, zero_con) end
49
+ b.aligned[:b].each do |b2| l.add_con_v(b2.v_br, b.v_br, zero_con) end
50
+ b.aligned[:l].each do |b2| l.add_con_h(b2.v_tl, b.v_tl, zero_con) end
51
+ b.aligned[:r].each do |b2| l.add_con_h(b2.v_br, b.v_br, zero_con) end
52
+ end
53
+
54
+ @points.each do |p|
55
+ # should not be outside of the diagram
56
+ l.add_con_h(DIAG_TL, p.v_p, margin_con)
57
+ l.add_con_h(p.v_p, DIAG_BR, margin_con)
58
+ l.add_con_v(DIAG_TL, p.v_p, margin_con)
59
+ l.add_con_v(p.v_p, DIAG_BR, margin_con)
60
+ # now, for each arrow
61
+ p.links[:N].each{|a|
62
+ l.add_con_v(a.v_end, p.v_p, zero_con)
63
+ l.add_con_h(a.v_end, p.v_p, zero_con)
64
+ }
65
+ p.links[:S].each{|a|
66
+ l.add_con_v(p.v_p, a.v_start, zero_con)
67
+ l.add_con_h(p.v_p, a.v_start, zero_con)
68
+ }
69
+ p.links[:W].each{|a|
70
+ l.add_con_h(a.v_end, p.v_p, zero_con)
71
+ l.add_con_v(a.v_end, p.v_p, zero_con)
72
+ }
73
+ p.links[:E].each{|a|
74
+ l.add_con_h(p.v_p, a.v_start, zero_con)
75
+ l.add_con_v(p.v_p, a.v_start, zero_con)
76
+ }
77
+
78
+ p.aligned[:t].each do |p2| l.add_con_v(p2.v_p, p.v_p, zero_con) end
79
+ p.aligned[:l].each do |p2| l.add_con_h(p2.v_p, p.v_p, zero_con) end
80
+ end
81
+
82
+ @arrows.each do |a|
83
+ if a.is_vert?
84
+ l.add_con_v(a.v_start, a.v_end, arrow_con)
85
+ l.add_con_h(a.v_start, a.v_end, zero_con)
86
+ else
87
+ l.add_con_h(a.v_start, a.v_end, arrow_con)
88
+ l.add_con_v(a.v_start, a.v_end, zero_con)
89
+ end
90
+ end
91
+
92
+ doth, dotv = l.to_dot
93
+ File.open("#{diag_id}_h.dot",'w') do |f| f.write doth end
94
+ File.open("#{diag_id}_v.dot",'w') do |f| f.write dotv end
95
+
96
+ # hs, vs = l.get_preferred(DIAG_TL, DIAG_BR)
97
+
98
+ # puts "Preferred hs = #{hs.inspect}"
99
+ # puts "Preferred vs = #{vs.inspect}"
100
+ end
101
+
102
+ end
103
+
104
+
105
+ end
@@ -0,0 +1,219 @@
1
+ module Diagrams
2
+
3
+ class Diagram
4
+ def create_grid_from_string(string)
5
+ lines = string.split("\n").map{|x| x.gsub(/\s*$/,'') }
6
+
7
+ while lines.first && lines.first.strip.size == 0; lines.shift end
8
+ while lines.last && lines.last.strip.size == 0; lines.pop end
9
+ width = lines.map{|x| x.size}.max
10
+ height = lines.size
11
+
12
+ grid = Grid.new(width, height, 32)
13
+ for y in 0..height-1
14
+ for x in 0..width-1
15
+ grid.set(x, y, lines[y][x])
16
+ end
17
+ end
18
+ grid
19
+ end
20
+
21
+
22
+ def detect_points
23
+ [?+, ?*].each do |p|
24
+ for_each_to_process(p) do |x,y|
25
+ point = Point.new
26
+ point.pos = [x, y]
27
+ point.char = p
28
+ @to_process.set(x,y,false)
29
+ @points.push point
30
+ @occup.set(x,y, point)
31
+ end
32
+ end
33
+
34
+ @points.each do |p1|
35
+ @points.each do |p2|
36
+ if p1 != p2
37
+ if p2.pos.x < p1.pos.x
38
+ p1.aligned[:t].push(p2) if p2.pos.y == p1.pos.y
39
+ end
40
+ if p2.pos.y < p1.pos.y
41
+ p1.aligned[:l].push(p2) if p2.pos.x == p1.pos.x
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ def detect_arrows
49
+ [ [?|, /^\|*$/, [?^, ?A], [?v, ?V], 0, 1, :S],
50
+ [?-, /^\-*$/, [?<], [?>], 1, 0, :E],
51
+ [?\\,/^\\*$/, [], [], 1, 1, :SE],
52
+ [?/, /^\/*$/, [], [], -1, 1, :SW]
53
+ ].each do |char, reg, cap1, cap2, inc_x, inc_y, ty|
54
+ for_each_to_process(char) do |x,y,e|
55
+ find_arrow(x, y, reg, cap1, cap2, inc_x, inc_y)
56
+ end
57
+ end
58
+ end
59
+
60
+
61
+ def find_arrow(x, y, reg, cap1, cap2, inc_x, inc_y)
62
+ inc = [inc_x, inc_y]
63
+ rinc = [-inc_x, -inc_y]
64
+
65
+ a = Arrow.new
66
+
67
+ if cap1.include?(c = @text.get(x-inc_x, y-inc_y))
68
+ a.cap1 = c
69
+ a.start_pos = [x-inc_x, y-inc_y]
70
+ else
71
+ a.cap1 = nil
72
+ a.start_pos = [x,y]
73
+ end
74
+
75
+ s = match(x,y,reg,inc_x,inc_y)
76
+ len = s.size
77
+
78
+ a.end_pos = [x+(len-1)*inc_x, y+(len-1)*inc_y]
79
+ maybe_cap = [x+(len)*inc_x, y+(len)*inc_y]
80
+ if cap2.include?(c=@text.get(*maybe_cap))
81
+ len +=1
82
+ a.end_pos = maybe_cap
83
+ a.cap2 = c
84
+ else
85
+ a.cap2 = nil
86
+ end
87
+
88
+ a.length = len
89
+
90
+ before = [a.start_pos[0]-inc_x,a.start_pos[1]-inc_y]
91
+ if ob = @occup.get(*before)
92
+ impact = ob.link_direction(before, rinc)
93
+ ob.links[impact] << a
94
+ a.links[Reverse[impact]]<< ob
95
+ a.start_link = ob
96
+ else
97
+ puts "Nothing found at #{before.inspect} : #{
98
+ @text.get(*before)
99
+ } while #{@text.get(*a.start_pos).chr}"
100
+ end
101
+ after = [a.end_pos[0]+inc_x,a.end_pos[1]+inc_y]
102
+ if ob = @occup.get(*after)
103
+ impact = ob.link_direction(after, inc)
104
+ ob.links[impact] << a
105
+ a.links[Reverse[impact]] << ob
106
+ a.end_link = ob
107
+ else
108
+ puts "Nothing found at #{after.inspect} : #{
109
+ @text.get(*after)
110
+ } while #{@text.get(*a.end_pos).chr}"
111
+ end
112
+
113
+ iterate(a.start_pos,a.end_pos) do |x,y|
114
+ @to_process.set(x,y,false)
115
+ @occup.set(x,y,a)
116
+ end
117
+
118
+ @arrows.push a
119
+ p a
120
+ end
121
+
122
+ def iterate(pos1,pos2)
123
+ inc_x = pos2[0]-pos1[0]
124
+ inc_y = pos2[1]-pos1[1]
125
+ len = [inc_x.abs,inc_y.abs].max + 1
126
+ if inc_x.abs > inc_y.abs
127
+ len = inc_x.abs + 1
128
+ else
129
+ len = inc_y.abs + 1
130
+ end
131
+
132
+ inc_x /= inc_x.abs if inc_x != 0
133
+ inc_y /= inc_y.abs if inc_y != 0
134
+
135
+ # raise "" if inc_x
136
+ for i in 0..(len-1)
137
+ x, y = pos1[0]+i*inc_x,pos1[1]+i*inc_y
138
+ yield x,y
139
+ end
140
+ end
141
+
142
+ def detect_boxes
143
+ for_each_to_process(?+) do |x,y,e|
144
+ find_box(x,y,/^\+[\-\+]+\+$/, /^\+[\|\+]+\+$/)
145
+ end
146
+ for_each_to_process(?/) do |x,y,e|
147
+ find_box(x,y,/^\/[\-\+]+\\$/, /^\/[\|\+]+\\$/)
148
+ end
149
+
150
+ # find alignments
151
+ @boxes.each do |b1|
152
+ @boxes.each do |b2|
153
+ if b1 != b2
154
+ if (b2.y < b1.y)
155
+ b1.aligned[:l].push(b2) if (b1.x == b2.x)
156
+ b1.aligned[:r].push(b2) if (b1.x+b1.width == b2.x+b2.width)
157
+ end
158
+ if (b2.x < b1.x)
159
+ b1.aligned[:t].push(b2) if (b1.y == b2.y)
160
+ b1.aligned[:b].push(b2) if (b1.y+b1.height == b2.y+b2.height)
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ def for_each_to_process(char)
168
+ @text.each do |x,y,e|
169
+ if e === char && @to_process.get(x,y)
170
+ yield x, y, e
171
+ end
172
+ end
173
+ end
174
+
175
+ def find_box(x,y,hmatch,vmatch)
176
+ horiz = match_horiz(x,y,hmatch)
177
+ vert = match_vert(x,y,vmatch)
178
+
179
+ return if not horiz or not vert
180
+ width, height = horiz.size, vert.size
181
+ if (width > 2) && (height > 2)
182
+ # mark the cell as processed
183
+ @to_process.set_area(x, y, horiz.size, vert.size, false)
184
+ box = Box.new(x,y,width,height)
185
+ box.content = @text.read_area(x+1,y+1,width-2,height-2)
186
+ box.content.gsub!(/\n/,' ')
187
+ # mark the area as occupied by the box
188
+ @occup.set_area(x, y, horiz.size, vert.size, box)
189
+ @boxes.push box
190
+ end
191
+ end
192
+
193
+ def match(x,y,reg,inc_x,inc_y)
194
+ s = ""
195
+ best = nil
196
+ while x<@text.width && y < @text.height
197
+ s << @text.get(x,y).chr
198
+ break if not @to_process.get(x,y)
199
+ if s =~ reg
200
+ best = s.dup
201
+ end
202
+ x += inc_x; y += inc_y
203
+ end
204
+ best
205
+ end
206
+
207
+ def match_horiz(x,y,reg)
208
+ match(x,y,reg,1,0)
209
+ end
210
+
211
+ def match_vert(x,y,reg)
212
+ match(x,y,reg,0,1)
213
+ end
214
+
215
+
216
+ end
217
+
218
+
219
+ end # moudle Diagram
@@ -0,0 +1,168 @@
1
+ class Array
2
+ def x() self[0] end
3
+ def y() self[1] end
4
+ end
5
+
6
+ module Diagrams
7
+
8
+ class Spring
9
+ attr_accessor :min,:shrink,:pref,:stretch,:max
10
+ attr_accessor :weight #not used yet
11
+ attr_accessor :imposed
12
+
13
+ def initialize(min,shrink,pref,stretch,max)
14
+ @min,@shrink,@pref,@stretch,@max =
15
+ min, shrink, pref, stretch, max
16
+ end
17
+
18
+ def Spring.series(s1,s2)
19
+ Spring.new(
20
+ s1.min+s2.min,
21
+ s1.shrink+s2.shrink,
22
+ s1.pref+s2.pref,
23
+ s1.stretch+s2.stretch,
24
+ s1.max+s2.max
25
+ )
26
+ end
27
+
28
+ def Spring.parallel(s1,s2)
29
+ pref = (s1.pref+s2.pref)*0.5
30
+ pref = [s1.min, pref].max
31
+ pref = [s1.max, pref].min
32
+ pref = [s2.min, pref].max
33
+ pref = [s2.max, pref].min
34
+
35
+ Spring.new(
36
+ [s1.min,s2.min].max,
37
+ [s1.shrink,s2.shrink].min,
38
+ pref,
39
+ [s1.stretch,s2.stretch].min,
40
+ [s1.max,s2.max].min
41
+ )
42
+ end
43
+
44
+
45
+ def inspect
46
+ if @min == @max
47
+ "Fixed(#{@min})"
48
+ else
49
+ "S[%.1f(%.1f)%.1f(%.1f)%.1f]=%.1f" %
50
+ [ @min, @shrink, @pref, @stretch, @max, @imposed || -1]
51
+ end
52
+ end
53
+ end
54
+
55
+ Reverse = {:N=>:S,:S=>:N,:W=>:E,:E=>:W}
56
+
57
+ class Sized
58
+ attr_accessor :hs, :vs # horizontal, vertical spring
59
+ attr_accessor :links #hash :N,:S,:W,:E
60
+ def initialize
61
+ @hs = Spring.new(1,0,1,0,1)
62
+ @vs = Spring.new(1,0,1,0,1)
63
+ @links = {:N=>[],:E=>[],:W=>[],:S=>[]}
64
+ end
65
+ end
66
+
67
+ class Arrow < Sized
68
+ attr_accessor :type # :S, :NW, :SE, :E
69
+ attr_accessor :cap1,:cap2 # either nil or the cap
70
+ attr_accessor :start_pos, :end_pos
71
+ attr_accessor :start_link, :end_link
72
+ attr_accessor :length
73
+ attr_accessor :object_start, :object_end
74
+
75
+
76
+ # variables for start and end
77
+ attr_accessor :v_start,:v_end
78
+
79
+ def is_vert?
80
+ start_pos.x == end_pos.x
81
+ end
82
+
83
+ end
84
+
85
+
86
+ class Box < Sized
87
+ attr_accessor :x,:y,:width,:height
88
+ attr_accessor :content
89
+
90
+ attr_accessor :aligned
91
+
92
+ # variables for top-left and bottom-right
93
+ attr_accessor :v_tl,:v_br
94
+
95
+
96
+ def initialize(x,y,width,height)
97
+ super()
98
+ @x,@y,@width,@height = x,y,width,height
99
+ @aligned = {:l=>[],:t=>[],:b=>[],:r=>[]}
100
+ end
101
+
102
+ # pos: position touching this
103
+ # from: other
104
+ def link_direction(pos, inc)
105
+ if pos.x == @x then return :W end
106
+ if pos.x == @x+@width-1 then return :E end
107
+ if pos.y == @y then return :N end
108
+ if pos.y == @y+@height-1 then return :S end
109
+ raise "Strange #{pos.inspect}: "+self.inspect
110
+ end
111
+ end
112
+
113
+ class Point < Sized
114
+ attr_accessor :pos
115
+ attr_accessor :char
116
+
117
+ attr_accessor :aligned
118
+
119
+ # variables for point position
120
+ attr_accessor :v_p
121
+
122
+ def initialize
123
+ super()
124
+ @aligned = {:l=>[],:t=>[]}
125
+ end
126
+
127
+ def link_direction(pos, inc)
128
+ if inc.x > 0 then return :W end
129
+ if inc.x < 0 then return :E end
130
+ if inc.y > 0 then return :N end
131
+ if inc.y < 0 then return :S end
132
+ raise "Strange #{inc.inspect}: "+self.inspect
133
+ end
134
+ end
135
+
136
+
137
+ class Diagram
138
+ attr_accessor :boxes, :points, :arrows
139
+
140
+ attr_accessor :text, :occup, :to_process
141
+
142
+ def initialize(s)
143
+ @text = create_grid_from_string(s)
144
+ @to_process = Grid.new(@text.width, @text.height, false)
145
+ @occup = Grid.new(@text.width, @text.height, nil)
146
+ @boxes = []
147
+ @points = []
148
+ @arrows = []
149
+ # mark cells to process
150
+ @text.each do |x,y,e|
151
+ @to_process.set(x,y,true) if e != 32
152
+ end
153
+ @width, @height = @text.width,@text.height
154
+
155
+ # p @to_process
156
+
157
+ puts @text.inspect2(@to_process)
158
+
159
+ detect_boxes
160
+ detect_points
161
+ detect_arrows
162
+
163
+ puts @text.inspect2(@to_process)
164
+ end
165
+ end
166
+
167
+
168
+ end