maruku 0.5.8 → 0.5.9
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.
- data/bin/maruku +22 -14
- data/lib/maruku/defaults.rb +2 -1
- data/lib/maruku/ext/div.rb +100 -0
- data/lib/maruku/ext/math.rb +1 -1
- data/lib/maruku/ext/math/mathml_engines/blahtex.rb +23 -25
- data/lib/maruku/input/parse_block.rb +4 -3
- data/lib/maruku/input/parse_span_better.rb +9 -4
- data/lib/maruku/input/type_detection.rb +5 -2
- data/lib/maruku/output/to_html.rb +14 -2
- data/lib/maruku/version.rb +1 -1
- data/tests/bugs/abbrev.md +1479 -0
- data/tests/bugs/html.md +29 -0
- data/tests/bugs/links.md +47 -0
- data/tests/unittest/divs/div1.md +204 -0
- data/tests/unittest/divs/div2.md +34 -0
- data/tests/unittest/divs/div3_nest.md +62 -0
- data/tests/unittest/email.md +1 -1
- data/tests/unittest/links.md +1 -1
- data/tests/unittest/pending/link.md +3 -3
- metadata +9 -2
data/bin/maruku
CHANGED
@@ -3,6 +3,11 @@
|
|
3
3
|
require 'maruku'
|
4
4
|
require 'optparse'
|
5
5
|
|
6
|
+
def cli_puts(s)
|
7
|
+
$stderr.puts(s) if MaRuKu::Globals[:verbose]
|
8
|
+
end
|
9
|
+
|
10
|
+
|
6
11
|
export = :html
|
7
12
|
break_on_error = false
|
8
13
|
using_math = false
|
@@ -26,7 +31,7 @@ opt = OptionParser.new do |opts|
|
|
26
31
|
MaRuKu::Globals[:html_math_output_png] = true
|
27
32
|
MaRuKu::Globals[:html_math_output_mathml] = false
|
28
33
|
MaRuKu::Globals[:html_png_engine] = s
|
29
|
-
|
34
|
+
cli_puts "Using png engine #{s}."
|
30
35
|
end
|
31
36
|
|
32
37
|
opts.on("-m", "--math-engine ENGINE", "Uses ENGINE to render MathML") do |s|
|
@@ -49,8 +54,7 @@ opt = OptionParser.new do |opts|
|
|
49
54
|
opts.on_tail("--inspect", "Shows the parsing result" ) do export = :inspect end
|
50
55
|
|
51
56
|
opts.on_tail("--version", "Show version") do
|
52
|
-
puts
|
53
|
-
exit
|
57
|
+
puts "Maruku #{MaRuKu::Version}"; exit
|
54
58
|
end
|
55
59
|
|
56
60
|
opts.on_tail("-h", "--help", "Show this message") do
|
@@ -68,27 +72,29 @@ rescue OptionParser::InvalidOption=>e
|
|
68
72
|
exit
|
69
73
|
end
|
70
74
|
|
75
|
+
|
71
76
|
if using_math
|
72
|
-
|
77
|
+
cli_puts "Using Math extensions."
|
73
78
|
require 'maruku/ext/math'
|
74
79
|
end
|
75
80
|
|
76
81
|
#p ARGV
|
77
82
|
#p MaRuKu::Globals
|
78
83
|
|
84
|
+
|
79
85
|
inputs =
|
80
86
|
# If we are given filenames, convert each file
|
81
87
|
if not ARGV.empty?
|
82
88
|
ARGV.map do |f|
|
83
89
|
# read file content
|
84
|
-
|
90
|
+
cli_puts "Reading from file #{f.inspect}."
|
85
91
|
[f, File.open(f,'r').read]
|
86
92
|
end
|
87
93
|
else
|
88
94
|
export = :html_frag if export == :html
|
89
95
|
export = :tex_frag if export == :tex
|
90
96
|
|
91
|
-
|
97
|
+
cli_puts "Reading from standard input."
|
92
98
|
[[nil, $stdin.read]]
|
93
99
|
end
|
94
100
|
|
@@ -100,7 +106,8 @@ inputs.each do |f, input|
|
|
100
106
|
|
101
107
|
t = Time.now
|
102
108
|
doc = Maruku.new(input, params)
|
103
|
-
|
109
|
+
|
110
|
+
cli_puts ("Parsing in %.2f seconds." % (Time.now-t))
|
104
111
|
|
105
112
|
out=""; suffix = "?"
|
106
113
|
t = Time.now
|
@@ -127,8 +134,9 @@ inputs.each do |f, input|
|
|
127
134
|
suffix='_s5slides.xhtml'
|
128
135
|
out = doc.to_s5({:content_only => false})
|
129
136
|
end
|
130
|
-
|
131
|
-
|
137
|
+
|
138
|
+
cli_puts("Rendering in %.2f seconds." % (Time.now-t))
|
139
|
+
|
132
140
|
# write to file or stdout
|
133
141
|
if f
|
134
142
|
|
@@ -141,19 +149,19 @@ inputs.each do |f, input|
|
|
141
149
|
end
|
142
150
|
|
143
151
|
if output_file == "-"
|
144
|
-
|
152
|
+
cli_puts "Writing to standard output"
|
145
153
|
$stdout.puts out
|
146
154
|
else
|
147
155
|
|
148
156
|
if not (export == :pdf)
|
149
|
-
|
157
|
+
cli_puts "Writing to #{output_file}"
|
150
158
|
File.open(output_file,'w') do |f| f.puts out end
|
151
159
|
else
|
152
|
-
|
160
|
+
cli_puts "Writing to #{job}.tex"
|
153
161
|
File.open("#{job}.tex",'w') do |f| f.puts out end
|
154
162
|
cmd = "pdflatex '#{job}.tex' -interaction=nonstopmode "+
|
155
163
|
"'-output-directory=#{dir}' "
|
156
|
-
|
164
|
+
cli_puts "maruku: executing $ #{cmd}"
|
157
165
|
# run twice for cross references
|
158
166
|
system cmd
|
159
167
|
system cmd
|
@@ -161,7 +169,7 @@ inputs.each do |f, input|
|
|
161
169
|
|
162
170
|
end
|
163
171
|
else # write to stdout
|
164
|
-
|
172
|
+
cli_puts "Writing to standard output"
|
165
173
|
$stdout.puts out
|
166
174
|
end
|
167
175
|
end
|
data/lib/maruku/defaults.rb
CHANGED
@@ -42,11 +42,12 @@ Globals = {
|
|
42
42
|
:html_png_dir => 'pngs',
|
43
43
|
:html_png_url => 'pngs/',
|
44
44
|
:html_png_resolution => 200,
|
45
|
-
|
45
|
+
|
46
46
|
:html_use_syntax => false,
|
47
47
|
|
48
48
|
:latex_use_listings => false,
|
49
49
|
:latex_cjk => false,
|
50
|
+
:latex_cache_file => "blahtex_cache.pstore", # cache file for blahtex filter
|
50
51
|
|
51
52
|
:debug_keep_ials => false,
|
52
53
|
:doc_prefix => ''
|
@@ -0,0 +1,100 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
OpenDiv = /^[ ]{0,3}\+\-\-+\s*([^\s-]*)\s*\-*\s*$/
|
4
|
+
CloseDiv = /^[ ]{0,3}\=\-\-+\s*([^\s-]*)\s*\-*\s*$/
|
5
|
+
StartPipe = /^[ ]{0,3}\|(.*)$/ # $1 is rest of line
|
6
|
+
DecorativeClosing = OpenDiv
|
7
|
+
|
8
|
+
MaRuKu::In::Markdown::register_block_extension(
|
9
|
+
:regexp => OpenDiv,
|
10
|
+
:handler => lambda { |doc, src, context|
|
11
|
+
# return false if not doc.is_math_enabled?
|
12
|
+
first = src.shift_line
|
13
|
+
first =~ OpenDiv
|
14
|
+
ial_at_beginning = $1
|
15
|
+
ial_at_end = nil
|
16
|
+
|
17
|
+
lines = []
|
18
|
+
# if second line starts with "|"
|
19
|
+
if src.cur_line =~ StartPipe
|
20
|
+
# then we read until no more "|"
|
21
|
+
while src.cur_line && (src.cur_line =~ StartPipe)
|
22
|
+
content = $1
|
23
|
+
lines.push content
|
24
|
+
src.shift_line
|
25
|
+
end
|
26
|
+
if src.cur_line =~ DecorativeClosing
|
27
|
+
ial_at_end = $1
|
28
|
+
src.shift_line
|
29
|
+
end
|
30
|
+
else
|
31
|
+
# else we read until CloseDiv
|
32
|
+
divs_open = 1
|
33
|
+
while src.cur_line && (divs_open>0)
|
34
|
+
if src.cur_line =~ CloseDiv
|
35
|
+
divs_open -= 1
|
36
|
+
if divs_open == 0
|
37
|
+
ial_at_end = $1
|
38
|
+
src.shift_line
|
39
|
+
break
|
40
|
+
else
|
41
|
+
lines.push src.shift_line
|
42
|
+
end
|
43
|
+
else
|
44
|
+
if src.cur_line =~ OpenDiv
|
45
|
+
divs_open += 1
|
46
|
+
end
|
47
|
+
lines.push src.shift_line
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if divs_open > 0
|
52
|
+
e = "At end of input, I still have #{divs_open} DIVs open."
|
53
|
+
doc.maruku_error(e, src, context)
|
54
|
+
return true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
ial_at_beginning = nil unless
|
59
|
+
(ial_at_beginning&&ial_at_beginning.size > 0)
|
60
|
+
ial_at_end = nil unless (ial_at_end && ial_at_end.size > 0)
|
61
|
+
|
62
|
+
if ial_at_beginning && ial_at_end
|
63
|
+
e = "Found two conflicting IALs: #{ial_at_beginning.inspect} and #{ial_at_end.inspect}"
|
64
|
+
doc.maruku_error(e, src, context)
|
65
|
+
end
|
66
|
+
|
67
|
+
al_string = ial_at_beginning || ial_at_end
|
68
|
+
al = nil
|
69
|
+
|
70
|
+
if al_string =~ /^\{(.*)\}$/
|
71
|
+
inside = $1
|
72
|
+
cs = MaRuKu::In::Markdown::SpanLevelParser::CharSource
|
73
|
+
al = al_string &&
|
74
|
+
doc.read_attribute_list(cs.new(inside), its_context=nil, break_on=[nil])
|
75
|
+
end
|
76
|
+
|
77
|
+
src = MaRuKu::In::Markdown::BlockLevelParser::LineSource.new(lines)
|
78
|
+
children = doc.parse_blocks(src)
|
79
|
+
|
80
|
+
context.push doc.md_div(children, al)
|
81
|
+
true
|
82
|
+
})
|
83
|
+
|
84
|
+
|
85
|
+
module MaRuKu; class MDElement
|
86
|
+
|
87
|
+
def md_div(children, a=nil)
|
88
|
+
self.md_el(:div, children, meta={}, a)
|
89
|
+
end
|
90
|
+
|
91
|
+
end end
|
92
|
+
|
93
|
+
|
94
|
+
module MaRuKu; module Out; module HTML
|
95
|
+
|
96
|
+
def to_html_div
|
97
|
+
add_ws wrap_as_element('div')
|
98
|
+
end
|
99
|
+
|
100
|
+
end end end
|
data/lib/maruku/ext/math.rb
CHANGED
@@ -15,36 +15,34 @@ module MaRuKu; module Out; module HTML
|
|
15
15
|
# first, we check whether this image has already been processed
|
16
16
|
md5sum = Digest::MD5.hexdigest(tex+" params: ")
|
17
17
|
result_file = File.join(MaRuKu::Globals[:html_png_dir], md5sum+".txt")
|
18
|
-
|
18
|
+
|
19
19
|
if not File.exists?(result_file)
|
20
20
|
tmp_in = Tempfile.new('maruku_blahtex')
|
21
|
-
|
21
|
+
f = tmp_in.open
|
22
22
|
f.write tex
|
23
23
|
f.close
|
24
|
-
|
24
|
+
|
25
25
|
resolution = get_setting(:html_png_resolution)
|
26
|
-
|
27
|
-
options = "--png --use-preview-package --shell-dvipng 'dvipng -D #{resolution}' "
|
26
|
+
|
27
|
+
options = "--png --use-preview-package --shell-dvipng '/usr/bin/dvipng -D #{resolution}' "
|
28
|
+
options += ("--temp-directory '%s' " % MaRuKu::Globals[:html_png_dir])
|
28
29
|
options += ("--png-directory '%s'" % MaRuKu::Globals[:html_png_dir])
|
29
|
-
|
30
|
+
|
30
31
|
cmd = "blahtex #{options} < #{tmp_in.path} > #{result_file}"
|
31
|
-
|
32
|
-
|
32
|
+
#$stderr.puts "$ #{cmd}"
|
33
|
+
system cmd
|
33
34
|
tmp_in.delete
|
34
|
-
|
35
35
|
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
result = File.read(result_file)
|
38
|
+
if result.nil? || result.empty?
|
39
|
+
raise "Blahtex error: empty output"
|
40
|
+
end
|
41
|
+
|
43
42
|
doc = Document.new(result, {:respect_whitespace =>:all})
|
44
43
|
png = doc.root.elements[1]
|
45
44
|
if png.name != 'png'
|
46
|
-
|
47
|
-
return nil
|
45
|
+
raise "Blahtex error: \n#{doc}"
|
48
46
|
end
|
49
47
|
depth = png.elements['depth'] || (raise "No depth element in:\n #{doc}")
|
50
48
|
height = png.elements['height'] || (raise "No height element in:\n #{doc}")
|
@@ -56,19 +54,19 @@ module MaRuKu; module Out; module HTML
|
|
56
54
|
|
57
55
|
dir_url = MaRuKu::Globals[:html_png_url]
|
58
56
|
return PNG.new("#{dir_url}#{md5}.png", depth, height)
|
59
|
-
|
60
57
|
rescue Exception => e
|
61
58
|
maruku_error "Error: #{e}"
|
62
59
|
end
|
63
60
|
nil
|
64
61
|
end
|
65
62
|
|
66
|
-
|
67
|
-
|
63
|
+
|
68
64
|
def convert_to_mathml_blahtex(kind, tex)
|
65
|
+
@@BlahtexCache = PStore.new(MaRuKu::Globals[:latex_cache_file])
|
66
|
+
|
69
67
|
begin
|
70
|
-
BlahtexCache.transaction do
|
71
|
-
if BlahtexCache[tex].nil?
|
68
|
+
@@BlahtexCache.transaction do
|
69
|
+
if @@BlahtexCache[tex].nil?
|
72
70
|
tmp_in = Tempfile.new('maruku_blahtex')
|
73
71
|
f = tmp_in.open
|
74
72
|
f.write tex
|
@@ -77,7 +75,7 @@ module MaRuKu; module Out; module HTML
|
|
77
75
|
|
78
76
|
options = "--mathml"
|
79
77
|
cmd = "blahtex #{options} < #{tmp_in.path} > #{tmp_out.path}"
|
80
|
-
|
78
|
+
#$stderr.puts "$ #{cmd}"
|
81
79
|
system cmd
|
82
80
|
tmp_in.delete
|
83
81
|
|
@@ -85,10 +83,10 @@ module MaRuKu; module Out; module HTML
|
|
85
83
|
File.open(tmp_out.path) do |f| result=f.read end
|
86
84
|
puts result
|
87
85
|
|
88
|
-
|
86
|
+
@@BlahtexCache[tex] = result
|
89
87
|
end
|
90
88
|
|
91
|
-
blahtex = BlahtexCache[tex]
|
89
|
+
blahtex = @@BlahtexCache[tex]
|
92
90
|
doc = Document.new(blahtex, {:respect_whitespace =>:all})
|
93
91
|
mathml = doc.root.elements['mathml']
|
94
92
|
if not mathml
|
@@ -337,7 +337,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|
337
337
|
|
338
338
|
# puts "id =_#{id}_; text=_#{text}_ indent=#{indentation}"
|
339
339
|
|
340
|
-
break_list = [:footnote_text]
|
340
|
+
break_list = [:footnote_text, :ref_definition, :definition, :abbreviation]
|
341
341
|
item_type = :footnote_text
|
342
342
|
lines, want_my_paragraph =
|
343
343
|
read_indented_content(src,indentation, break_list, item_type)
|
@@ -471,9 +471,10 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
|
|
471
471
|
def read_ref_definition(src, out)
|
472
472
|
line = src.shift_line
|
473
473
|
|
474
|
+
|
474
475
|
# if link is incomplete, shift next line
|
475
|
-
if src.cur_line && (src.cur_line.md_type
|
476
|
-
([1,2,3].include? number_of_leading_spaces(src.cur_line) )
|
476
|
+
if src.cur_line && !([:footnote_text, :ref_definition, :definition, :abbreviation].include? src.cur_line.md_type) &&
|
477
|
+
([1,2,3].include? number_of_leading_spaces(src.cur_line) )
|
477
478
|
line += " "+ src.shift_line
|
478
479
|
end
|
479
480
|
|
@@ -647,14 +647,19 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
|
|
647
647
|
con.push_element md_im_image(alt_text, url, title)
|
648
648
|
when ?[ # link ref
|
649
649
|
ref_id = read_ref_id(src,con)
|
650
|
+
if not ref_id # TODO: check around
|
651
|
+
error('Reference not closed.', src, con)
|
652
|
+
ref_id = ""
|
653
|
+
end
|
650
654
|
if ref_id.size == 0
|
651
|
-
ref_id = alt_text.to_s
|
652
|
-
else
|
653
|
-
ref_id = ref_id.downcase
|
655
|
+
ref_id = alt_text.to_s
|
654
656
|
end
|
657
|
+
|
658
|
+
ref_id = sanitize_ref_id(ref_id)
|
659
|
+
|
655
660
|
con.push_element md_image(alt_text, ref_id)
|
656
661
|
else # no stuff
|
657
|
-
ref_id = alt_text.to_s
|
662
|
+
ref_id = sanitize_ref_id(alt_text.to_s)
|
658
663
|
con.push_element md_image(alt_text, ref_id)
|
659
664
|
end
|
660
665
|
end # read link
|
@@ -94,6 +94,7 @@ module MaRuKu; module Strings
|
|
94
94
|
# *[HTML]: Hyper Text Markup Language
|
95
95
|
Abbreviation = %r{
|
96
96
|
^ # begin of line
|
97
|
+
[ ]{0,3} # up to 3 spaces
|
97
98
|
\* # one asterisk
|
98
99
|
\[ # opening bracket
|
99
100
|
([^\]]+) # any non-closing bracket: id = $1
|
@@ -106,7 +107,9 @@ module MaRuKu; module Strings
|
|
106
107
|
}x
|
107
108
|
|
108
109
|
FootnoteText = %r{
|
109
|
-
|
110
|
+
^ # begin of line
|
111
|
+
[ ]{0,3} # up to 3 spaces
|
112
|
+
\[(\^.+)\]: # id = $1 (including '^')
|
110
113
|
\s*(\S.*)?$ # text = $2 (not obb.)
|
111
114
|
}x
|
112
115
|
|
@@ -115,7 +118,7 @@ module MaRuKu; module Strings
|
|
115
118
|
LinkRegex = %r{
|
116
119
|
^[ ]{0,3}\[([^\[\]]+)\]: # id = $1
|
117
120
|
[ ]*
|
118
|
-
<?(
|
121
|
+
<?([^>\s]+)>? # url = $2
|
119
122
|
[ ]*
|
120
123
|
(?:# Titles are delimited by "quotes" or (parens).
|
121
124
|
["(']
|
@@ -312,7 +312,8 @@ Example:
|
|
312
312
|
li.insert_after(li.children.last, a)
|
313
313
|
ol << li
|
314
314
|
else
|
315
|
-
maruku_error"Could not find footnote '#{fid}'"
|
315
|
+
maruku_error "Could not find footnote id '#{fid}' among ["+
|
316
|
+
self.footnotes.keys.map{|s|"'"+s+"'"}.join(', ')+"]."
|
316
317
|
end
|
317
318
|
end
|
318
319
|
div << ol
|
@@ -827,10 +828,21 @@ If true, raw HTML is discarded from the output.
|
|
827
828
|
# save the order of used footnotes
|
828
829
|
order = @doc.footnotes_order
|
829
830
|
|
831
|
+
if order.include? id
|
832
|
+
# footnote has already been used
|
833
|
+
return []
|
834
|
+
end
|
835
|
+
|
836
|
+
if not @doc.footnotes[id]
|
837
|
+
return []
|
838
|
+
end
|
839
|
+
|
830
840
|
# take next number
|
831
841
|
order << id
|
832
|
-
num = order.size;
|
833
842
|
|
843
|
+
#num = order.size;
|
844
|
+
num = order.index(id) + 1
|
845
|
+
|
834
846
|
sup = Element.new 'sup'
|
835
847
|
sup.attributes['id'] = "#{get_setting(:doc_prefix)}fnref:#{num}"
|
836
848
|
a = Element.new 'a'
|