maruku 0.4.2.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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