tartan 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README +130 -0
- data/TODO +17 -0
- data/lib/core_ext/array.rb +12 -0
- data/lib/core_ext/file.rb +15 -0
- data/lib/core_ext/hash.rb +16 -0
- data/lib/core_ext/match_data.rb +62 -0
- data/lib/core_ext/module.rb +17 -0
- data/lib/core_ext/regexp.rb +33 -0
- data/lib/markdown.yml +499 -0
- data/lib/symbolize.rb +78 -0
- data/lib/table.yml +63 -0
- data/lib/tartan.rb +359 -0
- data/lib/tartan_markdown.rb +8 -0
- data/lib/tartan_markdown_def.rb +7 -0
- data/lib/tartan_table_def.rb +7 -0
- data/lib/tartan_test_base_def.rb +5 -0
- data/lib/tartan_wikilink_def.rb +14 -0
- data/lib/test_base.yml +18 -0
- data/lib/wiki-test.rb +94 -0
- data/lib/wiki_rule.rb +240 -0
- data/lib/wikilink.yml +18 -0
- data/test/MarkdownTest_1.0/Amps and angle encoding.html +17 -0
- data/test/MarkdownTest_1.0/Amps and angle encoding.text +21 -0
- data/test/MarkdownTest_1.0/Auto links.html +18 -0
- data/test/MarkdownTest_1.0/Auto links.text +13 -0
- data/test/MarkdownTest_1.0/Backslash codeescapes.html +68 -0
- data/test/MarkdownTest_1.0/Backslash codeescapes.text +68 -0
- data/test/MarkdownTest_1.0/Backslash simpleescapes.html +33 -0
- data/test/MarkdownTest_1.0/Backslash simpleescapes.text +33 -0
- data/test/MarkdownTest_1.0/Blockquotes with code blocks.html +15 -0
- data/test/MarkdownTest_1.0/Blockquotes with code blocks.text +11 -0
- data/test/MarkdownTest_1.0/Hard-wrapped paragraphs with list-like lines.html +8 -0
- data/test/MarkdownTest_1.0/Hard-wrapped paragraphs with list-like lines.text +8 -0
- data/test/MarkdownTest_1.0/Horizontal rules.html +71 -0
- data/test/MarkdownTest_1.0/Horizontal rules.text +67 -0
- data/test/MarkdownTest_1.0/Inline HTML (Advanced).html +14 -0
- data/test/MarkdownTest_1.0/Inline HTML (Advanced).text +14 -0
- data/test/MarkdownTest_1.0/Inline HTML (Simple).html +72 -0
- data/test/MarkdownTest_1.0/Inline HTML (Simple).text +69 -0
- data/test/MarkdownTest_1.0/Inline HTML comments.html +13 -0
- data/test/MarkdownTest_1.0/Inline HTML comments.text +13 -0
- data/test/MarkdownTest_1.0/Links, inline style.html +9 -0
- data/test/MarkdownTest_1.0/Links, inline style.text +9 -0
- data/test/MarkdownTest_1.0/Links, reference style.html +18 -0
- data/test/MarkdownTest_1.0/Links, reference style.text +31 -0
- data/test/MarkdownTest_1.0/Literal quotes in titles.html +3 -0
- data/test/MarkdownTest_1.0/Literal quotes in titles.text +7 -0
- data/test/MarkdownTest_1.0/Markdown Documentation - Basics.html +314 -0
- data/test/MarkdownTest_1.0/Markdown Documentation - Basics.text +306 -0
- data/test/MarkdownTest_1.0/Markdown Documentation - Syntax.html +942 -0
- data/test/MarkdownTest_1.0/Markdown Documentation - Syntax.text +888 -0
- data/test/MarkdownTest_1.0/Nested blockquotes.html +9 -0
- data/test/MarkdownTest_1.0/Nested blockquotes.text +5 -0
- data/test/MarkdownTest_1.0/Ordered and unordered lists.html +137 -0
- data/test/MarkdownTest_1.0/Ordered and unordered lists.text +122 -0
- data/test/MarkdownTest_1.0/Strong and em together.html +7 -0
- data/test/MarkdownTest_1.0/Strong and em together.text +7 -0
- data/test/MarkdownTest_1.0/Tabs.html +25 -0
- data/test/MarkdownTest_1.0/Tabs.text +21 -0
- data/test/MarkdownTest_1.0/Tidyness.html +8 -0
- data/test/MarkdownTest_1.0/Tidyness.text +5 -0
- data/test/MarkdownTest_1.0/run-markdown.rb +56 -0
- data/test/MarkdownTest_1.0/test-fireball-markdown.rb +177 -0
- data/test/MarkdownTest_1.0/testdiff.rb +42 -0
- data/test/harder/test-markdown-harder.rb +11 -0
- data/test/harder/test-markdown-harder.yml +111 -0
- data/test/redcloth/redcloth-markdown-tests.rb +29 -0
- data/test/redcloth/redcloth-markdown-tests.yml +218 -0
- data/test/test-combo.rb +23 -0
- data/test/test-hash.rb +31 -0
- data/test/test-markdown.rb +11 -0
- data/test/test-markdown.yml +1144 -0
- data/test/test-match-data.rb +54 -0
- data/test/test-readme-example.rb +48 -0
- data/test/test-tables.rb +16 -0
- data/test/test-tables.yml +82 -0
- data/test/test-tartan-markdown.rb +11 -0
- data/test/test-tartan.rb +306 -0
- data/test/test-wikilink.rb +18 -0
- data/test/test-wikilink.yml +22 -0
- data/test/wikilink-test-helper.rb +14 -0
- metadata +139 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2006 Larry Baltz & David B. Anderson
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
== Welcome to Tartan
|
2
|
+
|
3
|
+
Tartan is a general purpose text parsing engine whose main target is wiki text
|
4
|
+
parsing. (see c2.com[http://c2.com/cgi/wiki?WikiWikiWeb] and
|
5
|
+
Wikipedia[http://en.wikipedia.org/wiki/Wiki]) It doesn't implement one specific
|
6
|
+
mark-up, but instead, provides a way to specify a variety of mark-ups. So,
|
7
|
+
Tartan is a bit more "involved" than a purpose built parser like
|
8
|
+
RedCloth[http://whytheluckystiff.net/ruby/redcloth/] or
|
9
|
+
BlueCloth[http://www.deveiate.org/projects/BlueCloth], but provides the
|
10
|
+
following benefits:
|
11
|
+
|
12
|
+
1. separates the specific wiki syntax specification from the
|
13
|
+
implementation
|
14
|
+
2. allows layering and extension of parsing rules
|
15
|
+
3. allows multiple output formats from the same syntax specification
|
16
|
+
|
17
|
+
The current implementation of Tartan is in Ruby and includes a full Markdown
|
18
|
+
parser (described in YAML). The format of the parsing specification has been
|
19
|
+
created with an eye to having a language independent definition of wiki (and
|
20
|
+
possibly other) mark-ups. That's a lofty goal, and Tartan hasn't quite gotten
|
21
|
+
there yet, but we think there's a clear path. In any case, even if it is only
|
22
|
+
available in Ruby it will hopefully be helpful for projects needing to do
|
23
|
+
something more than just convert wiki text directly into HTML.
|
24
|
+
|
25
|
+
== Usage
|
26
|
+
|
27
|
+
So, really all you want to do is generate HTML from Markdown text. Here's
|
28
|
+
how you do it:
|
29
|
+
|
30
|
+
require 'tartan_markdown'
|
31
|
+
|
32
|
+
html = TartanMarkdown.new("* howdy\n* doody").to_html
|
33
|
+
# => "<ul>\n<li>howdy</li>\n<li>doody</li>\n</ul>"
|
34
|
+
|
35
|
+
Other parsers would have similar names and would have the same usage. In
|
36
|
+
particular, you will need to require the parser class file and then creat a
|
37
|
+
new instance of the parser and call <tt>to_html</tt> on that instance.
|
38
|
+
|
39
|
+
You can also have other output methods, say <tt>to_xml</tt>, which would be
|
40
|
+
called in the same way on the instance of the parser object.
|
41
|
+
|
42
|
+
=== Layering Parsers
|
43
|
+
|
44
|
+
You can add parsing syntax to existing parsers. This is done by building up a set of parsers specifications that work together.
|
45
|
+
|
46
|
+
In the Tartan distribution you have a specification for Markdown and you also
|
47
|
+
have a specification for table mark-up. You can combine them by creating a new
|
48
|
+
class that layers the tables onto the Markdown definition as follows in a file
|
49
|
+
called <tt>tartan_markdown_tables.rb</tt>:
|
50
|
+
|
51
|
+
require 'tartan_markdown_def'
|
52
|
+
require 'tartan_table_def'
|
53
|
+
|
54
|
+
class TartanMarkdownTables < Tartan
|
55
|
+
include TartanMarkdownDef
|
56
|
+
include TartanTableDef
|
57
|
+
end
|
58
|
+
|
59
|
+
In another file you could use this new parser:
|
60
|
+
|
61
|
+
|
62
|
+
require 'tartan_markdown_tables'
|
63
|
+
|
64
|
+
html = TartanMarkdownTables.new("[|*happy*||**days**|]").to_html
|
65
|
+
# => "<table class=\"\">
|
66
|
+
<tr><td><em>happy</em></td><td><strong>days</strong></td></tr>
|
67
|
+
</table>"
|
68
|
+
|
69
|
+
== The Parsing Specification
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
=== Overall Structure
|
74
|
+
|
75
|
+
Each parser is made up of a parsing definition and optional helper methods. The specification is defined in YAML and the helper methods are defined in a parser definition class.
|
76
|
+
|
77
|
+
The parsing definition in YAML has the following general structure:
|
78
|
+
|
79
|
+
block:
|
80
|
+
- <parsing rule>
|
81
|
+
- <parsing rule>
|
82
|
+
|
83
|
+
<parsing context>:
|
84
|
+
- <parsing rules>
|
85
|
+
|
86
|
+
So the parsing rules are defined as a set of contexts and each context is an
|
87
|
+
list of parsing rules. The base context defaults to <tt>block</tt>; that is, the parser starts with the <tt>block</tt> context which may point the parser off to other contexts to parse blocks of the parsed text. More on this after the explanation of the parsing rules.
|
88
|
+
|
89
|
+
==== Parsing Rules
|
90
|
+
|
91
|
+
The following is a simple parsing rule to match paragraphs and mark them up in HTML:
|
92
|
+
|
93
|
+
title: paragraph
|
94
|
+
match: "/(^[^\n]+$\n)+^[^\n]+$/m"
|
95
|
+
html:
|
96
|
+
start_mark: <p>
|
97
|
+
end_mark: </p>
|
98
|
+
|
99
|
+
A paragraph, in this case, is any grouping of non blank lines.
|
100
|
+
|
101
|
+
The parser will repetitively apply the <tt>match</tt> regular expression and if it matches, the <tt>html</tt> output sub-rule will put <tt><p></tt> and <tt></p></tt> around the text that is matched as a paragraph.
|
102
|
+
|
103
|
+
If we wanted to also mark off blocks of code that are indented by say 2 or more spaces at the beginning of the line, we could use the following rule:
|
104
|
+
|
105
|
+
title: code
|
106
|
+
match: "/(^[ ]{2,}\S.+?$\n)+^[ ]{2,}\S.+?$/m"
|
107
|
+
html:
|
108
|
+
start_mark: <pre><code>
|
109
|
+
end_mark: </code></pre>
|
110
|
+
|
111
|
+
When we want to add the <tt>code</tt> rule, the ordering becomes important. If we put the <tt>paragraph</tt> rule first, it will gobble up both the paragraphs and the code blocks since it's just looking for groups of non blank lines. To prevent this we need to put the <tt>code</tt> rule first. So the overall definition would be:
|
112
|
+
|
113
|
+
block:
|
114
|
+
- title: code
|
115
|
+
match: "/(^[ ]{2,}\S.+?$\n)+^[ ]{2,}\S.+?$/m"
|
116
|
+
html:
|
117
|
+
start_mark: <pre><code>
|
118
|
+
end_mark: </code></pre>
|
119
|
+
- title: paragraph
|
120
|
+
match: "/(^[^\n]+$\n)+^[^\n]+$/m"
|
121
|
+
html:
|
122
|
+
start_mark: <p>
|
123
|
+
end_mark: </p>
|
124
|
+
|
125
|
+
|
126
|
+
== The Name
|
127
|
+
|
128
|
+
Tartan is intended to weave together different parsing elements. It's intended
|
129
|
+
to be an alternative of both RedCloth[http:www.redcloth.org/] and BlueCloth. Tartan is a kind of cloth
|
130
|
+
that weaves different colors together in an interesting pattern.
|
data/TODO
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
To Do
|
2
|
+
* regular expression repetition reduction
|
3
|
+
* Markdown: > in code blocks not escaped (and perhaps other cases as well)
|
4
|
+
* > in code blocks not escaped (and perhaps other cases as well)
|
5
|
+
* extended links addon for naked URLs, eg: http://www.google.com
|
6
|
+
* update all the files to generate ID tags
|
7
|
+
* HTML comparator (ignore whitespace, optionally ignore class)
|
8
|
+
* change start_mark and end_mark to start_tag and end_tag
|
9
|
+
* strike through
|
10
|
+
* superscript, subscript
|
11
|
+
|
12
|
+
To consider
|
13
|
+
* class name on span
|
14
|
+
* math mark-up
|
15
|
+
|
16
|
+
Done
|
17
|
+
* get Markdown image links to work
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Extend the File class to add a function to check for a file in the
|
2
|
+
# load path.
|
3
|
+
|
4
|
+
class File
|
5
|
+
# find a file in the load path or raise an exception if the file can
|
6
|
+
# not be found.
|
7
|
+
def File.find_file_in_path(filename)
|
8
|
+
$:.each do |path|
|
9
|
+
file_with_path = path+'/'+filename
|
10
|
+
return file_with_path if file?(file_with_path)
|
11
|
+
end
|
12
|
+
|
13
|
+
raise ArgumentError, "Can't find file #{filename} in Ruby library path"
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Hash
|
2
|
+
def deep_merge(hash)
|
3
|
+
target = dup
|
4
|
+
|
5
|
+
hash.keys.each do |key|
|
6
|
+
if hash[key].is_a?(Hash) and self[key].is_a?(Hash)
|
7
|
+
target[key] = target[key].deep_merge(hash[key])
|
8
|
+
next
|
9
|
+
end
|
10
|
+
|
11
|
+
target[key] = hash[key]
|
12
|
+
end
|
13
|
+
|
14
|
+
target
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'pp'
|
2
|
+
|
3
|
+
class MatchData
|
4
|
+
def sym2index(sym)
|
5
|
+
case sym
|
6
|
+
when '+', :last_match, :last, "last_match", "last"
|
7
|
+
last_match_index
|
8
|
+
when '&', :all, "all"
|
9
|
+
0
|
10
|
+
when /[0-9]+/
|
11
|
+
sym.to_i
|
12
|
+
when Integer
|
13
|
+
sym
|
14
|
+
else
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def replace(replace_string)
|
20
|
+
replace_string.gsub(/\\([0-9+&'`\\])/) {|sub|
|
21
|
+
case $1
|
22
|
+
when '\\'
|
23
|
+
'\\'
|
24
|
+
when '`'
|
25
|
+
pre_match
|
26
|
+
when "'"
|
27
|
+
post_match
|
28
|
+
else
|
29
|
+
to_a[sym2index($1)]
|
30
|
+
end
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def last_match_index
|
35
|
+
index = length - 1
|
36
|
+
to_a.reverse.each do |sub_match|
|
37
|
+
return index if ! sub_match.nil?
|
38
|
+
index -= 1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def pre_sub_match(index)
|
43
|
+
if index.abs >= length
|
44
|
+
raise ArgumentError, "absolute value of index greater than length"
|
45
|
+
end
|
46
|
+
|
47
|
+
index = length + index if index < 0
|
48
|
+
|
49
|
+
string[offset(0)[0]...offset(index)[0]]
|
50
|
+
end
|
51
|
+
|
52
|
+
def post_sub_match(index)
|
53
|
+
if index.abs >= length
|
54
|
+
raise ArgumentError, "absolute value of index greater than length"
|
55
|
+
end
|
56
|
+
|
57
|
+
index = length + index if index < 0
|
58
|
+
|
59
|
+
string[offset(index)[1]...offset(0)[1]]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Module
|
2
|
+
def method_missing(method_name, *args, &block)
|
3
|
+
@arg_sets ||= {}
|
4
|
+
@arg_sets[method_name] = [args, block]
|
5
|
+
end
|
6
|
+
|
7
|
+
def included(klass)
|
8
|
+
return unless defined? @arg_sets
|
9
|
+
@arg_sets.each do |method, (args, block)|
|
10
|
+
if klass.methods.include?(method.id2name)
|
11
|
+
klass.send(method, *args, &block)
|
12
|
+
else
|
13
|
+
raise "method #{method} not defined in #{klass}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Regexp
|
2
|
+
def to_regexp
|
3
|
+
self
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class String
|
8
|
+
def chars
|
9
|
+
arr = []
|
10
|
+
scan(/./m) {|char| arr << char}
|
11
|
+
arr
|
12
|
+
end
|
13
|
+
def to_regexp
|
14
|
+
if self =~ /\A\s*\/((?:\\\/|[^\/])*)\/([imxnNeEsSuU]*)\s*\z/m
|
15
|
+
options = 0
|
16
|
+
lang = ''
|
17
|
+
$2.chars.each do |char|
|
18
|
+
case char
|
19
|
+
when 'i': options |= Regexp::IGNORECASE
|
20
|
+
when 'm': options |= Regexp::MULTILINE
|
21
|
+
when 'x': options |= Regexp::EXTENDED
|
22
|
+
when 'n', 'N': lang = 'n'
|
23
|
+
when 'e', 'E': lang = 'e'
|
24
|
+
when 's', 'S': lang = 's'
|
25
|
+
when 'u', 'U': lang = 'u'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
Regexp.compile($1, options, lang)
|
29
|
+
else
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/markdown.yml
ADDED
@@ -0,0 +1,499 @@
|
|
1
|
+
#$Id: markdown.rb 227 2006-06-12 16:30:08Z larry $
|
2
|
+
|
3
|
+
# To resolve:
|
4
|
+
# How to handle (if at all) raw <h1>..<h6> tags.
|
5
|
+
# span parsing of headers
|
6
|
+
# handle return (\r) characters properly (especially in \r\n combo)
|
7
|
+
|
8
|
+
span:
|
9
|
+
- title: backtick_2
|
10
|
+
shelve: true
|
11
|
+
match: /`` ?(.+?) ?``/
|
12
|
+
subparse:
|
13
|
+
context: back_smarties
|
14
|
+
match_group: 1
|
15
|
+
html:
|
16
|
+
start_mark: '<code>'
|
17
|
+
end_mark: '</code>'
|
18
|
+
|
19
|
+
- title: backtick_1
|
20
|
+
shelve: true
|
21
|
+
match: /`(.+?)`/
|
22
|
+
subparse:
|
23
|
+
context: back_smarties
|
24
|
+
match_group: 1
|
25
|
+
html:
|
26
|
+
start_mark: '<code>'
|
27
|
+
end_mark: '</code>'
|
28
|
+
|
29
|
+
- title: ref_image
|
30
|
+
shelve: true
|
31
|
+
match: /!\[(.*?)\][ ]?\[(.*?)\]/
|
32
|
+
html:
|
33
|
+
replace: '<img src="{{{\2url}}}" alt="\1"{{{\2title}}} />'
|
34
|
+
|
35
|
+
- title: ref_link_no_id
|
36
|
+
shelve: true
|
37
|
+
match: /\[(.*?)\][ ]?\[\]/
|
38
|
+
html:
|
39
|
+
replace: '<a href="{{{\1url}}}"{{{\1title}}}>\1</a>'
|
40
|
+
|
41
|
+
- title: ref_link
|
42
|
+
shelve: true
|
43
|
+
match: /\[(.*?)\][ ]?\[(.*?)\]/
|
44
|
+
html:
|
45
|
+
replace: '<a href="{{{\2url}}}"{{{\2title}}}>\1</a>'
|
46
|
+
|
47
|
+
- title: html_span
|
48
|
+
shelve: true
|
49
|
+
match: >
|
50
|
+
/ <\/?
|
51
|
+
(?:span|cite|del|em|strong|dfn|code|samp|kbd|var|abbr
|
52
|
+
|acronym|b|i|font|a|img|object|tt|big|small|strike|s|u
|
53
|
+
|sup|sub|q)
|
54
|
+
. *?>/x
|
55
|
+
html:
|
56
|
+
start_mark: ''
|
57
|
+
end_mark: ''
|
58
|
+
|
59
|
+
- title: entity_escaped
|
60
|
+
shelve: true
|
61
|
+
match: '/&[[:alnum:]-]+;/'
|
62
|
+
html:
|
63
|
+
start_mark: ''
|
64
|
+
end_mark: ''
|
65
|
+
|
66
|
+
- title: amp
|
67
|
+
match: /&/
|
68
|
+
html:
|
69
|
+
replace: '&'
|
70
|
+
|
71
|
+
- title: backslash_gt
|
72
|
+
match: /\\>/
|
73
|
+
html:
|
74
|
+
replace: '>'
|
75
|
+
|
76
|
+
- title: lt
|
77
|
+
match: /</
|
78
|
+
html:
|
79
|
+
replace: '<'
|
80
|
+
|
81
|
+
- title: gt
|
82
|
+
match: '/(?:(?!^))>/'
|
83
|
+
html:
|
84
|
+
replace: '>'
|
85
|
+
|
86
|
+
- title: backslash_escapes
|
87
|
+
shelve: true
|
88
|
+
match: /\\([\\\`\*\_\{\}\[\]\(\)\>\#\.\!\+\-])/
|
89
|
+
html:
|
90
|
+
replace: '\1'
|
91
|
+
|
92
|
+
- title: linebreak
|
93
|
+
match: /[ \t]{2,}$/
|
94
|
+
html:
|
95
|
+
replace: "<br />"
|
96
|
+
|
97
|
+
- rescan
|
98
|
+
|
99
|
+
- title: inline_image_with_title
|
100
|
+
shelve: true
|
101
|
+
match: /!\[(.+?)\]\((.+??)\s+"(.+?)"\)/
|
102
|
+
html:
|
103
|
+
replace: '<img src="\2" alt="\1" title="\3" />'
|
104
|
+
|
105
|
+
- rescan
|
106
|
+
|
107
|
+
- title: inline_image
|
108
|
+
shelve: true
|
109
|
+
match: /!\[(.+?)\]\((.*?)\)/
|
110
|
+
html:
|
111
|
+
replace: '<img src="\2" alt="\1" />'
|
112
|
+
|
113
|
+
- rescan
|
114
|
+
|
115
|
+
- title: link_with_title
|
116
|
+
shelve: true
|
117
|
+
match: /\[(.+?)\]\((.+??)\s+"(.+?)"\)/
|
118
|
+
html:
|
119
|
+
replace: '<a href="\2" title="\3">\1</a>'
|
120
|
+
- rescan
|
121
|
+
|
122
|
+
- title: link
|
123
|
+
shelve: true
|
124
|
+
match: /\[(.+?)\]\((.*?)\)/
|
125
|
+
html:
|
126
|
+
replace: '<a href="\2">\1</a>'
|
127
|
+
|
128
|
+
- rescan
|
129
|
+
|
130
|
+
- title: pre_emphasis
|
131
|
+
|
132
|
+
- title: strong_em
|
133
|
+
match: '/(?:\*{3}(.+?)\*{3})|(?:_{3}(.+?)_{3})/'
|
134
|
+
subparse:
|
135
|
+
context: span
|
136
|
+
match_group: last
|
137
|
+
html:
|
138
|
+
start_mark: '<strong><em>'
|
139
|
+
end_mark: '</em></strong>'
|
140
|
+
- rescan
|
141
|
+
|
142
|
+
- title: strong
|
143
|
+
match: '/(?:\*{2}(.+?)\*{2})|(?:_{2}(.+?)_{2})/'
|
144
|
+
subparse:
|
145
|
+
context: span
|
146
|
+
match_group: last
|
147
|
+
html:
|
148
|
+
start_mark: '<strong>'
|
149
|
+
end_mark: '</strong>'
|
150
|
+
- rescan
|
151
|
+
|
152
|
+
- title: em
|
153
|
+
match: '/(?:\*(.+?)\*)|(?:\_(.+?)\_)/'
|
154
|
+
subparse:
|
155
|
+
context: span
|
156
|
+
match_group: last
|
157
|
+
html:
|
158
|
+
start_mark: '<em>'
|
159
|
+
end_mark: '</em>'
|
160
|
+
|
161
|
+
- title: post_emphasis
|
162
|
+
|
163
|
+
back_smarties:
|
164
|
+
- title: backslash_gt
|
165
|
+
match: /\\>/
|
166
|
+
html:
|
167
|
+
replace: '\\>'
|
168
|
+
|
169
|
+
- title: backslash_lt
|
170
|
+
match: /\\</
|
171
|
+
html:
|
172
|
+
replace: '\\<'
|
173
|
+
|
174
|
+
- title: amp
|
175
|
+
match: /&/
|
176
|
+
html:
|
177
|
+
replace: '&'
|
178
|
+
|
179
|
+
- title: backslash_gt
|
180
|
+
match: /\\>/
|
181
|
+
html:
|
182
|
+
replace: '>'
|
183
|
+
|
184
|
+
- title: lt
|
185
|
+
match: /</
|
186
|
+
html:
|
187
|
+
replace: '<'
|
188
|
+
|
189
|
+
- title: gt
|
190
|
+
match: '/(?:(?!^))>/'
|
191
|
+
html:
|
192
|
+
replace: '>'
|
193
|
+
|
194
|
+
block:
|
195
|
+
- title: strip_return
|
196
|
+
match: /\r/
|
197
|
+
html:
|
198
|
+
replace: ''
|
199
|
+
|
200
|
+
- rescan
|
201
|
+
|
202
|
+
- title: main_block
|
203
|
+
|
204
|
+
- title: reference_title
|
205
|
+
match: >
|
206
|
+
/\n(?:[ ]{0,3})
|
207
|
+
\[([^\]]*)\]:\s+(?:<([^>]*)>|(\S*))\s+
|
208
|
+
(?:"([^"]*?)"|'([^']*?)')[ \t]*/mx
|
209
|
+
set:
|
210
|
+
'\1url': '\2\3'
|
211
|
+
'\1title': ' title="\4\5"'
|
212
|
+
html:
|
213
|
+
replace: ''
|
214
|
+
|
215
|
+
- title: reference
|
216
|
+
match: '/\n(?: {0,3})\[([^:\n]*)\]:\s+(?:<([^>]*)>|(\S*))$/m'
|
217
|
+
set:
|
218
|
+
'\1url': '\2\3'
|
219
|
+
'\1title': ''
|
220
|
+
html:
|
221
|
+
replace: ''
|
222
|
+
|
223
|
+
- title: html_comment
|
224
|
+
shelve: true
|
225
|
+
match: /(<!--.*?-->)/m
|
226
|
+
html:
|
227
|
+
replace: '\1'
|
228
|
+
|
229
|
+
- title: underline_header1
|
230
|
+
match: '/^([^\n\t #=-][^\n]*?)[ \t]*\n=+[ \t]*$/m'
|
231
|
+
subparse:
|
232
|
+
context: span
|
233
|
+
match_group: 1
|
234
|
+
html:
|
235
|
+
start_mark: '<h1>'
|
236
|
+
end_mark: '</h1>'
|
237
|
+
|
238
|
+
- title: underline_header2
|
239
|
+
match: '/^([^\n\s#=-][^\n]*?)[ \t]*\n-+[ \t]*$/m'
|
240
|
+
subparse:
|
241
|
+
context: span
|
242
|
+
match_group: 1
|
243
|
+
html:
|
244
|
+
start_mark: '<h2>'
|
245
|
+
end_mark: '</h2>'
|
246
|
+
|
247
|
+
- title: hash_header
|
248
|
+
match: '/^(\# {1,6})\s*([^#]*?)(?:\s*\#+\s*|\s*)$/x'
|
249
|
+
subparse:
|
250
|
+
context: span
|
251
|
+
match_group: 2
|
252
|
+
html:
|
253
|
+
start_mark: '<h#{len(\1)}>'
|
254
|
+
end_mark: '</h#{len(\1)}>'
|
255
|
+
|
256
|
+
- title: blockquote
|
257
|
+
match: '/^((?:>.*?$)(?:\n[^\n]+)*)/m'
|
258
|
+
subparse: embeddedBlock
|
259
|
+
strip:
|
260
|
+
match: /^(> |>$)/
|
261
|
+
replace: ''
|
262
|
+
unstrip:
|
263
|
+
match: /^|(\n)\z/
|
264
|
+
replace: '\1> '
|
265
|
+
html:
|
266
|
+
start_mark: "<blockquote>\n"
|
267
|
+
end_mark: "\n</blockquote>"
|
268
|
+
# Needs to go before the bullet lists to ensure that
|
269
|
+
# spaced - and * HRs aren't interpreted as bullet lists
|
270
|
+
|
271
|
+
- title: horizontal_rule
|
272
|
+
match: >
|
273
|
+
/ (?:(\n)\s*(\n)|\A|\A\s*(\n))
|
274
|
+
[ ]{0,3}([-_*][ ]?){3,}[ \t]*?$/xm
|
275
|
+
html:
|
276
|
+
replace: '\1\2\3<hr />'
|
277
|
+
|
278
|
+
- title: bulletListSpaced
|
279
|
+
match: >
|
280
|
+
/ (?>\A(\s*)|\n(\n))
|
281
|
+
(
|
282
|
+
[-*+](?>[ ]+|\t)[^\n]*
|
283
|
+
(?>\n(?>[ ]{4}|\t)?[^\n]+)*
|
284
|
+
(?>
|
285
|
+
\n\n(?>[ ]{4}|\t)[^-*+\n][^\n]*
|
286
|
+
(?>\n(?>[ ]{4}|\t)?[^\n]+)*
|
287
|
+
)*
|
288
|
+
(?>
|
289
|
+
\n\n[-*+](?:[ ]+|\t)[^\n]*
|
290
|
+
(?>\n
|
291
|
+
(?>[ ]{4}|\t)?
|
292
|
+
[^\n]+
|
293
|
+
)*
|
294
|
+
(?>
|
295
|
+
\n\n(?>[ ]{4}|\t)[^-*+\n][^\n]*
|
296
|
+
(?>\n(?>[ ]{4}|\t)?[^\n]+)*
|
297
|
+
)*
|
298
|
+
)+
|
299
|
+
)/xm
|
300
|
+
subparse:
|
301
|
+
context: listSpaced
|
302
|
+
match_group: 3
|
303
|
+
html:
|
304
|
+
start_mark: "<ul>\n"
|
305
|
+
end_mark: "\n</ul>"
|
306
|
+
|
307
|
+
- title: bulletListClose
|
308
|
+
match: >
|
309
|
+
/ (?:\A(\s*)|\n(\n))
|
310
|
+
([-*+](?:[ ]+|\t)[^\n]+(:?\n[ \t]*[^\s][^\n]*)*)/xm
|
311
|
+
subparse:
|
312
|
+
context: listClose
|
313
|
+
match_group: 3
|
314
|
+
html:
|
315
|
+
start_mark: "\\1\\2<ul>\n"
|
316
|
+
end_mark: "\n</ul>"
|
317
|
+
|
318
|
+
- title: numberedListSpaced
|
319
|
+
match: >
|
320
|
+
/ (?>\A(\s*)|\n(\n))
|
321
|
+
(
|
322
|
+
(?>^[[:digit:]]+\.
|
323
|
+
(?>[ ]+|\t)[^\n]*)
|
324
|
+
(?>\n(?:[ ]{4}|\t)?
|
325
|
+
[^\n]+
|
326
|
+
)*
|
327
|
+
(?>
|
328
|
+
(?>\n\n(?:[ ]{4}|\t)[^[:digit:]\n][^\n]*)
|
329
|
+
(?>\n(?:[ ]{4}|\t)?[^\n]+)*
|
330
|
+
)*
|
331
|
+
(?>\n\n
|
332
|
+
(?>^[[:digit:]]+\.
|
333
|
+
(?>[ ]+|\t)[^\n]*)
|
334
|
+
(?>\n(?:[ ]{4}|\t)?
|
335
|
+
[^\n]+
|
336
|
+
)*
|
337
|
+
(?>
|
338
|
+
(?>\n\n(?:[ ]{4}|\t)[^[:digit:]\n][^\n]*)
|
339
|
+
(?>\n(?:[ ]{4}|\t)?[^\n]+)*
|
340
|
+
)*
|
341
|
+
)+
|
342
|
+
)/xm
|
343
|
+
subparse:
|
344
|
+
context: listSpaced
|
345
|
+
match_group: 3
|
346
|
+
html:
|
347
|
+
start_mark: "\\1\\2<ol>\n"
|
348
|
+
end_mark: "\n</ol>"
|
349
|
+
|
350
|
+
- title: numberedListClose
|
351
|
+
match: >
|
352
|
+
/ (?:\A(\s*)|\n(\n))
|
353
|
+
((?:^[[:digit:]]+\.(?:[ ]+|\t)[^\n]*)
|
354
|
+
(?:\n(?:[[:digit:]]+\.(?:[ ]+|\t)
|
355
|
+
|(?:[ ]{4}|\t)?
|
356
|
+
)[^\n]+
|
357
|
+
)*
|
358
|
+
)/xm
|
359
|
+
subparse:
|
360
|
+
context: listClose
|
361
|
+
match_group: 3
|
362
|
+
html:
|
363
|
+
start_mark: "\\1\\2<ol>\n"
|
364
|
+
end_mark: "\n</ol>"
|
365
|
+
|
366
|
+
- title: html_block
|
367
|
+
shelve: true
|
368
|
+
match: >
|
369
|
+
/ ^[ ]{0,3}<(script|table|div|pre|center|blockquote|p|ul|ol|h[1-6])(?:[^>]*)?>
|
370
|
+
.*?
|
371
|
+
<\/\1>/xm
|
372
|
+
html: true
|
373
|
+
|
374
|
+
- title: code
|
375
|
+
match: >
|
376
|
+
/ (?:\A|(\n)(?:[ ]{4}|\t)?(\n))((?:\t|[ ]{4})[^\n]*
|
377
|
+
(?:\n+(?:\t|[ ]{4})[^\n]*)*)/xm
|
378
|
+
subparse:
|
379
|
+
context: codeBlock
|
380
|
+
match_group: 3
|
381
|
+
strip:
|
382
|
+
match: '/^(?:\t|[ ]{4})/'
|
383
|
+
replace: ''
|
384
|
+
unstrip:
|
385
|
+
match: /\n/
|
386
|
+
replace: "\n "
|
387
|
+
html:
|
388
|
+
start_mark: '\1\2<pre><code>'
|
389
|
+
end_mark: "\n</code></pre>"
|
390
|
+
|
391
|
+
- title: paragraph
|
392
|
+
match: '/((?:^\S.*?$)(?:\n\S[^\n]*)*)/m'
|
393
|
+
subparse: span
|
394
|
+
html:
|
395
|
+
start_mark: '<p>'
|
396
|
+
end_mark: '</p>'
|
397
|
+
|
398
|
+
- title: extraReturns
|
399
|
+
match: '/^(?:\s*\n){3,}/'
|
400
|
+
html:
|
401
|
+
replace: "\n\n"
|
402
|
+
|
403
|
+
codeBlock:
|
404
|
+
- title: codeContents
|
405
|
+
match: /(\A.+\z)/m
|
406
|
+
rescan: true
|
407
|
+
html:
|
408
|
+
replace: '#{untabify(\1)}'
|
409
|
+
|
410
|
+
- title: check_smarties
|
411
|
+
match: /(\A.+\z)/m
|
412
|
+
subparse: back_smarties
|
413
|
+
|
414
|
+
embeddedBlock:
|
415
|
+
- title: emBulletListClose
|
416
|
+
match: >
|
417
|
+
/ ((?:^[-*+](?:[ ]+|\t).*?$)
|
418
|
+
(?:\n(?:[-*+]|(?:[ ]{4}|\t)?)[^\n]*)*
|
419
|
+
)/xm
|
420
|
+
subparse: listClose
|
421
|
+
html:
|
422
|
+
start_mark: "<ul>\n"
|
423
|
+
end_mark: "\n</ul>"
|
424
|
+
|
425
|
+
- title: emNumberedListClose
|
426
|
+
match: >-
|
427
|
+
/ ( (?:^[[:digit:]]+\.(?:[ ]+|\t).*?$)
|
428
|
+
(?:\n(?:[[:digit:]]+\.|(?:[ ]{4}|\t)?)
|
429
|
+
[^\n]*)*
|
430
|
+
)/xm
|
431
|
+
subparse: listClose
|
432
|
+
html:
|
433
|
+
start_mark: "<ol>\n"
|
434
|
+
end_mark: "\n</ol>"
|
435
|
+
|
436
|
+
- title: embeddedPara
|
437
|
+
position: first
|
438
|
+
match:
|
439
|
+
/\A (?:(?![*+-]|[[:digit:]]))
|
440
|
+
(?:(?:\S[^\n]*)(?:\n\S[^\n]*)*)
|
441
|
+
\n?\z/xm
|
442
|
+
subparse: span
|
443
|
+
html:
|
444
|
+
end_mark: '\1'
|
445
|
+
|
446
|
+
- title: embeddedRemainder
|
447
|
+
match: /.+/m
|
448
|
+
subparse: block
|
449
|
+
html: true
|
450
|
+
|
451
|
+
listSpaced:
|
452
|
+
- title: spacedListItem
|
453
|
+
match: >-
|
454
|
+
/^(?:^(?:[-*+]|[[:digit:]]+\.)
|
455
|
+
(?:[ ]+|\t).*?$
|
456
|
+
)
|
457
|
+
(?:\n[^-*+[:digit:]\n][^\n]*)*
|
458
|
+
(?:
|
459
|
+
(?:\n\n(?:[ ]{4}|\t)[^-*+[:digit:]\n][^\n]*)
|
460
|
+
(?:\n[^-*+[:digit:]\n][^\n]*)*
|
461
|
+
)*/xm
|
462
|
+
strip:
|
463
|
+
match: '/^(([-*+]|[[:digit:]]\.)\s*|(?: |\t))/'
|
464
|
+
replace: ''
|
465
|
+
subparse: block
|
466
|
+
html:
|
467
|
+
start_mark: '<li>'
|
468
|
+
end_mark: "</li>"
|
469
|
+
|
470
|
+
- title: listSpacedDoubleReturn
|
471
|
+
match: /\n\n/
|
472
|
+
html:
|
473
|
+
replace: "\n"
|
474
|
+
|
475
|
+
listClose:
|
476
|
+
- title: closeListItem
|
477
|
+
match: >
|
478
|
+
/^(
|
479
|
+
(?:
|
480
|
+
(?:[-*+]|[[:digit:]+]\.)
|
481
|
+
(?:[ ]+|\t).*?$
|
482
|
+
)
|
483
|
+
(?:\n(?![-*+\n]|[[:digit:]]+\.)[^\n]*)*
|
484
|
+
)/xm
|
485
|
+
strip:
|
486
|
+
match: >
|
487
|
+
/^( (?:[-*+]|[[:digit:]]+\.)\s*
|
488
|
+
|(?:[ ]+|\t)
|
489
|
+
)/x
|
490
|
+
replace: ''
|
491
|
+
subparse: embeddedBlock
|
492
|
+
html:
|
493
|
+
start_mark: '<li>'
|
494
|
+
end_mark: '</li>'
|
495
|
+
|
496
|
+
- title: listCloseDoubleReturn
|
497
|
+
match: /\n\n/
|
498
|
+
html:
|
499
|
+
replace: "\n"
|