kramdown 0.1.0
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/AUTHORS +1 -0
- data/COPYING +24 -0
- data/ChangeLog +1416 -0
- data/GPL +674 -0
- data/README +20 -0
- data/Rakefile +300 -0
- data/VERSION +1 -0
- data/benchmark/benchmark.rb +33 -0
- data/benchmark/mdbasics.text +306 -0
- data/benchmark/mdsyntax.text +888 -0
- data/benchmark/testing.sh +9 -0
- data/benchmark/timing.sh +10 -0
- data/bin/kramdown +26 -0
- data/doc/default.css +293 -0
- data/doc/default.template +78 -0
- data/doc/index.page +89 -0
- data/doc/installation.page +90 -0
- data/doc/news.feed +10 -0
- data/doc/news.page +27 -0
- data/doc/quickref.page +474 -0
- data/doc/syntax.page +1089 -0
- data/doc/tests.page +44 -0
- data/doc/virtual +2 -0
- data/lib/kramdown.rb +23 -0
- data/lib/kramdown/converter.rb +215 -0
- data/lib/kramdown/document.rb +150 -0
- data/lib/kramdown/error.rb +27 -0
- data/lib/kramdown/extension.rb +73 -0
- data/lib/kramdown/parser.rb +1056 -0
- data/lib/kramdown/parser/registry.rb +62 -0
- data/setup.rb +1585 -0
- data/test/run_tests.rb +58 -0
- data/test/test_files.rb +39 -0
- data/test/testcases/block/01_blank_line/spaces.html +1 -0
- data/test/testcases/block/01_blank_line/spaces.text +3 -0
- data/test/testcases/block/01_blank_line/tabs.html +1 -0
- data/test/testcases/block/01_blank_line/tabs.text +6 -0
- data/test/testcases/block/02_eob/beginning.html +1 -0
- data/test/testcases/block/02_eob/beginning.text +3 -0
- data/test/testcases/block/02_eob/end.html +1 -0
- data/test/testcases/block/02_eob/end.text +3 -0
- data/test/testcases/block/02_eob/middle.html +1 -0
- data/test/testcases/block/02_eob/middle.text +5 -0
- data/test/testcases/block/03_paragraph/indented.html +18 -0
- data/test/testcases/block/03_paragraph/indented.text +19 -0
- data/test/testcases/block/03_paragraph/no_newline_at_end.html +5 -0
- data/test/testcases/block/03_paragraph/no_newline_at_end.text +5 -0
- data/test/testcases/block/03_paragraph/one_para.html +1 -0
- data/test/testcases/block/03_paragraph/one_para.text +1 -0
- data/test/testcases/block/03_paragraph/two_para.html +4 -0
- data/test/testcases/block/03_paragraph/two_para.text +4 -0
- data/test/testcases/block/04_header/atx_header.html +26 -0
- data/test/testcases/block/04_header/atx_header.text +24 -0
- data/test/testcases/block/04_header/atx_header_no_newline_at_end.html +1 -0
- data/test/testcases/block/04_header/atx_header_no_newline_at_end.text +1 -0
- data/test/testcases/block/04_header/setext_header.html +25 -0
- data/test/testcases/block/04_header/setext_header.text +27 -0
- data/test/testcases/block/04_header/setext_header_no_newline_at_end.html +1 -0
- data/test/testcases/block/04_header/setext_header_no_newline_at_end.text +2 -0
- data/test/testcases/block/04_header/with_auto_ids.html +17 -0
- data/test/testcases/block/04_header/with_auto_ids.options +1 -0
- data/test/testcases/block/04_header/with_auto_ids.text +19 -0
- data/test/testcases/block/05_blockquote/indented.html +25 -0
- data/test/testcases/block/05_blockquote/indented.text +14 -0
- data/test/testcases/block/05_blockquote/nested.html +9 -0
- data/test/testcases/block/05_blockquote/nested.text +5 -0
- data/test/testcases/block/05_blockquote/no_newline_at_end.html +4 -0
- data/test/testcases/block/05_blockquote/no_newline_at_end.text +2 -0
- data/test/testcases/block/05_blockquote/only_first_quoted.html +8 -0
- data/test/testcases/block/05_blockquote/only_first_quoted.text +4 -0
- data/test/testcases/block/05_blockquote/with_code_blocks.html +15 -0
- data/test/testcases/block/05_blockquote/with_code_blocks.text +11 -0
- data/test/testcases/block/06_codeblock/error.html +4 -0
- data/test/testcases/block/06_codeblock/error.text +4 -0
- data/test/testcases/block/06_codeblock/no_newline_at_end.html +2 -0
- data/test/testcases/block/06_codeblock/no_newline_at_end.text +1 -0
- data/test/testcases/block/06_codeblock/normal.html +13 -0
- data/test/testcases/block/06_codeblock/normal.text +10 -0
- data/test/testcases/block/06_codeblock/tilde_syntax.html +7 -0
- data/test/testcases/block/06_codeblock/tilde_syntax.text +9 -0
- data/test/testcases/block/06_codeblock/whitespace.html +3 -0
- data/test/testcases/block/06_codeblock/whitespace.text +3 -0
- data/test/testcases/block/06_codeblock/with_blank_line.html +13 -0
- data/test/testcases/block/06_codeblock/with_blank_line.text +11 -0
- data/test/testcases/block/06_codeblock/with_eob_marker.html +6 -0
- data/test/testcases/block/06_codeblock/with_eob_marker.text +5 -0
- data/test/testcases/block/07_horizontal_rule/error.html +7 -0
- data/test/testcases/block/07_horizontal_rule/error.text +7 -0
- data/test/testcases/block/07_horizontal_rule/normal.html +19 -0
- data/test/testcases/block/07_horizontal_rule/normal.text +19 -0
- data/test/testcases/block/08_list/escaping.html +17 -0
- data/test/testcases/block/08_list/escaping.text +17 -0
- data/test/testcases/block/08_list/list_and_hr.html +9 -0
- data/test/testcases/block/08_list/list_and_hr.text +5 -0
- data/test/testcases/block/08_list/list_and_others.html +38 -0
- data/test/testcases/block/08_list/list_and_others.text +25 -0
- data/test/testcases/block/08_list/mixed.html +111 -0
- data/test/testcases/block/08_list/mixed.text +66 -0
- data/test/testcases/block/08_list/nested.html +17 -0
- data/test/testcases/block/08_list/nested.text +7 -0
- data/test/testcases/block/08_list/other_first_element.html +39 -0
- data/test/testcases/block/08_list/other_first_element.text +18 -0
- data/test/testcases/block/08_list/simple_ol.html +19 -0
- data/test/testcases/block/08_list/simple_ol.text +13 -0
- data/test/testcases/block/08_list/simple_ul.html +61 -0
- data/test/testcases/block/08_list/simple_ul.text +43 -0
- data/test/testcases/block/08_list/single_item.html +3 -0
- data/test/testcases/block/08_list/single_item.text +1 -0
- data/test/testcases/block/08_list/special_cases.html +29 -0
- data/test/testcases/block/08_list/special_cases.text +19 -0
- data/test/testcases/block/09_html/auto_parse_block_html.html +17 -0
- data/test/testcases/block/09_html/auto_parse_block_html.options +1 -0
- data/test/testcases/block/09_html/auto_parse_block_html.text +14 -0
- data/test/testcases/block/09_html/comment.html +12 -0
- data/test/testcases/block/09_html/comment.text +12 -0
- data/test/testcases/block/09_html/filtered_html.html +1 -0
- data/test/testcases/block/09_html/filtered_html.options +1 -0
- data/test/testcases/block/09_html/filtered_html.text +1 -0
- data/test/testcases/block/09_html/html_and_codeblocks.html +15 -0
- data/test/testcases/block/09_html/html_and_codeblocks.options +1 -0
- data/test/testcases/block/09_html/html_and_codeblocks.text +13 -0
- data/test/testcases/block/09_html/invalid_html_1.html +5 -0
- data/test/testcases/block/09_html/invalid_html_1.text +5 -0
- data/test/testcases/block/09_html/invalid_html_2.html +6 -0
- data/test/testcases/block/09_html/invalid_html_2.text +5 -0
- data/test/testcases/block/09_html/parse_as_raw.html +26 -0
- data/test/testcases/block/09_html/parse_as_raw.text +16 -0
- data/test/testcases/block/09_html/parse_as_span.html +12 -0
- data/test/testcases/block/09_html/parse_as_span.text +7 -0
- data/test/testcases/block/09_html/processing_instruction.html +12 -0
- data/test/testcases/block/09_html/processing_instruction.text +12 -0
- data/test/testcases/block/09_html/simple.html +78 -0
- data/test/testcases/block/09_html/simple.text +56 -0
- data/test/testcases/block/10_ald/simple.html +2 -0
- data/test/testcases/block/10_ald/simple.text +8 -0
- data/test/testcases/block/11_ial/simple.html +17 -0
- data/test/testcases/block/11_ial/simple.text +25 -0
- data/test/testcases/block/12_extension/comment.html +5 -0
- data/test/testcases/block/12_extension/comment.text +11 -0
- data/test/testcases/block/12_extension/ignored.html +6 -0
- data/test/testcases/block/12_extension/ignored.text +11 -0
- data/test/testcases/block/12_extension/kdoptions.html +15 -0
- data/test/testcases/block/12_extension/kdoptions.text +18 -0
- data/test/testcases/block/12_extension/kdoptions2.html +10 -0
- data/test/testcases/block/12_extension/kdoptions2.text +5 -0
- data/test/testcases/block/12_extension/nokramdown.html +6 -0
- data/test/testcases/block/12_extension/nokramdown.text +11 -0
- data/test/testcases/span/01_link/empty.html +3 -0
- data/test/testcases/span/01_link/empty.text +3 -0
- data/test/testcases/span/01_link/image_in_a.html +5 -0
- data/test/testcases/span/01_link/image_in_a.text +5 -0
- data/test/testcases/span/01_link/imagelinks.html +12 -0
- data/test/testcases/span/01_link/imagelinks.text +14 -0
- data/test/testcases/span/01_link/inline.html +40 -0
- data/test/testcases/span/01_link/inline.text +42 -0
- data/test/testcases/span/01_link/link_defs.html +8 -0
- data/test/testcases/span/01_link/link_defs.text +22 -0
- data/test/testcases/span/01_link/links_with_angle_brackets.html +3 -0
- data/test/testcases/span/01_link/links_with_angle_brackets.text +3 -0
- data/test/testcases/span/01_link/reference.html +32 -0
- data/test/testcases/span/01_link/reference.text +42 -0
- data/test/testcases/span/02_emphasis/empty.html +3 -0
- data/test/testcases/span/02_emphasis/empty.text +3 -0
- data/test/testcases/span/02_emphasis/errors.html +9 -0
- data/test/testcases/span/02_emphasis/errors.text +9 -0
- data/test/testcases/span/02_emphasis/nesting.html +34 -0
- data/test/testcases/span/02_emphasis/nesting.text +30 -0
- data/test/testcases/span/02_emphasis/normal.html +42 -0
- data/test/testcases/span/02_emphasis/normal.text +42 -0
- data/test/testcases/span/03_codespan/empty.html +5 -0
- data/test/testcases/span/03_codespan/empty.text +5 -0
- data/test/testcases/span/03_codespan/errors.html +1 -0
- data/test/testcases/span/03_codespan/errors.text +1 -0
- data/test/testcases/span/03_codespan/normal.html +16 -0
- data/test/testcases/span/03_codespan/normal.text +16 -0
- data/test/testcases/span/04_footnote/definitions.html +14 -0
- data/test/testcases/span/04_footnote/definitions.text +18 -0
- data/test/testcases/span/04_footnote/footnote_nr.html +12 -0
- data/test/testcases/span/04_footnote/footnote_nr.options +1 -0
- data/test/testcases/span/04_footnote/footnote_nr.text +4 -0
- data/test/testcases/span/04_footnote/markers.html +46 -0
- data/test/testcases/span/04_footnote/markers.text +26 -0
- data/test/testcases/span/05_html/normal.html +17 -0
- data/test/testcases/span/05_html/normal.text +17 -0
- data/test/testcases/span/autolinks/url_links.html +9 -0
- data/test/testcases/span/autolinks/url_links.text +9 -0
- data/test/testcases/span/escaped_chars/normal.html +33 -0
- data/test/testcases/span/escaped_chars/normal.text +33 -0
- data/test/testcases/span/ial/simple.html +5 -0
- data/test/testcases/span/ial/simple.text +5 -0
- data/test/testcases/span/line_breaks/normal.html +11 -0
- data/test/testcases/span/line_breaks/normal.text +11 -0
- data/test/testcases/span/text_substitutions/entities.html +4 -0
- data/test/testcases/span/text_substitutions/entities.text +4 -0
- data/test/testcases/span/text_substitutions/greaterthan.html +1 -0
- data/test/testcases/span/text_substitutions/greaterthan.text +1 -0
- data/test/testcases/span/text_substitutions/lowerthan.html +1 -0
- data/test/testcases/span/text_substitutions/lowerthan.text +1 -0
- data/test/testcases/span/text_substitutions/typography.html +3 -0
- data/test/testcases/span/text_substitutions/typography.text +3 -0
- metadata +259 -0
data/doc/tests.page
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
---
|
2
|
+
title: Tests and Benchmark
|
3
|
+
---
|
4
|
+
|
5
|
+
# Tests
|
6
|
+
|
7
|
+
There exist several test suites for testing the correctness of a Markdown implementation. The
|
8
|
+
original [Markdown Test Suite] is the standard which one needs to test against. The [PHP Markdown
|
9
|
+
suite][MDTest] contains the original test suite and several more tests (some specifically geared
|
10
|
+
towards the extension of the PHP Markdown Extra package). I have used the latter test tool to
|
11
|
+
roughly verify that kramdown is able to parse standard Markdown. However, since the syntax used by
|
12
|
+
kramdown varies slightly from standard Markdown most of the tests fail - which is fine. When looking
|
13
|
+
at the differences one can see that the failures result from these differences.
|
14
|
+
|
15
|
+
Besides using the above mentioned test suite kramdown comes with its own set of tests which is used
|
16
|
+
to verify that the implementation matches the kramdown specification.
|
17
|
+
|
18
|
+
If you believe you have found a bug in the implementation, please follow these steps:
|
19
|
+
|
20
|
+
* Check the syntax page and see if the behaviour is not intended.
|
21
|
+
|
22
|
+
* If the behaviour is not intended and it seems that kramdown should parse some text in another
|
23
|
+
fashion, please open a bug report and attach two files: one with the text and one with the HTML
|
24
|
+
conversion you think is correct.
|
25
|
+
|
26
|
+
^
|
27
|
+
|
28
|
+
# Benchmark
|
29
|
+
|
30
|
+
kramdown comes with a small benchmark to test how fast it is in regard to four other Ruby Markdown
|
31
|
+
implementations: Maruku, BlueFeather, BlueCloth and RDiscount. The first two are written using only
|
32
|
+
Ruby, the latter two use the C discount library for the actual hard work (which makes them really
|
33
|
+
fast but they do not provide additional syntax elements). As one can see below, kramdown is
|
34
|
+
currently (November 2009) ~5x faster than Maruku, ~10x faster than BlueFeather but ~30x slower than
|
35
|
+
BlueCloth and rdiscount:
|
36
|
+
|
37
|
+
{::nokramdown:}
|
38
|
+
<pre><code>
|
39
|
+
{execute_cmd: {command: "ruby -Ilib -rubygems benchmark/benchmark.rb", process_output: false, escape_html: true}}
|
40
|
+
</code></pre>
|
41
|
+
{::nokramdown:}
|
42
|
+
|
43
|
+
[Markdown Test Suite]: http://daringfireball.net/projects/downloads/MarkdownTest_1.0.zip
|
44
|
+
[MDTest]: http://www.michelf.com/docs/projets/mdtest-1.0.zip
|
data/doc/virtual
ADDED
data/lib/kramdown.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2009 Thomas Leitner <t_leitner@gmx.at>
|
5
|
+
#
|
6
|
+
# This file is part of kramdown.
|
7
|
+
#
|
8
|
+
# kramdown is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'kramdown/document'
|
@@ -0,0 +1,215 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2009 Thomas Leitner <t_leitner@gmx.at>
|
5
|
+
#
|
6
|
+
# This file is part of kramdown.
|
7
|
+
#
|
8
|
+
# kramdown is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'rexml/parsers/baseparser'
|
24
|
+
|
25
|
+
module Kramdown
|
26
|
+
|
27
|
+
# This module contains all available converters, i.e. classes that take a document and convert the
|
28
|
+
# document tree to a string in a specific format, for example, HTML.
|
29
|
+
module Converter
|
30
|
+
|
31
|
+
# Converts a Kramdown::Document to HTML.
|
32
|
+
class Html
|
33
|
+
|
34
|
+
# Initialize the HTML converter with the given Kramdown document +doc+.
|
35
|
+
def initialize(doc)
|
36
|
+
@doc = doc
|
37
|
+
@footnote_counter = @footnote_start = @doc.options[:footnote_nr]
|
38
|
+
@footnotes = []
|
39
|
+
end
|
40
|
+
private_class_method(:new, :allocate)
|
41
|
+
|
42
|
+
# Convert the Kramdown document +doc+ to HTML.
|
43
|
+
def self.convert(doc)
|
44
|
+
new(doc).convert(doc.tree)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Convert the element tree +el+, setting the indentation level to +indent+.
|
48
|
+
def convert(el, indent = -2)
|
49
|
+
result = ''
|
50
|
+
el.children.each do |inner_el|
|
51
|
+
result << convert(inner_el, indent + 2)
|
52
|
+
end
|
53
|
+
send("convert_#{el.type}", el, result, indent)
|
54
|
+
end
|
55
|
+
|
56
|
+
def convert_blank(el, inner, indent)
|
57
|
+
"\n"
|
58
|
+
end
|
59
|
+
|
60
|
+
def convert_text(el, inner, indent)
|
61
|
+
escape_html(el.value, false)
|
62
|
+
end
|
63
|
+
|
64
|
+
def convert_p(el, inner, indent)
|
65
|
+
"#{' '*indent}<p#{options_for_element(el)}>#{inner}</p>\n"
|
66
|
+
end
|
67
|
+
|
68
|
+
def convert_codeblock(el, inner, indent)
|
69
|
+
result = escape_html(el.value)
|
70
|
+
if el.options[:attr] && el.options[:attr].has_key?('class') && el.options[:attr]['class'] =~ /\bshow-whitespaces\b/
|
71
|
+
result.gsub!(/(?:(^[ \t]+)|([ \t]+$)|([ \t]+))/) do |m|
|
72
|
+
suffix = ($1 ? '-l' : ($2 ? '-r' : ''))
|
73
|
+
m.scan(/./).map do |c|
|
74
|
+
case c
|
75
|
+
when "\t" then "<span class=\"ws-tab#{suffix}\">\t</span>"
|
76
|
+
when " " then "<span class=\"ws-space#{suffix}\">⋅</span>"
|
77
|
+
end
|
78
|
+
end.join('')
|
79
|
+
end
|
80
|
+
end
|
81
|
+
"#{' '*indent}<pre#{options_for_element(el)}><code>#{result}#{result =~ /\n\Z/ ? '' : "\n"}</code></pre>\n"
|
82
|
+
end
|
83
|
+
|
84
|
+
def convert_blockquote(el, inner, indent)
|
85
|
+
"#{' '*indent}<blockquote#{options_for_element(el)}>\n#{inner}#{' '*indent}</blockquote>\n"
|
86
|
+
end
|
87
|
+
|
88
|
+
def convert_header(el, inner, indent)
|
89
|
+
"#{' '*indent}<h#{el.options[:level]}#{options_for_element(el)}>#{inner}</h#{el.options[:level]}>\n"
|
90
|
+
end
|
91
|
+
|
92
|
+
def convert_hr(el, inner, indent)
|
93
|
+
"#{' '*indent}<hr />\n"
|
94
|
+
end
|
95
|
+
|
96
|
+
def convert_ul(el, inner, indent)
|
97
|
+
"#{' '*indent}<#{el.type}#{options_for_element(el)}>\n#{inner}#{' '*indent}</#{el.type}>\n"
|
98
|
+
end
|
99
|
+
alias :convert_ol :convert_ul
|
100
|
+
|
101
|
+
def convert_li(el, inner, indent)
|
102
|
+
output = ' '*indent << "<li" << options_for_element(el) << ">"
|
103
|
+
if el.options[:first_as_block]
|
104
|
+
output << "\n" << inner << ' '*indent
|
105
|
+
else
|
106
|
+
output << inner << (inner =~ /\n\Z/ ? ' '*indent : '')
|
107
|
+
end
|
108
|
+
output << "</li>\n"
|
109
|
+
end
|
110
|
+
|
111
|
+
def convert_html_raw(el, inner, indent)
|
112
|
+
el.value + (el.options[:type] == :block ? "\n" : '')
|
113
|
+
end
|
114
|
+
|
115
|
+
HTML_TAGS_WITH_BODY=['div']
|
116
|
+
|
117
|
+
def convert_html_element(el, inner, indent)
|
118
|
+
if @doc.options[:filter_html].include?(el.value)
|
119
|
+
inner.chomp + (el.options[:type] == :block ? "\n" : '')
|
120
|
+
elsif el.options[:type] == :span
|
121
|
+
"<#{el.value}#{options_for_element(el)}" << (!inner.empty? ? ">#{inner}</#{el.value}>" : " />")
|
122
|
+
else
|
123
|
+
output = ' '*indent << "<#{el.value}#{options_for_element(el)}"
|
124
|
+
if !inner.empty?
|
125
|
+
output << ">\n#{inner.chomp}\n" << ' '*indent << "</#{el.value}>"
|
126
|
+
elsif HTML_TAGS_WITH_BODY.include?(el.value)
|
127
|
+
output << "></#{el.value}>"
|
128
|
+
else
|
129
|
+
output << " />"
|
130
|
+
end
|
131
|
+
output << "\n"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def convert_br(el, inner, indent)
|
136
|
+
"<br />"
|
137
|
+
end
|
138
|
+
|
139
|
+
def convert_a(el, inner, indent)
|
140
|
+
"<a#{options_for_element(el)}>#{inner}</a>"
|
141
|
+
end
|
142
|
+
|
143
|
+
def convert_img(el, inner, indent)
|
144
|
+
"<img#{options_for_element(el)} />"
|
145
|
+
end
|
146
|
+
|
147
|
+
def convert_codespan(el, inner, indent)
|
148
|
+
"<code#{options_for_element(el)}>#{escape_html(el.value)}</code>"
|
149
|
+
end
|
150
|
+
|
151
|
+
def convert_footnote(el, inner, indent)
|
152
|
+
number = @footnote_counter
|
153
|
+
@footnote_counter += 1
|
154
|
+
@footnotes << [el.options[:name], @doc.parse_infos[:footnotes][el.options[:name]]]
|
155
|
+
"<sup id=\"fnref:#{el.options[:name]}\"><a href=\"#fn:#{el.options[:name]}\" rel=\"footnote\">#{number}</a></sup>"
|
156
|
+
end
|
157
|
+
|
158
|
+
def convert_raw(el, inner, indent)
|
159
|
+
el.value
|
160
|
+
end
|
161
|
+
|
162
|
+
def convert_em(el, inner, indent)
|
163
|
+
"<#{el.type}#{options_for_element(el)}>#{inner}</#{el.type}>"
|
164
|
+
end
|
165
|
+
alias :convert_strong :convert_em
|
166
|
+
|
167
|
+
def convert_root(el, inner, indent)
|
168
|
+
inner << footnote_content
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
# Return a HTML list with the footnote content for the used footnotes.
|
173
|
+
def footnote_content
|
174
|
+
ol = Element.new(:ol)
|
175
|
+
ol.options[:attr] = {'start' => @footnote_start} if @footnote_start != 1
|
176
|
+
@footnotes.each do |name, data|
|
177
|
+
li = Element.new(:li, nil, {:attr => {:id => "fn:#{name}"}, :first_as_block => true})
|
178
|
+
li.children = Marshal.load(Marshal.dump(data[:content].children)) #TODO: probably remove this!!!!
|
179
|
+
ol.children << li
|
180
|
+
|
181
|
+
ref = Element.new(:raw, "<a href=\"#fnref:#{name}\" rev=\"footnote\">↩</a>")
|
182
|
+
if li.children.last.type == :p
|
183
|
+
para = li.children.last
|
184
|
+
else
|
185
|
+
li.children << (para = Element.new(:p))
|
186
|
+
end
|
187
|
+
para.children << ref
|
188
|
+
end
|
189
|
+
(ol.children.empty? ? '' : "<div class=\"kramdown-footnotes\">\n#{convert(ol, 2)}</div>\n")
|
190
|
+
end
|
191
|
+
|
192
|
+
# Return the string with the attributes of the element +el+.
|
193
|
+
def options_for_element(el)
|
194
|
+
(el.options[:attr] || {}).map {|k,v| v.nil? ? '' : " #{k}=\"#{escape_html(v.to_s, false)}\"" }.sort.join('')
|
195
|
+
end
|
196
|
+
|
197
|
+
ESCAPE_MAP = {
|
198
|
+
'<' => '<',
|
199
|
+
'>' => '>',
|
200
|
+
'"' => '"',
|
201
|
+
'&' => '&'
|
202
|
+
}
|
203
|
+
ESCAPE_ALL_RE = Regexp.union(*ESCAPE_MAP.collect {|k,v| Regexp.escape(k)})
|
204
|
+
ESCAPE_ALL_NOT_ENTITIES_RE = Regexp.union(REXML::Parsers::BaseParser::REFERENCE_RE, ESCAPE_ALL_RE)
|
205
|
+
|
206
|
+
# Escape the special HTML characters in the string +str+. If +all+ is +true+ then all
|
207
|
+
# characters are escaped, if +all+ is +false+
|
208
|
+
def escape_html(str, all = true)
|
209
|
+
str.gsub(all ? ESCAPE_ALL_RE : ESCAPE_ALL_NOT_ENTITIES_RE) {|m| ESCAPE_MAP[m] || m}
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2009 Thomas Leitner <t_leitner@gmx.at>
|
5
|
+
#
|
6
|
+
# This file is part of kramdown.
|
7
|
+
#
|
8
|
+
# kramdown is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
require 'kramdown/error'
|
24
|
+
require 'kramdown/parser'
|
25
|
+
require 'kramdown/converter'
|
26
|
+
require 'kramdown/extension'
|
27
|
+
|
28
|
+
module Kramdown
|
29
|
+
|
30
|
+
# The kramdown version.
|
31
|
+
VERSION = '0.1.0'
|
32
|
+
|
33
|
+
# The main interface to kramdown.
|
34
|
+
#
|
35
|
+
# This class provides a one-stop-shop for using kramdown to convert text into various output
|
36
|
+
# formats. Use it like this:
|
37
|
+
#
|
38
|
+
# require 'kramdown'
|
39
|
+
# doc = Kramdown::Document.new('This *is* some kramdown text')
|
40
|
+
# puts doc.to_html
|
41
|
+
#
|
42
|
+
# The #to_html method is a shortcut for using the Converter::ToHtml class. If other converters are
|
43
|
+
# added later, there may be additional shortcut methods.
|
44
|
+
#
|
45
|
+
# The second argument to the #new method is an options hash for customizing the behaviour of
|
46
|
+
# kramdown.
|
47
|
+
class Document
|
48
|
+
|
49
|
+
# Currently available options are:
|
50
|
+
#
|
51
|
+
# [:auto_ids (used by the parser)]
|
52
|
+
# A boolean value deciding whether automatic header ID generation is used. Default: +false+.
|
53
|
+
# When using the +kdoptions+ extension, the string 'false' will be the value +false+, every
|
54
|
+
# other non-empty string will be +true+.
|
55
|
+
# [:filter_html (used by the HTML converter)]
|
56
|
+
# An array of HTML tag names that defines which tags should be filtered from the output. For
|
57
|
+
# example, if the value contains +iframe+, then all HTML +iframe+ tags are filtered out and
|
58
|
+
# only the body is displayed. Default: empty array. When using the +kdoptions+ extension, the
|
59
|
+
# string value needs to hold the HTML tag names separated by one or more spaces.
|
60
|
+
# [:footnote_nr (used by the HTML converter)]
|
61
|
+
# The initial number used for creating the link to the first footnote. Default: +1+. When
|
62
|
+
# using the +kdoptions+ extension, the string value needs to be a valid number.
|
63
|
+
DEFAULT_OPTIONS={
|
64
|
+
:footnote_nr => 1,
|
65
|
+
:filter_html => [],
|
66
|
+
:auto_ids => false
|
67
|
+
}
|
68
|
+
|
69
|
+
|
70
|
+
# The element tree of the document. It is immediately available after the #new method has been
|
71
|
+
# called.
|
72
|
+
attr_accessor :tree
|
73
|
+
|
74
|
+
# The options hash which holds the options for parsing/converting the Kramdown document. It is
|
75
|
+
# possible that these values get changed during the parsing phase.
|
76
|
+
attr_accessor :options
|
77
|
+
|
78
|
+
# An array of warning messages. It is filled with warnings during the parsing phase (i.e. in
|
79
|
+
# #new) and the converting phase.
|
80
|
+
attr_reader :warnings
|
81
|
+
|
82
|
+
# Holds needed parse information like ALDs, link definitions and so on.
|
83
|
+
attr_reader :parse_infos
|
84
|
+
|
85
|
+
# Holds an instance of the extension class.
|
86
|
+
attr_reader :extension
|
87
|
+
|
88
|
+
|
89
|
+
# Create a new Kramdown document from the string +source+ and use the provided +options+ (see
|
90
|
+
# DEFAULT_OPTIONS for a list of available options). The +source+ is immediately parsed by the
|
91
|
+
# kramdown parser sothat after this call the output can be generated.
|
92
|
+
#
|
93
|
+
# The parameter +ext+ can be used to set a custom extension class. Note that the default
|
94
|
+
# kramdown extensions should be available in the custom extension class.
|
95
|
+
def initialize(source, options = {}, ext = nil)
|
96
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
97
|
+
@warnings = []
|
98
|
+
@parse_infos = {}
|
99
|
+
@extension = extension || Kramdown::Extension.new
|
100
|
+
@tree = Parser::Kramdown.parse(source, self)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Convert the document to HTML. Uses the Converter::ToHtml class for doing the conversion.
|
104
|
+
def to_html
|
105
|
+
Converter::Html.convert(self)
|
106
|
+
end
|
107
|
+
|
108
|
+
def inspect #:nodoc:
|
109
|
+
"<KD:Document: options=#{@options.inspect} tree=#{@tree.inspect} warnings=#{@warnings.inspect}>"
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
# Represents all elements in the parse tree.
|
116
|
+
#
|
117
|
+
# kramdown only uses this one class for representing all available elements in a parse tree
|
118
|
+
# (paragraphs, headers, emphasis, ...). The type of element can be set via the #type accessor.
|
119
|
+
class Element
|
120
|
+
|
121
|
+
# A symbol representing the element type. For example, +:p+ or +:blockquote+.
|
122
|
+
attr_accessor :type
|
123
|
+
|
124
|
+
# The value of the element. The interpretation of this field depends on the type of the element.
|
125
|
+
# Many elements don't use this field.
|
126
|
+
attr_accessor :value
|
127
|
+
|
128
|
+
# The options hash for the element. It is used for storing arbitray options as well as the
|
129
|
+
# *attributes* of the element under the <tt>:attr</tt> key.
|
130
|
+
attr_accessor :options
|
131
|
+
|
132
|
+
# The child elements of this element.
|
133
|
+
attr_accessor :children
|
134
|
+
|
135
|
+
|
136
|
+
# Create a new Element object of type +type+. The optional parameters +value+ and +options+ can
|
137
|
+
# also be set in this constructor for convenience.
|
138
|
+
def initialize(type, value = nil, options = {})
|
139
|
+
@type, @value, @options = type, value, options
|
140
|
+
@children = []
|
141
|
+
end
|
142
|
+
|
143
|
+
def inspect #:nodoc:
|
144
|
+
"<kd:#{@type}#{@value.nil? ? '' : ' ' + @value.inspect}#{options.empty? ? '' : ' ' + @options.inspect}#{@children.empty? ? '' : ' ' + @children.inspect}>"
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# Copyright (C) 2009 Thomas Leitner <t_leitner@gmx.at>
|
5
|
+
#
|
6
|
+
# This file is part of kramdown.
|
7
|
+
#
|
8
|
+
# kramdown is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
#++
|
21
|
+
#
|
22
|
+
|
23
|
+
module Kramdown
|
24
|
+
|
25
|
+
class Error < RuntimeError; end
|
26
|
+
|
27
|
+
end
|