diff --git a/lib/maruku/attributes.rb b/lib/maruku/attributes.rb
index 07736186..98ddc992 100644
--- a/lib/maruku/attributes.rb
+++ b/lib/maruku/attributes.rb
@@ -45,8 +45,11 @@ module MaRuKu;
push [key, val]
end
def push_ref(ref_id);
+
raise "Bad :ref #{ref_id.inspect}" if not ref_id
- push [:ref, ref_id]
+ push [:ref, ref_id+""]
+
+# p "Now ", self ########################################
end
def push_class(val);
raise "Bad :id #{val.inspect}" if not val
@@ -81,6 +84,7 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
[ "a =b", :throw, "No whitespace before `=`." ],
[ "a= b", :throw, "No whitespace after `=`." ],
+ [ "a b", [[:ref, 'a'],[:ref, 'b']], "More than one ref" ],
[ "a b c", [[:ref, 'a'],[:ref, 'b'],[:ref, 'c']], "More than one ref" ],
[ "hello notfound", [[:ref, 'hello'],[:ref, 'notfound']]],
@@ -129,6 +133,7 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser
# returns nil or an AttributeList
def read_attribute_list(src, con, break_on_chars)
+
separators = break_on_chars + [?=,?\ ,?\t]
escaped = Maruku::EscapedCharInQuotes
diff --git a/lib/maruku/defaults.rb b/lib/maruku/defaults.rb
index 2d4af38e..93dff0c1 100644
--- a/lib/maruku/defaults.rb
+++ b/lib/maruku/defaults.rb
@@ -30,6 +30,12 @@ Globals = {
:code_background_color => '#fef',
:code_show_spaces => false,
:html_math_engine => 'itex2mml', #ritex, itex2mml, none
+
+ :html_png_engine => 'none',
+ :html_png_dir => 'pngs',
+ :html_png_url => 'pngs/',
+ :html_png_resolution => 200,
+
:html_use_syntax => false,
:on_error => :warning
}
diff --git a/lib/maruku/errors_management.rb b/lib/maruku/errors_management.rb
index 387acea8..9aa8d3bc 100644
--- a/lib/maruku/errors_management.rb
+++ b/lib/maruku/errors_management.rb
@@ -70,13 +70,13 @@ module Errors
def create_frame(s)
n = 75
"\n" +
- " "+"_"*n << "\n"<<
- "| Maruku tells you:\n" <<
- "+"+"-"*n +"\n"+
- add_tabs(s,1,'| ') << "\n" <<
- "+" << "-"*n << "\n" <<
- add_tabs(caller[0, 5].join("\n"),1,'!') << "\n" <<
- "\\" << "_"*n << "\n"
+ " "+"_"*n + "\n"+
+ "| Maruku tells you:\n" +
+ "+" + ("-"*n) +"\n"+
+ add_tabs(s,1,'| ') + "\n" +
+ "+" + ("-"*n) + "\n" +
+ add_tabs(caller[0, 5].join("\n"),1,'!') + "\n" +
+ "\\" + ("_"*n) + "\n"
end
def describe_error(s,src,con)
diff --git a/lib/maruku/ext/math.rb b/lib/maruku/ext/math.rb
index 55b51ceb..759deb1f 100644
--- a/lib/maruku/ext/math.rb
+++ b/lib/maruku/ext/math.rb
@@ -8,3 +8,4 @@ require 'maruku/ext/math/to_html'
require 'maruku/ext/math/mathml_engines/none'
require 'maruku/ext/math/mathml_engines/ritex'
require 'maruku/ext/math/mathml_engines/itex2mml'
+require 'maruku/ext/math/mathml_engines/blahtex'
diff --git a/lib/maruku/ext/math/mathml_engines/blahtex.rb b/lib/maruku/ext/math/mathml_engines/blahtex.rb
new file mode 100644
index 00000000..2da34cbd
--- /dev/null
+++ b/lib/maruku/ext/math/mathml_engines/blahtex.rb
@@ -0,0 +1,108 @@
+
+require 'tempfile'
+require 'fileutils'
+require 'digest/md5'
+require 'pstore'
+
+module MaRuKu; module Out; module HTML
+
+ PNG = Struct.new(:src,:depth,:height)
+
+ def convert_to_png_blahtex(kind, tex)
+ begin
+ FileUtils::mkdir_p MaRuKu::Globals[:html_png_dir]
+
+ # first, we check whether this image has already been processed
+ md5sum = Digest::MD5.hexdigest(tex+" params: ")
+ result_file = File.join(MaRuKu::Globals[:html_png_dir], md5sum+".txt")
+
+ if not File.exists?(result_file)
+ tmp_in = Tempfile.new('maruku_blahtex')
+ f = tmp_in.open
+ f.write tex
+ f.close
+
+ resolution = get_setting(:html_png_resolution)
+
+ options = "--png --use-preview-package --shell-dvipng 'dvipng -D #{resolution}' "
+ options += ("--png-directory '%s'" % MaRuKu::Globals[:html_png_dir])
+
+ cmd = "blahtex #{options} < #{tmp_in.path} > #{result_file}"
+ $stderr.puts "$ #{cmd}"
+ system cmd
+ tmp_in.delete
+
+ end
+
+ result = nil
+ f = File.open(result_file)
+ result = f.read
+ f.close
+
+
+ doc = Document.new(result, {:respect_whitespace =>:all})
+ png = doc.root.elements[1]
+ if png.name != 'png'
+ maruku_error "Blahtex error: \n#{doc}"
+ return nil
+ end
+ depth = png.elements['depth'] || (raise "No depth element in:\n #{doc}")
+ height = png.elements['height'] || (raise "No height element in:\n #{doc}")
+ md5 = png.elements['md5'] || (raise "No md5 element in:\n #{doc}")
+
+ depth = depth.text.to_f
+ height = height.text.to_f # XXX check != 0
+ md5 = md5.text
+
+ dir_url = MaRuKu::Globals[:html_png_url]
+ return PNG.new("#{dir_url}#{md5}.png", depth, height)
+
+ rescue Exception => e
+ maruku_error "Error: #{e}"
+ end
+ nil
+ end
+
+ BlahtexCache = PStore.new("blahtex_cache.pstore")
+
+ def convert_to_mathml_blahtex(kind, tex)
+ begin
+ BlahtexCache.transaction do
+ if BlahtexCache[tex].nil?
+ tmp_in = Tempfile.new('maruku_blahtex')
+ f = tmp_in.open
+ f.write tex
+ f.close
+ tmp_out = Tempfile.new('maruku_blahtex')
+
+ options = "--mathml"
+ cmd = "blahtex #{options} < #{tmp_in.path} > #{tmp_out.path}"
+ $stderr.puts "$ #{cmd}"
+ system cmd
+ tmp_in.delete
+
+ result = nil
+ File.open(tmp_out.path) do |f| result=f.read end
+ puts result
+
+ BlahtexCache[tex] = result
+ end
+
+ blahtex = BlahtexCache[tex]
+ doc = Document.new(blahtex, {:respect_whitespace =>:all})
+ mathml = doc.root.elements['mathml']
+ if not mathml
+ maruku_error "Blahtex error: \n#{doc}"
+ return nil
+ else
+ return mathml
+ end
+ end
+
+ rescue Exception => e
+ maruku_error "Error: #{e}"
+ end
+ nil
+ end
+
+end end end
diff --git a/lib/maruku/ext/math/mathml_engines/itex2mml.rb b/lib/maruku/ext/math/mathml_engines/itex2mml.rb
index 4f5be42e..164247fb 100644
--- a/lib/maruku/ext/math/mathml_engines/itex2mml.rb
+++ b/lib/maruku/ext/math/mathml_engines/itex2mml.rb
@@ -1,14 +1,16 @@
module MaRuKu; module Out; module HTML
- def convert_to_mathml_itex2mml(tex, method)
+ def convert_to_mathml_itex2mml(kind, tex)
begin
if not $itex2mml_parser
require 'itextomml'
$itex2mml_parser = Itex2MML::Parser.new
end
- mathml = $itex2mml_parser.send(method, tex)
+ itex_method = {:equation=>:block_filter,:inline=>:inline_filter}
+
+ mathml = $itex2mml_parser.send(itex_method[kind], tex)
doc = Document.new(mathml, {:respect_whitespace =>:all}).root
return doc
rescue LoadError => e
@@ -23,13 +25,5 @@ module MaRuKu; module Out; module HTML
end
nil
end
-
- def to_html_inline_math_itex2mml
- convert_to_mathml_itex2mml(self.math, :inline_filter)
- end
-
- def to_html_equation_itex2mml
- convert_to_mathml_itex2mml(self.math, :block_filter)
- end
end end end
diff --git a/lib/maruku/ext/math/mathml_engines/none.rb b/lib/maruku/ext/math/mathml_engines/none.rb
index 5fd04ec4..42f1df47 100644
--- a/lib/maruku/ext/math/mathml_engines/none.rb
+++ b/lib/maruku/ext/math/mathml_engines/none.rb
@@ -1,20 +1,20 @@
module MaRuKu; module Out; module HTML
- def to_html_inline_math_none
+ def convert_to_mathml_none(kind, tex)
# You can: either return a REXML::Element
# return Element.new 'div'
# or return an empty array on error
# return []
# or have a string parsed by REXML:
- tex = self.math
- tex.gsub!('&','&')
+ tex = tex.gsub('&','&')
mathml = "#{tex}
"
return Document.new(mathml).root
end
- def to_html_equation_none
- return to_html_inline_math_none
+ def convert_to_png_none(kind, tex)
+ return nil
end
+
end end end
diff --git a/lib/maruku/ext/math/mathml_engines/ritex.rb b/lib/maruku/ext/math/mathml_engines/ritex.rb
index fbb753b0..199eff5c 100644
--- a/lib/maruku/ext/math/mathml_engines/ritex.rb
+++ b/lib/maruku/ext/math/mathml_engines/ritex.rb
@@ -1,5 +1,6 @@
module MaRuKu; module Out; module HTML
- def convert_to_mathml_ritex(tex)
+
+ def convert_to_mathml_ritex(kind, tex)
begin
if not $ritex_parser
require 'ritex'
@@ -20,15 +21,4 @@ module MaRuKu; module Out; module HTML
nil
end
- def to_html_inline_math_ritex
- tex = self.math
- mathml = convert_to_mathml_ritex(tex)
- return mathml || []
- end
-
- def to_html_equation_ritex
- tex = self.math
- mathml = convert_to_mathml_ritex(tex)
- return mathml || []
- end
end end end
diff --git a/lib/maruku/ext/math/to_html.rb b/lib/maruku/ext/math/to_html.rb
index 5bc3fcab..105e6d7c 100644
--- a/lib/maruku/ext/math/to_html.rb
+++ b/lib/maruku/ext/math/to_html.rb
@@ -1,33 +1,37 @@
=begin maruku_doc
+Extension: math
Attribute: html_math_engine
Scope: document, element
Output: html
-Summary: Select the rendering engine for math.
+Summary: Select the rendering engine for MathML.
Default:
Select the rendering engine for math.
-If you want to use your engine `foo`, then set:
+If you want to use your custom engine `foo`, then set:
HTML math engine: foo
{:lang=markdown}
and then implement two functions:
- def to_html_inline_math_foo
- # You can: either return a REXML::Element
- # return Element.new 'div'
- # or return an empty array on error
- # return []
- # or have a string parsed by REXML:
- tex = self.math
- tex.gsub!('&','&')
- mathml = "#{tex}
"
- return Document.new(mathml).root
+ def convert_to_mathml_foo(kind, tex)
+ ...
end
+=end
- def to_html_equation_foo
+=begin maruku_doc
+Extension: math
+Attribute: html_png_engine
+Scope: document, element
+Output: html
+Summary: Select the rendering engine for math.
+Default:
+
+Same thing as `html_math_engine`, only for PNG output.
+
+ def convert_to_png_foo(kind, tex)
# same thing
...
end
@@ -37,16 +41,6 @@ and then implement two functions:
module MaRuKu; module Out; module HTML
- def to_html_inline_math
- s = get_setting(:html_math_engine)
- method = "to_html_inline_math_#{s}".to_sym
- if self.respond_to? method
- self.send method || to_html_equation_none
- else
- puts "A method called #{method} should be defined."
- return []
- end
- end
def add_class_to(el, cl)
el.attributes['class'] =
@@ -57,35 +51,112 @@ module MaRuKu; module Out; module HTML
end
end
- def to_html_equation
- s = get_setting(:html_math_engine)
- method = "to_html_equation_#{s}".to_sym
+ # Creates an xml Mathml document of self.math
+ def render_mathml(kind, tex)
+ engine = get_setting(:html_math_engine)
+ method = "convert_to_mathml_#{engine}".to_sym
if self.respond_to? method
- mathml = self.send(method) || to_html_equation_none
- div = create_html_element 'div'
- add_class_to(div, 'maruku-equation')
- if self.label # then numerate
- span = Element.new 'span'
- span.attributes['class'] = 'maruku-eq-number'
- num = self.num
- span << Text.new("(#{num})")
- div << span
- div.attributes['id'] = "eq:#{self.label}"
- end
- div << mathml
-
- source_div = Element.new 'div'
- add_class_to(source_div, 'maruku-eq-tex')
- code = to_html_equation_none
- code.attributes['style'] = 'display: none'
- source_div << code
- div << source_div
- div
+ mathml = self.send(method, kind, tex)
+ return mathml || convert_to_mathml_none(kind, tex)
else
puts "A method called #{method} should be defined."
- return []
+ return convert_to_mathml_none(kind, tex)
end
end
+
+ # Creates an xml Mathml document of self.math
+ def render_png(kind, tex)
+ engine = get_setting(:html_png_engine)
+ method = "convert_to_png_#{engine}".to_sym
+ if self.respond_to? method
+ return self.send(method, kind, tex)
+ else
+ puts "A method called #{method} should be defined."
+ return nil
+ end
+ end
+
+ def pixels_per_ex
+ if not $pixels_per_ex
+ x = render_png(:inline, "x")
+ $pixels_per_ex = x.height # + x.depth
+ end
+ $pixels_per_ex
+ end
+
+ def adjust_png(png, use_depth)
+ src = png.src
+
+ height_in_px = png.height
+ depth_in_px = png.depth
+ height_in_ex = height_in_px / pixels_per_ex
+ depth_in_ex = depth_in_px / pixels_per_ex
+ total_height_in_ex = height_in_ex + depth_in_ex
+ style = ""
+ style += "vertical-align: -#{depth_in_ex}ex;" if use_depth
+ style += "height: #{total_height_in_ex}ex;"
+ img = Element.new 'img'
+ img.attributes['src'] = src
+ img.attributes['style'] = style
+ img.attributes['alt'] = "equation"
+ img
+ end
+
+ def to_html_inline_math
+ mathml = render_mathml(:inline, self.math)
+ png = render_png(:inline, self.math)
+
+ span = create_html_element 'span'
+ add_class_to(span, 'maruku-inline')
+
+ if mathml
+ add_class_to(mathml, 'maruku-mathml')
+ span << mathml
+ end
+
+ if png
+ img = adjust_png(png, use_depth=true)
+ add_class_to(img, 'maruku-png')
+ span << img
+ end
+ span
+
+ end
+
+ def to_html_equation
+ mathml = render_mathml(:equation, self.math)
+ png = render_png(:equation, self.math)
+
+ div = create_html_element 'div'
+ add_class_to(div, 'maruku-equation')
+ if self.label # then numerate
+ span = Element.new 'span'
+ span.attributes['class'] = 'maruku-eq-number'
+ num = self.num
+ span << Text.new("(#{num})")
+ div << span
+ div.attributes['id'] = "eq:#{self.label}"
+ end
+
+ if mathml
+ add_class_to(mathml, 'maruku-mathml')
+ div << mathml
+ end
+
+ if png
+ img = adjust_png(png, use_depth=false)
+ add_class_to(img, 'maruku-png')
+ div << img
+ end
+
+ source_div = Element.new 'div'
+ add_class_to(source_div, 'maruku-eq-tex')
+ code = convert_to_mathml_none(:equation, self.math)
+ code.attributes['style'] = 'display: none'
+ source_div << code
+ div << source_div
+ div
+ end
def to_html_eqref
if eq = self.doc.eqid2eq[self.eqid]
@@ -97,7 +168,7 @@ module MaRuKu; module Out; module HTML
a
else
maruku_error "Cannot find equation #{self.eqid.inspect}"
- Text.new "(#{self.eqid})"
+ Text.new "(eq:#{self.eqid})"
end
end
diff --git a/lib/maruku/input/parse_block.rb b/lib/maruku/input/parse_block.rb
index 3c1d1288..f142a300 100644
--- a/lib/maruku/input/parse_block.rb
+++ b/lib/maruku/input/parse_block.rb
@@ -59,6 +59,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
when :ial
m = InlineAttributeList.match src.shift_line
content = m[1] || ""
+# puts "Content: #{content.inspect}"
src2 = CharSource.new(content, src)
interpret_extension(src2, output, [nil])
when :ald
@@ -468,7 +469,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser
end
id = match[1]; url = match[2]; title = match[3];
- id = id.strip.downcase
+ id = id.strip.downcase.gsub(' ','_')
hash = self.refs[id] = {:url=>url,:title=>title}
diff --git a/lib/maruku/output/to_html.rb b/lib/maruku/output/to_html.rb
index 8cf401d3..97c11fce 100644
--- a/lib/maruku/output/to_html.rb
+++ b/lib/maruku/output/to_html.rb
@@ -21,9 +21,6 @@
require 'rexml/document'
-require 'rubygems'
-require 'syntax'
-require 'syntax/convertors/html'
class String
@@ -341,6 +338,12 @@ generated file.
element =
if use_syntax && lang
begin
+ if not $syntax_loaded
+ require 'rubygems'
+ require 'syntax'
+ require 'syntax/convertors/html'
+ $syntax_loaded = true
+ end
convertor = Syntax::Convertors::HTML.for_syntax lang
# eliminate trailing newlines otherwise Syntax crashes
@@ -351,6 +354,10 @@ generated file.
pre = Document.new(html, {:respect_whitespace =>:all}).root
pre.attributes['class'] = lang
pre
+ rescue LoadError => e
+ maruku_error "Could not load package 'syntax'.\n"+
+ "Please install it, for example using 'gem install syntax'."
+ to_html_code_using_pre(source)
rescue Object => e
maruku_error"Error while using the syntax library for code:\n#{source.inspect}"+
"Lang is #{lang} object is: \n"+
@@ -422,7 +429,8 @@ generated file.
id = self.ref_id
# if empty, use text
if id.size == 0
- id = children.to_s.downcase
+ id = children.to_s.downcase.gsub(' ','_')
+
end
if ref = @doc.refs[id]
@@ -431,7 +439,8 @@ generated file.
a.attributes['href'] = url if url
a.attributes['title'] = title if title
else
- maruku_error"Could not find ref_id = #{id.inspect} for #{self.inspect}"
+ maruku_error "Could not find ref_id = #{id.inspect} for #{self.inspect}\n"+
+ "Available refs are #{@doc.refs.keys.inspect}"
tell_user "Not creating a link for ref_id = #{id.inspect}."
return wrap_as_element('span')
end
diff --git a/lib/maruku/output/to_latex.rb b/lib/maruku/output/to_latex.rb
index 0c91a176..84d24e44 100644
--- a/lib/maruku/output/to_latex.rb
+++ b/lib/maruku/output/to_latex.rb
@@ -78,8 +78,11 @@ You have to have these fonts installed -- and this can be a pain.
If `latex_cjk` is specified, this is added to the preamble:
+
+
+
while the default is to add this:
diff --git a/lib/maruku/tests/benchmark.rb b/lib/maruku/tests/benchmark.rb
index 9854e10b..21d4a935 100644
--- a/lib/maruku/tests/benchmark.rb
+++ b/lib/maruku/tests/benchmark.rb
@@ -20,7 +20,7 @@
require 'maruku'
-require 'bluecloth'
+#require 'bluecloth'
data = $stdin.read
@@ -35,7 +35,7 @@ methods =
[
[Maruku, :to_html],
- [BlueCloth, :to_html],
+# [BlueCloth, :to_html],
[Maruku, :to_latex]
]
diff --git a/lib/maruku/tests/new_parser.rb b/lib/maruku/tests/new_parser.rb
index c2229552..6374398a 100644
--- a/lib/maruku/tests/new_parser.rb
+++ b/lib/maruku/tests/new_parser.rb
@@ -20,6 +20,7 @@
require 'maruku'
+require 'maruku/ext/math'
module MaRuKu; module Tests
# 5 accented letters in italian, encoded as UTF-8
@@ -149,8 +150,10 @@ module MaRuKu; module Tests
# links of the form [text][ref]
["\\[a]", ["[a]"], 'Escaping 1'],
["\\[a\\]", ["[a]"], 'Escaping 2'],
- ["[a]", ["a"], 'Not a link'],
- ["[a][]", [ md_link(["a"],'')], 'Empty link'],
+# This is valid in the new Markdown version
+# ["[a]", ["a"], 'Not a link'],
+ ["[a]", [ md_link(["a"],'')], 'Empty link'],
+ ["[a][]", ],
["[a][]b", [ md_link(["a"],''),'b'], 'Empty link'],
["[a\\]][]", [ md_link(["a]"],'')], 'Escape inside link'],
@@ -256,11 +259,12 @@ module MaRuKu; module Tests
['[bar](/url/ "Title with "quotes" inside")',
[md_im_link(["bar"],'/url/', 'Title with "quotes" inside')],
"Link with quotes"],
-
- ['$20,000 and $30,000', ['$20,000 and $30,000'], 'Math: spaces'],
+
+# We dropped this idea
+# ['$20,000 and $30,000', ['$20,000 and $30,000'], 'Math: spaces'],
['$20,000$', [md_inline_math('20,000')]],
- ['$ 20,000$', ['$ 20,000$']],
- ['$20,000 $ $20,000$', ['$20,000 $ ', md_inline_math('20,000')]],
+# ['$ 20,000$', ['$ 20,000$']],
+# ['$20,000 $ $20,000$', ['$20,000 $ ', md_inline_math('20,000')]],
["#{Maruku8}", [Maruku8], "Reading UTF-8"],
["#{AccIta1}", [AccIta8], "Converting ISO-8859-1 to UTF-8",
{:encoding => 'iso-8859-1'}],
diff --git a/public/stylesheets/instiki.css b/public/stylesheets/instiki.css
index 2d6aedf3..f47bb065 100644
--- a/public/stylesheets/instiki.css
+++ b/public/stylesheets/instiki.css
@@ -308,7 +308,7 @@ a,li span {
color:#000;
}
-a:hover,a.nav:hover {
+a:hover,a.nav:hover, a:hover math {
background-color:#000;
color:#FFF;
}