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.
- data/bin/maruku +66 -20
- data/bin/marutest +12 -2
- data/docs/changelog.html +188 -23
- data/docs/changelog.md +128 -5
- data/docs/entity_test.html +245 -240
- data/docs/entity_test.md +2 -0
- data/docs/exd.html +181 -23
- data/docs/index.html +130 -349
- data/docs/markdown_syntax.html +55 -51
- data/docs/maruku.html +130 -349
- data/docs/maruku.md +154 -339
- data/docs/math.md +143 -0
- data/docs/proposal.html +16 -12
- data/lib/maruku.rb +6 -3
- data/lib/maruku/attributes.rb +7 -2
- data/lib/maruku/defaults.rb +27 -27
- data/lib/maruku/errors_management.rb +10 -9
- data/lib/maruku/ext/diagrams/diagrams.rb +8 -0
- data/lib/maruku/ext/diagrams/grid.rb +78 -0
- data/lib/maruku/ext/diagrams/inspect.rb +11 -0
- data/lib/maruku/ext/diagrams/layout.rb +105 -0
- data/lib/maruku/ext/diagrams/parser.rb +219 -0
- data/lib/maruku/ext/diagrams/structures.rb +168 -0
- data/lib/maruku/ext/diagrams/to_html.rb +37 -0
- data/lib/maruku/ext/diagrams/to_latex.rb +308 -0
- data/lib/maruku/ext/diagrams/unittest.rb +123 -0
- data/lib/maruku/ext/math.rb +11 -0
- data/lib/maruku/ext/math/elements.rb +26 -0
- data/lib/maruku/ext/math/mathml_engines/blahtex.rb +108 -0
- data/lib/maruku/ext/math/mathml_engines/itex2mml.rb +29 -0
- data/lib/maruku/ext/math/mathml_engines/none.rb +20 -0
- data/lib/maruku/ext/math/mathml_engines/ritex.rb +24 -0
- data/lib/maruku/ext/math/parsing.rb +82 -0
- data/lib/maruku/ext/math/to_html.rb +178 -0
- data/lib/maruku/ext/math/to_latex.rb +21 -0
- data/lib/maruku/helpers.rb +11 -0
- data/lib/maruku/input/charsource.rb +1 -1
- data/lib/maruku/input/extensions.rb +68 -0
- data/lib/maruku/input/html_helper.rb +91 -60
- data/lib/maruku/input/parse_block.rb +10 -9
- data/lib/maruku/input/parse_doc.rb +21 -13
- data/lib/maruku/input/parse_span_better.rb +19 -8
- data/lib/maruku/input/type_detection.rb +5 -3
- data/lib/maruku/output/to_html.rb +236 -67
- data/lib/maruku/output/to_latex.rb +69 -26
- data/lib/maruku/output/to_latex_entities.rb +14 -2
- data/lib/maruku/output/to_s.rb +8 -0
- data/lib/maruku/structures.rb +1 -1
- data/lib/maruku/tests/benchmark.rb +2 -2
- data/lib/maruku/tests/new_parser.rb +13 -5
- data/lib/maruku/version.rb +1 -1
- data/lib/sort_prof.rb +22 -0
- data/tests/diagrams/diagrams.md +54 -0
- data/tests/math/syntax.md +46 -0
- data/tests/math_usage/document.md +13 -0
- data/tests/unittest/attributes/attributes.md +50 -6
- data/tests/unittest/easy.md +1 -1
- data/tests/unittest/email.md +3 -3
- data/tests/unittest/entities.md +12 -7
- data/tests/unittest/escaping.md +4 -4
- data/tests/unittest/extra_table1.md +3 -1
- data/tests/unittest/footnotes.md +5 -5
- data/tests/unittest/headers.md +3 -3
- data/tests/unittest/images.md +7 -7
- data/tests/unittest/inline_html.md +51 -5
- data/tests/unittest/links.md +7 -7
- data/tests/unittest/list2.md +1 -1
- data/tests/unittest/lists.md +1 -1
- data/tests/unittest/lists_after_paragraph.md +1 -1
- data/tests/unittest/lists_ol.md +1 -1
- data/tests/unittest/math/equations.md +82 -0
- data/tests/unittest/math/inline.md +80 -0
- data/tests/unittest/math/table.md +51 -0
- data/tests/unittest/math/table2.md +67 -0
- data/tests/unittest/misc_sw.md +24 -24
- data/tests/unittest/notyet/ticks.md +1 -1
- data/tests/unittest/references/long_example.md +2 -2
- data/tests/unittest/smartypants.md +4 -4
- data/tests/unittest/xml.md +68 -0
- data/tests/unittest/xml2.md +36 -0
- data/tests/unittest/xml3.md +52 -0
- data/tests/unittest/xml_instruction.md +5 -5
- metadata +33 -4
- data/docs/a.html +0 -6
- 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
|
data/lib/maruku/helpers.rb
CHANGED
@@ -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
|
|
@@ -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
|
-
|
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
|
-
|
53
|
-
|
54
|
-
@
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
201
|
-
|
202
|
-
s
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
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
|
-
|
210
|
-
|
211
|
-
|
217
|
+
}
|
218
|
+
|
212
219
|
end
|
220
|
+
|
213
221
|
end
|
214
222
|
end
|
215
223
|
end
|