kramdown 0.12.0 → 0.13.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of kramdown might be problematic. Click here for more details.
- data/CONTRIBUTERS +2 -1
- data/ChangeLog +278 -0
- data/README +3 -0
- data/Rakefile +24 -0
- data/VERSION +1 -1
- data/benchmark/benchmark.sh +11 -2
- data/doc/documentation.page +2 -3
- data/doc/index.page +4 -4
- data/doc/installation.page +10 -11
- data/doc/syntax.page +17 -7
- data/doc/tests.page +1 -1
- data/lib/kramdown/converter/base.rb +9 -6
- data/lib/kramdown/converter/html.rb +2 -2
- data/lib/kramdown/converter/latex.rb +46 -26
- data/lib/kramdown/options.rb +42 -20
- data/lib/kramdown/parser/html.rb +50 -11
- data/lib/kramdown/parser/kramdown.rb +4 -4
- data/lib/kramdown/parser/kramdown/html_entity.rb +7 -2
- data/lib/kramdown/parser/kramdown/link.rb +9 -7
- data/lib/kramdown/parser/kramdown/list.rb +5 -4
- data/lib/kramdown/parser/kramdown/table.rb +24 -19
- data/lib/kramdown/utils/entities.rb +4 -0
- data/lib/kramdown/version.rb +1 -1
- data/man/man1/kramdown.1 +15 -14
- data/test/testcases/block/08_list/item_ial.html +3 -0
- data/test/testcases/block/08_list/item_ial.text +3 -0
- data/test/testcases/block/09_html/html_to_native/emphasis.html +2 -0
- data/test/testcases/block/09_html/html_to_native/emphasis.text +3 -0
- data/test/testcases/block/09_html/parse_as_raw.html +2 -0
- data/test/testcases/block/09_html/parse_as_raw.text +2 -0
- data/test/testcases/block/14_table/simple.html +19 -0
- data/test/testcases/block/14_table/simple.html.19 +19 -0
- data/test/testcases/block/14_table/simple.text +5 -0
- data/test/testcases/span/01_link/reference.html +3 -2
- data/test/testcases/span/01_link/reference.html.19 +3 -2
- data/test/testcases/span/01_link/reference.text +4 -1
- data/test/testcases/span/05_html/normal.html +2 -0
- data/test/testcases/span/05_html/normal.text +2 -0
- data/test/testcases/span/text_substitutions/entities.html +2 -0
- data/test/testcases/span/text_substitutions/entities.text +2 -0
- metadata +4 -4
data/doc/syntax.page
CHANGED
@@ -688,12 +688,12 @@ There are four different line types that can be used in a table:
|
|
688
688
|
|
689
689
|
A table row is any line that contains at least one pipe character and is not identified as any
|
690
690
|
other type of table line! The table row is divided into individual table cells by pipe characters.
|
691
|
-
An optional trailing pipe character is ignored.
|
691
|
+
An optional trailing pipe character is ignored. Note that literal pipe characters need to be
|
692
|
+
escaped *except* if they occur in code spans or HTML `<code>` elements!
|
692
693
|
|
693
694
|
Header rows, footer rows and normal rows are all done using these table rows. Table cells can only
|
694
695
|
contain a single line of text, no multi-line text is supported. The text of a table cell is parsed
|
695
|
-
as span-level elements.
|
696
|
-
in code spans!
|
696
|
+
as span-level elements.
|
697
697
|
|
698
698
|
Here are some example table rows:
|
699
699
|
|
@@ -1108,10 +1108,10 @@ Notes:
|
|
1108
1108
|
|
1109
1109
|
To create a reference style link, you need to surround the link text with square brackets (as with
|
1110
1110
|
inline links), followed by optional spaces/tabs/line breaks and then optionally followed with
|
1111
|
-
another set of square brackets with the link identifier in them. A link identifier may
|
1112
|
-
|
1113
|
-
|
1114
|
-
example:
|
1111
|
+
another set of square brackets with the link identifier in them. A link identifier may not contain a
|
1112
|
+
closing bracket and, when specified in a link definition, newline characters; it is also not case
|
1113
|
+
sensitive, line breaks and tabs are converted to spaces and multiple spaces are compressed into one.
|
1114
|
+
For example:
|
1115
1115
|
|
1116
1116
|
This is a [reference style link][linkid] to a page. And [this]
|
1117
1117
|
[linkid] is also a link. As is [this][] and [THIS].
|
@@ -1144,6 +1144,16 @@ The link definition has the following structure:
|
|
1144
1144
|
> allowed for consistency with the inline title.
|
1145
1145
|
{: .markdown-difference}
|
1146
1146
|
|
1147
|
+
If you have some text that looks like a link definition but should really be a link and some text,
|
1148
|
+
you can escape the colon after the link identifier:
|
1149
|
+
|
1150
|
+
The next paragraph contains a link and some text.
|
1151
|
+
|
1152
|
+
[Room 100]\: There you should find everything you need!
|
1153
|
+
|
1154
|
+
[Room 100]: link_to_room_100.html
|
1155
|
+
|
1156
|
+
|
1147
1157
|
### Images
|
1148
1158
|
|
1149
1159
|
Images can be specified via a syntax that is similar to the one used by links. The difference is
|
data/doc/tests.page
CHANGED
@@ -45,7 +45,7 @@ different Ruby interpreters:
|
|
45
45
|
![ruby 1.8.6p399]({relocatable: img/graph-ruby-1.8.6-399.png})
|
46
46
|
![ruby 1.8.7p249]({relocatable: img/graph-ruby-1.8.7-249.png})
|
47
47
|
![ruby 1.8.7p302]({relocatable: img/graph-ruby-1.8.7-302.png})
|
48
|
-
![ruby 1.9.
|
48
|
+
![ruby 1.9.2p136]({relocatable: img/graph-ruby-1.9.2p136-136.png})
|
49
49
|
![jruby 1.5.3]({relocatable: img/graph-jruby-1.5.3-249.png})
|
50
50
|
|
51
51
|
[Markdown Test Suite]: http://daringfireball.net/projects/downloads/MarkdownTest_1.0.zip
|
@@ -132,12 +132,7 @@ module Kramdown
|
|
132
132
|
# Return +true+ if the header element +el+ should be used for the table of contents (as
|
133
133
|
# specified by the +toc_levels+ option).
|
134
134
|
def in_toc?(el)
|
135
|
-
|
136
|
-
warn('Option toc_depth is deprecated, use the new option toc_levels instead')
|
137
|
-
@options[:toc_depth] == 0 || el.options[:level] <= @options[:toc_depth]
|
138
|
-
else
|
139
|
-
@options[:toc_levels].include?(el.options[:level])
|
140
|
-
end
|
135
|
+
@options[:toc_levels].include?(el.options[:level])
|
141
136
|
end
|
142
137
|
|
143
138
|
# Generate an unique alpha-numeric ID from the the string +str+ for use as a header ID.
|
@@ -159,6 +154,14 @@ module Kramdown
|
|
159
154
|
@options[:auto_id_prefix] + gen_id
|
160
155
|
end
|
161
156
|
|
157
|
+
SMART_QUOTE_INDICES = {:lsquo => 0, :rsquo => 1, :ldquo => 2, :rdquo => 3} # :nodoc:
|
158
|
+
|
159
|
+
# Return the entity that represents the given smart_quote element.
|
160
|
+
def smart_quote_entity(el)
|
161
|
+
res = @options[:smart_quotes][SMART_QUOTE_INDICES[el.value]]
|
162
|
+
::Kramdown::Utils::Entities.entity(res)
|
163
|
+
end
|
164
|
+
|
162
165
|
end
|
163
166
|
|
164
167
|
end
|
@@ -178,7 +178,7 @@ module Kramdown
|
|
178
178
|
end
|
179
179
|
|
180
180
|
# A list of all HTML tags that need to have a body (even if the body is empty).
|
181
|
-
HTML_TAGS_WITH_BODY=['div', 'script', 'iframe', 'textarea'] # :nodoc:
|
181
|
+
HTML_TAGS_WITH_BODY=['div', 'script', 'iframe', 'textarea', 'a'] # :nodoc:
|
182
182
|
|
183
183
|
def convert_html_element(el, indent)
|
184
184
|
res = inner(el, indent)
|
@@ -311,7 +311,7 @@ module Kramdown
|
|
311
311
|
end
|
312
312
|
|
313
313
|
def convert_smart_quote(el, indent)
|
314
|
-
entity_to_str(
|
314
|
+
entity_to_str(smart_quote_entity(el))
|
315
315
|
end
|
316
316
|
|
317
317
|
def convert_math(el, indent)
|
@@ -84,7 +84,7 @@ module Kramdown
|
|
84
84
|
if el.children.size == 1 && el.children.first.type == :img && !(img = convert_img(el.children.first, opts)).empty?
|
85
85
|
convert_standalone_image(el, opts, img)
|
86
86
|
else
|
87
|
-
"#{inner(el, opts)}\n\n"
|
87
|
+
"#{latex_link_target(el)}#{inner(el, opts)}\n\n"
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
@@ -92,20 +92,23 @@ module Kramdown
|
|
92
92
|
# <tt>:img</tt> element.
|
93
93
|
def convert_standalone_image(el, opts, img)
|
94
94
|
attrs = attribute_list(el)
|
95
|
-
"\\begin{figure}#{attrs}\n\\begin{center}\n#{img}\n\\end{center}\n\\caption{#{escape(el.children.first.attr['alt'])}}\n\\end{figure}#{attrs}\n"
|
95
|
+
"\\begin{figure}#{attrs}\n\\begin{center}\n#{img}\n\\end{center}\n\\caption{#{escape(el.children.first.attr['alt'])}}\n#{latex_link_target(el, true)}\n\\end{figure}#{attrs}\n"
|
96
96
|
end
|
97
97
|
|
98
98
|
def convert_codeblock(el, opts)
|
99
99
|
show_whitespace = el.attr['class'].to_s =~ /\bshow-whitespaces\b/
|
100
100
|
lang = el.attr['lang']
|
101
101
|
if show_whitespace || lang
|
102
|
-
|
103
|
-
|
104
|
-
|
102
|
+
options = []
|
103
|
+
options << "showspaces=%s,showtabs=%s" % (show_whitespace ? ['true', 'true'] : ['false', 'false'])
|
104
|
+
options << "language=#{lang}" if lang
|
105
|
+
options << "basicstyle=\\ttfamily\\footnotesize,columns=fixed,frame=tlbr"
|
106
|
+
id = el.attr['id']
|
107
|
+
options << "label=#{id}" if id
|
105
108
|
attrs = attribute_list(el)
|
106
|
-
|
109
|
+
"#{latex_link_target(el)}\\begin{lstlisting}[#{options.join(',')}]\n#{el.value}\n\\end{lstlisting}#{attrs}\n"
|
107
110
|
else
|
108
|
-
"\\begin{verbatim}#{el.value}\\end{verbatim}\n"
|
111
|
+
"#{latex_link_target(el)}\\begin{verbatim}#{el.value}\\end{verbatim}\n"
|
109
112
|
end
|
110
113
|
end
|
111
114
|
|
@@ -117,7 +120,7 @@ module Kramdown
|
|
117
120
|
type = @options[:latex_headers][el.options[:level] - 1]
|
118
121
|
if ((id = el.attr['id']) ||
|
119
122
|
(@options[:auto_ids] && (id = generate_id(el.options[:raw_text])))) && in_toc?(el)
|
120
|
-
"
|
123
|
+
"\\#{type}{#{inner(el, opts)}}\\hypertarget{#{id}}{}\\label{#{id}}\n\n"
|
121
124
|
else
|
122
125
|
"\\#{type}*{#{inner(el, opts)}}\n\n"
|
123
126
|
end
|
@@ -125,7 +128,7 @@ module Kramdown
|
|
125
128
|
|
126
129
|
def convert_hr(el, opts)
|
127
130
|
attrs = attribute_list(el)
|
128
|
-
"\\begin{center}#{attrs}\n\\rule{3in}{0.4pt}\n\\end{center}#{attrs}\n"
|
131
|
+
"#{latex_link_target(el)}\\begin{center}#{attrs}\n\\rule{3in}{0.4pt}\n\\end{center}#{attrs}\n"
|
129
132
|
end
|
130
133
|
|
131
134
|
def convert_ul(el, opts)
|
@@ -143,7 +146,7 @@ module Kramdown
|
|
143
146
|
end
|
144
147
|
|
145
148
|
def convert_li(el, opts)
|
146
|
-
"\\item #{inner(el, opts).sub(/\n+\Z/, '')}\n"
|
149
|
+
"\\item #{latex_link_target(el, true)}#{inner(el, opts).sub(/\n+\Z/, '')}\n"
|
147
150
|
end
|
148
151
|
|
149
152
|
def convert_dt(el, opts)
|
@@ -151,7 +154,7 @@ module Kramdown
|
|
151
154
|
end
|
152
155
|
|
153
156
|
def convert_dd(el, opts)
|
154
|
-
"#{inner(el, opts)}\n\n"
|
157
|
+
"#{latex_link_target(el)}#{inner(el, opts)}\n\n"
|
155
158
|
end
|
156
159
|
|
157
160
|
def convert_html_element(el, opts)
|
@@ -179,7 +182,7 @@ module Kramdown
|
|
179
182
|
def convert_table(el, opts)
|
180
183
|
align = el.options[:alignment].map {|a| TABLE_ALIGNMENT_CHAR[a]}.join('|')
|
181
184
|
attrs = attribute_list(el)
|
182
|
-
"\\begin{tabular}{|#{align}|}#{attrs}\n\\hline\n#{inner(el, opts)}\\hline\n\\end{tabular}#{attrs}\n\n"
|
185
|
+
"#{latex_link_target(el)}\\begin{tabular}{|#{align}|}#{attrs}\n\\hline\n#{inner(el, opts)}\\hline\n\\end{tabular}#{attrs}\n\n"
|
183
186
|
end
|
184
187
|
|
185
188
|
def convert_thead(el, opts)
|
@@ -227,7 +230,7 @@ module Kramdown
|
|
227
230
|
''
|
228
231
|
elsif !el.options.attr['src'].empty?
|
229
232
|
@data[:packages] << 'graphicx'
|
230
|
-
"\\includegraphics{#{el.attr['src']}}"
|
233
|
+
"#{latex_link_target(el)}\\includegraphics{#{el.attr['src']}}"
|
231
234
|
else
|
232
235
|
warning("Cannot include image with empty path")
|
233
236
|
''
|
@@ -235,7 +238,7 @@ module Kramdown
|
|
235
238
|
end
|
236
239
|
|
237
240
|
def convert_codespan(el, opts)
|
238
|
-
"{\\tt #{escape(el.value)}}"
|
241
|
+
"{\\tt #{latex_link_target(el)}#{escape(el.value)}}"
|
239
242
|
end
|
240
243
|
|
241
244
|
def convert_footnote(el, opts)
|
@@ -252,11 +255,11 @@ module Kramdown
|
|
252
255
|
end
|
253
256
|
|
254
257
|
def convert_em(el, opts)
|
255
|
-
"\\emph{#{inner(el, opts)}}"
|
258
|
+
"\\emph{#{latex_link_target(el)}#{inner(el, opts)}}"
|
256
259
|
end
|
257
260
|
|
258
261
|
def convert_strong(el, opts)
|
259
|
-
"\\textbf{#{inner(el, opts)}}"
|
262
|
+
"\\textbf{#{latex_link_target(el)}#{inner(el, opts)}}"
|
260
263
|
end
|
261
264
|
|
262
265
|
# Inspired by Maruku: entity conversion table based on the one from htmltolatex
|
@@ -387,8 +390,8 @@ module Kramdown
|
|
387
390
|
34 => ['"'],
|
388
391
|
39 => ['\''],
|
389
392
|
169 => ['\copyright'],
|
390
|
-
60 => ['\textless
|
391
|
-
62 => ['\textgreater
|
393
|
+
60 => ['\textless'],
|
394
|
+
62 => ['\textgreater'],
|
392
395
|
338 => ['\OE'],
|
393
396
|
339 => ['\oe'],
|
394
397
|
352 => ['\v{S}'],
|
@@ -503,20 +506,27 @@ module Kramdown
|
|
503
506
|
253 => ['\\\'y'],
|
504
507
|
254 => ['\thorn', 'wasysym'],
|
505
508
|
255 => ['\"y'],
|
509
|
+
8201 => ['\thinspace'],
|
510
|
+
8194 => ['\hskip .5em\relax'],
|
511
|
+
8195 => ['\quad'],
|
506
512
|
} # :nodoc:
|
507
|
-
ENTITY_CONV_TABLE.each {|k,v| ENTITY_CONV_TABLE[k]
|
513
|
+
ENTITY_CONV_TABLE.each {|k,v| ENTITY_CONV_TABLE[k][0].insert(-1, '{}')}
|
508
514
|
|
509
|
-
def
|
510
|
-
text, package = ENTITY_CONV_TABLE[
|
515
|
+
def entity_to_latex(entity)
|
516
|
+
text, package = ENTITY_CONV_TABLE[entity.code_point]
|
511
517
|
if text
|
512
518
|
@data[:packages] << package if package
|
513
519
|
text
|
514
520
|
else
|
515
|
-
warning("Couldn't find entity in substitution table!")
|
521
|
+
warning("Couldn't find entity with code #{entity.code_point} in substitution table!")
|
516
522
|
''
|
517
523
|
end
|
518
524
|
end
|
519
525
|
|
526
|
+
def convert_entity(el, opts)
|
527
|
+
entity_to_latex(el.value)
|
528
|
+
end
|
529
|
+
|
520
530
|
TYPOGRAPHIC_SYMS = {
|
521
531
|
:mdash => '---', :ndash => '--', :hellip => '\ldots{}',
|
522
532
|
:laquo_space => '\guillemotleft{}~', :raquo_space => '~\guillemotright{}',
|
@@ -526,10 +536,9 @@ module Kramdown
|
|
526
536
|
TYPOGRAPHIC_SYMS[el.value]
|
527
537
|
end
|
528
538
|
|
529
|
-
SMART_QUOTE_SYMS = {:lsquo => '`', :rsquo => '\'', :ldquo => '``', :rdquo => '\'\''} # :nodoc:
|
530
539
|
def convert_smart_quote(el, opts)
|
531
|
-
res =
|
532
|
-
res << "{}" if (nel = opts[:parent].children[opts[:index]+1]) && nel.type == :smart_quote
|
540
|
+
res = entity_to_latex(smart_quote_entity(el)).chomp('{}')
|
541
|
+
res << "{}" if ((nel = opts[:parent].children[opts[:index]+1]) && nel.type == :smart_quote) || res =~ /\w$/
|
533
542
|
res
|
534
543
|
end
|
535
544
|
|
@@ -556,7 +565,18 @@ module Kramdown
|
|
556
565
|
# environments.
|
557
566
|
def latex_environment(type, el, text)
|
558
567
|
attrs = attribute_list(el)
|
559
|
-
"\\begin{#{type}}#{attrs}\n#{text.rstrip}\n\\end{#{type}}#{attrs}\n"
|
568
|
+
"\\begin{#{type}}#{latex_link_target(el)}#{attrs}\n#{text.rstrip}\n\\end{#{type}}#{attrs}\n"
|
569
|
+
end
|
570
|
+
|
571
|
+
# Return a string containing a valid <tt>\hypertarget</tt> command if the element has an ID
|
572
|
+
# defined, or +nil+ otherwise. If the parameter +add_label+ is +true+, a <tt>\label</tt>
|
573
|
+
# command will also be used additionally to the <tt>\hypertarget</tt> command.
|
574
|
+
def latex_link_target(el, add_label = false)
|
575
|
+
if (id = el.attr['id'])
|
576
|
+
"\\hypertarget{#{id}}{}" << (add_label ? "\\label{#{id}}" : '')
|
577
|
+
else
|
578
|
+
nil
|
579
|
+
end
|
560
580
|
end
|
561
581
|
|
562
582
|
# Return a LaTeX comment containing all attributes as <tt>key="value"</tt> pairs.
|
data/lib/kramdown/options.rb
CHANGED
@@ -119,6 +119,31 @@ module Kramdown
|
|
119
119
|
data
|
120
120
|
end
|
121
121
|
|
122
|
+
# ----------------------------
|
123
|
+
# :section: Option Validators
|
124
|
+
#
|
125
|
+
# This sections contains all pre-defined option validators.
|
126
|
+
# ----------------------------
|
127
|
+
|
128
|
+
# Ensures that the option value +val+ for the option called +name+ is a valid array. The
|
129
|
+
# parameter +val+ can be
|
130
|
+
#
|
131
|
+
# - a comma separated string which is split into an array of values
|
132
|
+
# - or an array.
|
133
|
+
#
|
134
|
+
# Additionally, the array is checked for the correct size.
|
135
|
+
def self.simple_array_validator(val, name, size)
|
136
|
+
if String === val
|
137
|
+
val = val.split(/,/)
|
138
|
+
elsif !(Array === val)
|
139
|
+
raise Kramdown::Error, "Invalid type #{val.class} for option #{name}"
|
140
|
+
end
|
141
|
+
if val.size != size
|
142
|
+
raise Kramdown::Error, "Option #{name} needs exactly #{size} values"
|
143
|
+
end
|
144
|
+
val
|
145
|
+
end
|
146
|
+
|
122
147
|
# ----------------------------
|
123
148
|
# :section: Option Definitions
|
124
149
|
#
|
@@ -141,7 +166,7 @@ file still cannot be found, the templates name is interpreted as a
|
|
141
166
|
template name that is provided by kramdown (without the converter
|
142
167
|
extension).
|
143
168
|
|
144
|
-
kramdown provides a default template named '
|
169
|
+
kramdown provides a default template named 'document' for each converter.
|
145
170
|
|
146
171
|
Default: ''
|
147
172
|
Used by: all converters
|
@@ -277,17 +302,6 @@ on Ruby 1.9).
|
|
277
302
|
|
278
303
|
Default: :as_char
|
279
304
|
Used by: HTML converter, kramdown converter
|
280
|
-
EOF
|
281
|
-
|
282
|
-
define(:toc_depth, Integer, -1, <<EOF)
|
283
|
-
DEPRECATED: Defines the maximum level of headers which will be used to generate the table of
|
284
|
-
contents. For instance, with a value of 2, toc entries will be generated for h1
|
285
|
-
and h2 headers but not for h3, h4, etc. A value of 0 uses all header levels.
|
286
|
-
|
287
|
-
Use option toc_levels instead!
|
288
|
-
|
289
|
-
Default: -1
|
290
|
-
Used by: HTML/Latex converter
|
291
305
|
EOF
|
292
306
|
|
293
307
|
define(:toc_levels, Object, (1..6).to_a, <<EOF) do |val|
|
@@ -335,14 +349,22 @@ separating them with commas.
|
|
335
349
|
Default: section,subsection,subsubsection,paragraph,subparagraph,subsubparagraph
|
336
350
|
Used by: Latex converter
|
337
351
|
EOF
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
352
|
+
simple_array_validator(val, :latex_headers, 6)
|
353
|
+
end
|
354
|
+
|
355
|
+
define(:smart_quotes, Object, %w{lsquo rsquo ldquo rdquo}, <<EOF) do |val|
|
356
|
+
Defines the HTML entity names or code points for smart quote output
|
357
|
+
|
358
|
+
The entities identified by entity name or code point that should be
|
359
|
+
used for, in order, a left single quote, a right single quote, a left
|
360
|
+
double and a right double quote are specified by separating them with
|
361
|
+
commas.
|
362
|
+
|
363
|
+
Default: lsquo,rsquo,ldquo,rdquo
|
364
|
+
Used by: HTML/Latex converter
|
365
|
+
EOF
|
366
|
+
val = simple_array_validator(val, :smart_quotes, 4)
|
367
|
+
val.map! {|v| Integer(v) rescue v}
|
346
368
|
val
|
347
369
|
end
|
348
370
|
|
data/lib/kramdown/parser/html.rb
CHANGED
@@ -260,7 +260,12 @@ module Kramdown
|
|
260
260
|
elsif %w{mdash ndash hellip laquo raquo}.include?(val)
|
261
261
|
Element.new(:typographic_sym, val.intern)
|
262
262
|
else
|
263
|
-
|
263
|
+
begin
|
264
|
+
Element.new(:entity, entity(val), nil, :original => src.matched)
|
265
|
+
rescue ::Kramdown::Error
|
266
|
+
src.pos -= src.matched_size - 1
|
267
|
+
Element.new(:entity, ::Kramdown::Utils::Entities.entity('amp'))
|
268
|
+
end
|
264
269
|
end
|
265
270
|
else
|
266
271
|
result << Element.new(:text, src.rest)
|
@@ -339,14 +344,19 @@ module Kramdown
|
|
339
344
|
end
|
340
345
|
end
|
341
346
|
|
342
|
-
|
343
|
-
|
344
|
-
|
347
|
+
EMPHASIS_TYPE_MAP = {'em' => :em, 'i' => :em, 'strong' => :strong, 'b' => :strong}
|
348
|
+
def convert_em(el)
|
349
|
+
text = ''
|
350
|
+
extract_text(el, text)
|
351
|
+
if text =~ /\A\s/ || text =~ /\s\z/
|
352
|
+
process_html_element(el, false)
|
353
|
+
else
|
354
|
+
set_basics(el, EMPHASIS_TYPE_MAP[el.value])
|
355
|
+
process_children(el)
|
356
|
+
end
|
345
357
|
end
|
346
|
-
|
347
|
-
|
348
|
-
set_basics(el, :em)
|
349
|
-
process_children(el)
|
358
|
+
%w{b strong i}.each do |i|
|
359
|
+
alias_method("convert_#{i}".to_sym, :convert_em)
|
350
360
|
end
|
351
361
|
|
352
362
|
def convert_h1(el)
|
@@ -405,15 +415,25 @@ module Kramdown
|
|
405
415
|
set_basics(el, :table)
|
406
416
|
el.options[:alignment] = []
|
407
417
|
|
418
|
+
nr_cols = 0
|
408
419
|
calc_alignment = lambda do |c|
|
409
|
-
|
410
|
-
|
420
|
+
align = c.attr['align']
|
421
|
+
if c.type == :html_element && c.value == 'col' && (align.nil? || %w{left right center}.include?(align))
|
422
|
+
el.options[:alignment] << (align.nil? ? :default : align.to_sym)
|
423
|
+
elsif c.type == :tr
|
424
|
+
nr_cols = c.children.length
|
411
425
|
break
|
412
426
|
else
|
413
427
|
c.children.each {|cc| calc_alignment.call(cc)}
|
414
428
|
end
|
415
429
|
end
|
416
430
|
calc_alignment.call(el)
|
431
|
+
if el.options[:alignment].length > nr_cols
|
432
|
+
el.options[:alignment][nr_cols..-1] = []
|
433
|
+
else
|
434
|
+
el.options[:alignment] += [:default] * (nr_cols - el.options[:alignment].length)
|
435
|
+
end
|
436
|
+
el.children.delete_if {|c| c.type == :html_element}
|
417
437
|
|
418
438
|
change_th_type = lambda do |c|
|
419
439
|
if c.type == :th
|
@@ -446,12 +466,31 @@ module Kramdown
|
|
446
466
|
end
|
447
467
|
check_cells.call(el)
|
448
468
|
|
469
|
+
nr_cells = 0
|
470
|
+
check_nr_cells = lambda do |t|
|
471
|
+
if t.value == 'tr'
|
472
|
+
count = t.children.select {|cc| cc.value == 'th' || cc.value == 'td'}.length
|
473
|
+
if count != nr_cells
|
474
|
+
if nr_cells == 0
|
475
|
+
nr_cells = count
|
476
|
+
else
|
477
|
+
nr_cells = -1
|
478
|
+
break
|
479
|
+
end
|
480
|
+
end
|
481
|
+
else
|
482
|
+
t.children.each {|cc| check_nr_cells.call(cc)}
|
483
|
+
end
|
484
|
+
end
|
485
|
+
check_nr_cells.call(el)
|
486
|
+
return false if nr_cells == -1
|
487
|
+
|
449
488
|
check_rows = lambda do |t, type|
|
450
489
|
t.children.all? {|r| (r.value == 'tr' || r.type == :text) && r.children.all? {|c| c.value == type || c.type == :text}}
|
451
490
|
end
|
452
491
|
check_rows.call(el, 'td') ||
|
453
492
|
(el.children.all? do |t|
|
454
|
-
t.type == :text || (t.value == 'thead' && check_rows.call(t, 'th')) ||
|
493
|
+
t.type == :text || t.value == 'col' || (t.value == 'thead' && check_rows.call(t, 'th')) ||
|
455
494
|
((t.value == 'tfoot' || t.value == 'tbody') && check_rows.call(t, 'td'))
|
456
495
|
end && el.children.any? {|t| t.value == 'tbody'})
|
457
496
|
end
|