pink_shirt 0.0.1
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/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/Readme.txt +26 -0
- data/lib/pink_shirt/attributes.rb +169 -0
- data/lib/pink_shirt/entities.rb +32 -0
- data/lib/pink_shirt/flags.rb +5 -0
- data/lib/pink_shirt/output.rb +64 -0
- data/lib/pink_shirt/sax/acronym.rb +15 -0
- data/lib/pink_shirt/sax/base.rb +20 -0
- data/lib/pink_shirt/sax/basic.rb +114 -0
- data/lib/pink_shirt/sax/block_level.rb +69 -0
- data/lib/pink_shirt/sax/boiler_plate.rb +11 -0
- data/lib/pink_shirt/sax/images.rb +17 -0
- data/lib/pink_shirt/sax/links.rb +19 -0
- data/lib/pink_shirt/sax/lists.rb +67 -0
- data/lib/pink_shirt/sax/preformatted.rb +13 -0
- data/lib/pink_shirt/sax/script.rb +12 -0
- data/lib/pink_shirt/sax/tables.rb +38 -0
- data/lib/pink_shirt/sax.rb +75 -0
- data/lib/pink_shirt/version.rb +3 -0
- data/lib/pink_shirt.rb +49 -0
- data/pink_shirt.gemspec +25 -0
- data/spec/basics_spec.rb +16 -0
- data/spec/examples/basics.yaml +172 -0
- data/spec/reverse_redcloth_spec.rb +17 -0
- data/spec/reverse_textile_spec.rb +65 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/textile-spec/CHANGELOG +6 -0
- data/spec/textile-spec/README.textile +55 -0
- data/spec/textile-spec/attributes.yaml +58 -0
- data/spec/textile-spec/html.yaml +156 -0
- data/spec/textile-spec/index.yaml +12 -0
- data/spec/textile-spec/page_layout.yaml +276 -0
- data/spec/textile-spec/paragraph_text.yaml +131 -0
- data/spec/textile-spec/phrase_modifiers.yaml +125 -0
- data/spec/textile_spec.rb +113 -0
- metadata +130 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
data/Readme.txt
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
I had a problem: some html needed to be textile
|
|
2
|
+
|
|
3
|
+
None of the available options could get back to exactly where you started.
|
|
4
|
+
They weren't 'reversable'
|
|
5
|
+
|
|
6
|
+
I learned a lot by reading other's who went before.
|
|
7
|
+
I've looked at: html2texile https://github.com/thickpaddy/html2textile
|
|
8
|
+
I've looked at: clothred https://github.com/CynicalRyan/ClothRed
|
|
9
|
+
I've looked at: a deeply buried module in humpyard https://github.com/humpyard/humpyard
|
|
10
|
+
|
|
11
|
+
This library still has some problems with whitespace management, but all the tags convert.
|
|
12
|
+
|
|
13
|
+
It's based around https://github.com/textile/textile-spec
|
|
14
|
+
and built to produce mirror images of html produced by
|
|
15
|
+
RedCloth https://github.com/jgarber/redcloth
|
|
16
|
+
|
|
17
|
+
Usage
|
|
18
|
+
============================
|
|
19
|
+
text = "This is *my* text."
|
|
20
|
+
html = RedCloth.new(text).to_html
|
|
21
|
+
same = PinkShirt.new(html).to_textile
|
|
22
|
+
same #=> "This is *my* text."
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
class PinkShirt
|
|
2
|
+
# Attributes
|
|
3
|
+
# -------------------------
|
|
4
|
+
# the sax parser passes an array of attributes along with each tag
|
|
5
|
+
# attrs = ['href', 'http://www.example.com', 'style', 'background-color: snake;']
|
|
6
|
+
#
|
|
7
|
+
# Textile displays attributes in a certain way
|
|
8
|
+
#
|
|
9
|
+
# USAGE
|
|
10
|
+
# ---------------------------
|
|
11
|
+
# Attributes.new(attrs).write
|
|
12
|
+
#
|
|
13
|
+
#
|
|
14
|
+
# colspan=2 => \2
|
|
15
|
+
# rowspan=3 => /3
|
|
16
|
+
# style='padding-left:1em' => (
|
|
17
|
+
# style='padding-right:2em' => ))
|
|
18
|
+
# style='text-align:right' => >
|
|
19
|
+
# style='text-align:left' => <
|
|
20
|
+
# style='text-align:center' => =
|
|
21
|
+
# style='text-align:justify'=> <>
|
|
22
|
+
# class = 'panthers' => (panthers)
|
|
23
|
+
# id = 'banner' => (#banner)
|
|
24
|
+
# class='this' id='that' => (this#that)
|
|
25
|
+
# lang='fr' => [fr]
|
|
26
|
+
# style='color:red' => {color:red}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Attributes
|
|
30
|
+
|
|
31
|
+
def initialize(attrs)
|
|
32
|
+
@attrs = attrs
|
|
33
|
+
@attrs_hash = Hash[attrs]
|
|
34
|
+
@styles_hash = parse_styles
|
|
35
|
+
@nudges = steal_nudges
|
|
36
|
+
@padding = steal_padding
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def attrs
|
|
40
|
+
@attrs_hash
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def styles
|
|
44
|
+
@styles_hash ||= {}
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def write
|
|
49
|
+
add = []
|
|
50
|
+
add << colspan
|
|
51
|
+
add << rowspan
|
|
52
|
+
add << nudges
|
|
53
|
+
add << padding
|
|
54
|
+
add << klass_and_id
|
|
55
|
+
add << style
|
|
56
|
+
add << lang
|
|
57
|
+
out = add.join
|
|
58
|
+
return nil if out == ""
|
|
59
|
+
out
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def parse_styles
|
|
63
|
+
return nil unless attrs['style']
|
|
64
|
+
rules_list = attrs['style'].split(";").map{|rule|
|
|
65
|
+
rule.split(":")
|
|
66
|
+
}
|
|
67
|
+
Hash[rules_list]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def styles_to_s
|
|
71
|
+
@styles_hash.map{|k, v| "#{k}:#{v}"}.join(";")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def steal_nudges
|
|
75
|
+
|
|
76
|
+
return nil unless attrs['style']
|
|
77
|
+
nudges = []
|
|
78
|
+
style = attrs['style']
|
|
79
|
+
|
|
80
|
+
text_align = case styles.delete('text-align')
|
|
81
|
+
when 'left'
|
|
82
|
+
"<"
|
|
83
|
+
when 'right'
|
|
84
|
+
">"
|
|
85
|
+
when 'center'
|
|
86
|
+
"="
|
|
87
|
+
when 'justify'
|
|
88
|
+
"<>"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
nudges << text_align
|
|
92
|
+
|
|
93
|
+
nudges
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def steal_padding
|
|
97
|
+
|
|
98
|
+
return nil unless attrs['style']
|
|
99
|
+
left = case styles.delete('padding-left')
|
|
100
|
+
when '1em'; "(" ;
|
|
101
|
+
when '2em'; "((";
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
#Alternately, but i'd rather not encourage it
|
|
105
|
+
# left_count = styles.delete('padding-left').to_i
|
|
106
|
+
# left = Array.new(left_count).map{"("}.join
|
|
107
|
+
|
|
108
|
+
right = case styles.delete('padding-right')
|
|
109
|
+
when '1em'; ")" ;
|
|
110
|
+
when '2em'; "))";
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
padding = "#{left}#{right}"
|
|
114
|
+
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def colspan
|
|
118
|
+
return nil unless attrs['colspan']
|
|
119
|
+
width = attrs['colspan']
|
|
120
|
+
colspan = ""
|
|
121
|
+
colspan << "\\" #literal backslash
|
|
122
|
+
colspan << "#{width}"
|
|
123
|
+
colspan if width
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def rowspan
|
|
127
|
+
return nil unless attrs['rowspan']
|
|
128
|
+
height = attrs['rowspan']
|
|
129
|
+
colspan = '/' + "#{height}" if height
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def nudges
|
|
133
|
+
@nudges
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def padding
|
|
137
|
+
@padding
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def klass_and_id
|
|
142
|
+
klass = attrs['class']
|
|
143
|
+
id = attrs['id']
|
|
144
|
+
return nil unless klass || id
|
|
145
|
+
output = ""
|
|
146
|
+
output += "("
|
|
147
|
+
output += klass if klass
|
|
148
|
+
output += "##{id}" if id
|
|
149
|
+
output += ")"
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def style
|
|
153
|
+
return nil unless styles.length > 0
|
|
154
|
+
|
|
155
|
+
output = ""
|
|
156
|
+
output += "{"
|
|
157
|
+
output += styles_to_s
|
|
158
|
+
output += "}"
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def lang
|
|
162
|
+
return nil unless attrs.include?('lang')
|
|
163
|
+
output = ""
|
|
164
|
+
output += "["
|
|
165
|
+
output += attrs['lang']
|
|
166
|
+
output += "]"
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
class PinkShirt
|
|
2
|
+
# Gets rid of smart quotes, dashes and some pesky unicode
|
|
3
|
+
# Usage
|
|
4
|
+
# ---------------------
|
|
5
|
+
# Entities.sanitize(input)
|
|
6
|
+
#
|
|
7
|
+
class Entities
|
|
8
|
+
REPLACEMENTS = {
|
|
9
|
+
8217 => "'", #single quote
|
|
10
|
+
8216 => "'", #left single quote
|
|
11
|
+
8220 => '"', #right double quote
|
|
12
|
+
8221 => '"', #left double quote
|
|
13
|
+
8211 => "-", #endash
|
|
14
|
+
8212 => "--", #emdash
|
|
15
|
+
8230 => "...", #ellipsis
|
|
16
|
+
215 => "x", #times
|
|
17
|
+
8242 => "'", #inch
|
|
18
|
+
174 => "(r)", #registered trademark
|
|
19
|
+
8482 => "(tm)", # trademark
|
|
20
|
+
169 => "(c)", #copyright
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def self.sanitize(string)
|
|
25
|
+
string_chars = string.unpack("U*")
|
|
26
|
+
string_chars.map! {|x| REPLACEMENTS[x] ? REPLACEMENTS[x].unpack('U*') : x}
|
|
27
|
+
string_chars.flatten
|
|
28
|
+
string = string_chars.flatten.pack('U*')
|
|
29
|
+
string
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
class PinkShirt
|
|
2
|
+
#
|
|
3
|
+
# Nokogiri::Sax builds output as a long stream.
|
|
4
|
+
# Output collects all the writes as an array, and then joins them when required
|
|
5
|
+
# you can also lock it for writing.
|
|
6
|
+
#
|
|
7
|
+
# Usage
|
|
8
|
+
# ------------------------
|
|
9
|
+
# stream = Output.new
|
|
10
|
+
# stream << 'goods... '
|
|
11
|
+
# stream.inspect #=> ['goods... ']
|
|
12
|
+
# stream.lock('suspicious tag')
|
|
13
|
+
# stream << 'bad stuff'
|
|
14
|
+
# stream.inspect #=> ['goods... ']
|
|
15
|
+
# stream.unlock
|
|
16
|
+
# stream << 'good again'
|
|
17
|
+
# stream.inspect #=> ['goods... ', 'good again']
|
|
18
|
+
#
|
|
19
|
+
class Output
|
|
20
|
+
def initialize
|
|
21
|
+
@contents = []
|
|
22
|
+
@silenced = false
|
|
23
|
+
@locks = []
|
|
24
|
+
@ouput = ""
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def lock(key)
|
|
28
|
+
@locks << key
|
|
29
|
+
@silenced = true
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def unlock
|
|
33
|
+
@locks.pop
|
|
34
|
+
@silenced = false if @locks.empty?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def << (more)
|
|
38
|
+
@contents << more unless @silenced
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def join
|
|
42
|
+
@output = @contents.join
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def sanitize
|
|
46
|
+
@output = PinkShirt::Entities.sanitize(@output)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def trim
|
|
50
|
+
@output = @output.chomp.chomp.chomp
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def to_s
|
|
54
|
+
join
|
|
55
|
+
sanitize
|
|
56
|
+
trim
|
|
57
|
+
@output
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def inspect
|
|
61
|
+
@contents
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class PinkShirt
|
|
2
|
+
class SAX::Acronym < SAX::Base
|
|
3
|
+
TAGS = %(acronym)
|
|
4
|
+
def initialize(*args)
|
|
5
|
+
@current_acronym = []
|
|
6
|
+
super
|
|
7
|
+
end
|
|
8
|
+
def start_acronym attrs
|
|
9
|
+
@current_acronym << attrs['title']
|
|
10
|
+
end
|
|
11
|
+
def end_acronym
|
|
12
|
+
@output << "(#{@current_acronym.pop})"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class PinkShirt
|
|
2
|
+
class SAX::Base
|
|
3
|
+
TAGS = []
|
|
4
|
+
def initialize(input, flags)
|
|
5
|
+
@output = input
|
|
6
|
+
@flags = flags
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def add_attributes(attrs)
|
|
10
|
+
PinkShirt::Attributes.new(attrs).write
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_s
|
|
14
|
+
@output
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def method_missing(*args)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
class PinkShirt
|
|
2
|
+
class SAX::Basic < SAX::Base
|
|
3
|
+
TAGS = %w(strong b em i cite del ins sub sup span code)
|
|
4
|
+
attr_accessor :nospan
|
|
5
|
+
def start_strong attrs
|
|
6
|
+
@output << "*"
|
|
7
|
+
@output << add_attributes(attrs) if add_attributes(attrs)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
alias :start_b :start_strong
|
|
11
|
+
|
|
12
|
+
def end_strong
|
|
13
|
+
@output << "*"
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def start_b attrs
|
|
18
|
+
@output << "**"
|
|
19
|
+
@output << add_attributes(attrs) if add_attributes(attrs)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def end_b
|
|
23
|
+
@output << "**"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def start_cite attrs
|
|
27
|
+
@output << "??"
|
|
28
|
+
@output << add_attributes(attrs) if add_attributes(attrs)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def end_cite
|
|
32
|
+
@output << "??"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def start_em attrs
|
|
36
|
+
@output << "_"
|
|
37
|
+
@output << add_attributes(attrs) if add_attributes(attrs)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def end_em
|
|
41
|
+
@output << "_"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def start_i attrs
|
|
45
|
+
@output << "__"
|
|
46
|
+
@output << add_attributes(attrs) if add_attributes(attrs)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def end_i
|
|
50
|
+
@output << "__"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def start_del attrs
|
|
54
|
+
@output << "-"
|
|
55
|
+
@output << add_attributes(attrs) if add_attributes(attrs)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def end_del
|
|
59
|
+
@output << "-"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def start_ins attrs
|
|
63
|
+
@output << "+"
|
|
64
|
+
@output << add_attributes(attrs) if add_attributes(attrs)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def end_ins
|
|
68
|
+
@output << "+"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def start_sub attrs
|
|
72
|
+
@output << "~"
|
|
73
|
+
@output << add_attributes(attrs) if add_attributes(attrs)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def end_sub
|
|
77
|
+
@output << "~"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def start_sup attrs
|
|
81
|
+
@output << "^"
|
|
82
|
+
@output << add_attributes(attrs) if add_attributes(attrs)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def end_sup
|
|
86
|
+
@output << "^"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# redcloth loves to put caps in 'span-caps', it's lame
|
|
90
|
+
def start_span attrs
|
|
91
|
+
if attrs['class'] == 'caps'
|
|
92
|
+
@nospan = true
|
|
93
|
+
else
|
|
94
|
+
@output << "%"
|
|
95
|
+
@output << add_attributes(attrs) if add_attributes(attrs)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def end_span
|
|
100
|
+
@output << "%" unless @nospan
|
|
101
|
+
@nospan = false
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def start_code attrs
|
|
105
|
+
@output << "@"
|
|
106
|
+
@output << add_attributes(attrs) if add_attributes(attrs)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def end_code
|
|
110
|
+
@output << "@"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
class PinkShirt
|
|
2
|
+
class SAX::BlockLevel < SAX::Base
|
|
3
|
+
TAGS = %w(p br h1 h2 h3 h4 h5 h6 div blockquote)
|
|
4
|
+
def start_p attrs
|
|
5
|
+
@output << "p#{add_attributes(attrs)}. " if add_attributes(attrs)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def end_p
|
|
9
|
+
@output << "\n\n"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def start_div attrs
|
|
13
|
+
@output << "div#{add_attributes(attrs)}. "
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def end_div
|
|
17
|
+
@output << "\n"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def start_blockquote attrs
|
|
21
|
+
if attrs['cite']
|
|
22
|
+
@output << "bq.:#{attrs['cite']} "
|
|
23
|
+
else
|
|
24
|
+
@output << "bq#{add_attributes(attrs)}. "
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def start_br attrs
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def end_br
|
|
32
|
+
@output << "\n"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def start_h1 attrs
|
|
36
|
+
@output << "h1#{add_attributes(attrs)}. "
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def start_h2 attrs
|
|
40
|
+
@output << "h2#{add_attributes(attrs)}. "
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def start_h3 attrs
|
|
44
|
+
@output << "h3#{add_attributes(attrs)}. "
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def start_h4 attrs
|
|
48
|
+
@output << "h4#{add_attributes(attrs)}. "
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def start_h5 attrs
|
|
52
|
+
@output << "h5#{add_attributes(attrs)}. "
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def start_h6 attrs
|
|
56
|
+
@output << "h6#{add_attributes(attrs)}. "
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def end_h
|
|
60
|
+
@output << "\n\n"
|
|
61
|
+
end
|
|
62
|
+
alias :end_h1 :end_h
|
|
63
|
+
alias :end_h2 :end_h
|
|
64
|
+
alias :end_h3 :end_h
|
|
65
|
+
alias :end_h4 :end_h
|
|
66
|
+
alias :end_h5 :end_h
|
|
67
|
+
alias :end_h6 :end_h
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class PinkShirt
|
|
2
|
+
class SAX::Images < SAX::Base
|
|
3
|
+
TAGS = %(img)
|
|
4
|
+
def start_img attrs
|
|
5
|
+
title = attrs['alt'] || attrs['title']
|
|
6
|
+
title = nil if title == "" || title == " "
|
|
7
|
+
image = "!"
|
|
8
|
+
image += attrs['src']
|
|
9
|
+
image += "(#{title})" if title
|
|
10
|
+
image += "!"
|
|
11
|
+
@output << image
|
|
12
|
+
end
|
|
13
|
+
def end_img
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class PinkShirt
|
|
2
|
+
class SAX::Links < SAX::Base
|
|
3
|
+
TAGS = %(a)
|
|
4
|
+
def start_a attrs
|
|
5
|
+
@link_info = attrs
|
|
6
|
+
link = ""
|
|
7
|
+
link += '"'
|
|
8
|
+
link += "(#{attrs['class']}). " if attrs['class']
|
|
9
|
+
@output << link
|
|
10
|
+
end
|
|
11
|
+
def end_a
|
|
12
|
+
link = ""
|
|
13
|
+
link += " (#{@link_info['title']})" if @link_info['title']
|
|
14
|
+
link += '"'
|
|
15
|
+
link += ":#{@link_info['href']}"
|
|
16
|
+
@output << link
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
class PinkShirt
|
|
2
|
+
class SAX::Lists < SAX::Base
|
|
3
|
+
TAGS = %w(ul ol li dl dt dd)
|
|
4
|
+
def initialize(*args)
|
|
5
|
+
@last_depth = 0
|
|
6
|
+
@nesting = []
|
|
7
|
+
super
|
|
8
|
+
end
|
|
9
|
+
def start_ul(attrs)
|
|
10
|
+
@nesting.push "ul"
|
|
11
|
+
@in_ul = true
|
|
12
|
+
@output << "\n" unless @nesting.length == 1
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def end_ul
|
|
16
|
+
@nesting.pop
|
|
17
|
+
@in_ul = false
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def start_ol(attrs)
|
|
21
|
+
@nesting.push('ol')
|
|
22
|
+
@in_ol = true
|
|
23
|
+
@output << "\n" unless @nesting.length == 1
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def end_ol
|
|
27
|
+
@nesting.pop
|
|
28
|
+
@in_ol = false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def start_li(attrs)
|
|
32
|
+
current_nest = @nesting.last
|
|
33
|
+
if current_nest == "ol"
|
|
34
|
+
chr = "#"
|
|
35
|
+
else
|
|
36
|
+
chr = "*"
|
|
37
|
+
end
|
|
38
|
+
@output << Array.new(@nesting.length).map{chr}.join + " "
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def end_li
|
|
42
|
+
@output << "\n" unless @last_depth > @nesting.length
|
|
43
|
+
@last_depth = @nesting.length
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def start_dl attrs
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def end_dl
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def start_dt attrs
|
|
53
|
+
@output << "- "
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def end_dt
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def start_dd attrs
|
|
60
|
+
@output << " := "
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def end_dd
|
|
64
|
+
@output << "\n"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|