godfat-friendly_format 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +12 -0
- data/README +6 -7
- data/Rakefile +3 -5
- data/TODO +2 -0
- data/friendly_format.gemspec +17 -20
- data/lib/friendly_format.rb +43 -22
- data/lib/friendly_format/adapter/hpricot_adapter.rb +11 -24
- data/lib/friendly_format/adapter/nokogiri_adapter.rb +12 -6
- data/lib/friendly_format/version.rb +1 -1
- data/test/sample/complex_article_result.txt +6 -2
- data/test/test_friendly_format.rb +45 -27
- metadata +10 -21
- data/lib/friendly_format/adapter/abstract.rb +0 -31
- data/lib/friendly_format/adapter/libxml_adapter.rb +0 -25
data/CHANGES
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
= friendly_format changes history
|
2
2
|
|
3
|
+
== friendly_format 0.7.0 / 2009-07-31
|
4
|
+
|
5
|
+
* no more super long line. added a newline after br tag.
|
6
|
+
* all adapters work nearly the same now.
|
7
|
+
* dropped support for libxml
|
8
|
+
* fixed a bug that ignored tag attributes
|
9
|
+
* fixed a bug that in nested a tag
|
10
|
+
* fixed a bug that added extra slash in not allowed tag
|
11
|
+
* fixed format_autolink_rec, use the same trick in format_aritcle
|
12
|
+
* now tag attributes are ordered by lexical order
|
13
|
+
* now js attrs in allowed tags would be filter out
|
14
|
+
|
3
15
|
== friendly_format 0.6.1 / 2009-04-05
|
4
16
|
|
5
17
|
* added nokogiri and libxml-ruby support.
|
data/README
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
= friendly_format 0.
|
2
|
-
by Lin Jen-Shin (
|
1
|
+
= friendly_format 0.7.0
|
2
|
+
by Lin Jen-Shin (aka godfat-真常[http://godfat.org])
|
3
3
|
godfat (XD) godfat.org
|
4
4
|
|
5
5
|
== LINKS:
|
@@ -19,24 +19,23 @@ by Lin Jen-Shin (a.k.a. godfat-真常[http://godfat.org])
|
|
19
19
|
FriendlyFormat.format_article(text, FriendlyFormat::SetCommon.new)
|
20
20
|
|
21
21
|
FriendlyFormat.adapter = FriendlyFormat::NokogiriAdapter
|
22
|
-
FriendlyFormat.adapter = FriendlyFormat::LibxmlAdapter
|
23
22
|
FriendlyFormat.adapter = FriendlyFormat::HpricotAdapter # default
|
24
23
|
|
25
24
|
== REQUIREMENTS:
|
26
25
|
|
27
|
-
*
|
26
|
+
* ruby 1.8+ or 1.9.1+
|
27
|
+
* hpricot >=0.8 or
|
28
28
|
* nokogiri >=1.2 or
|
29
|
-
* libxml-ruby >=1.1
|
30
29
|
|
31
30
|
== INSTALL:
|
32
31
|
|
33
|
-
*
|
32
|
+
* gem install friendly_format
|
34
33
|
|
35
34
|
== LICENSE:
|
36
35
|
|
37
36
|
Apache License 2.0
|
38
37
|
|
39
|
-
Copyright (c) 2008, Lin Jen-Shin (
|
38
|
+
Copyright (c) 2008, Lin Jen-Shin (aka godfat 真常)
|
40
39
|
|
41
40
|
Licensed under the Apache License, Version 2.0 (the "License");
|
42
41
|
you may not use this file except in compliance with the License.
|
data/Rakefile
CHANGED
@@ -4,15 +4,13 @@ require 'bones'
|
|
4
4
|
Bones.setup
|
5
5
|
|
6
6
|
PROJ.name = 'friendly_format'
|
7
|
-
PROJ.authors = 'Lin Jen-Shin (
|
7
|
+
PROJ.authors = 'Lin Jen-Shin (aka godfat 真常)'
|
8
8
|
PROJ.email = 'godfat (XD) godfat.org'
|
9
9
|
PROJ.url = "http://github.com/godfat/#{PROJ.name}"
|
10
10
|
PROJ.rubyforge.name = 'ludy'
|
11
11
|
|
12
|
-
PROJ.gem.development_dependencies << ['hpricot', '>=0.
|
13
|
-
['nokogiri', '>=1.
|
14
|
-
['libxml-ruby', '>=0.9']
|
15
|
-
|
12
|
+
PROJ.gem.development_dependencies << ['hpricot', '>=0.8'] <<
|
13
|
+
['nokogiri', '>=1.2']
|
16
14
|
# PROJ.ruby_opts.delete '-w'
|
17
15
|
|
18
16
|
PROJ.description = PROJ.summary = paragraphs_of('README', 'description').join("\n\n")
|
data/TODO
CHANGED
data/friendly_format.gemspec
CHANGED
@@ -2,43 +2,40 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{friendly_format}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.7.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
-
s.authors = ["Lin Jen-Shin (
|
9
|
-
s.date = %q{2009-
|
10
|
-
s.description = %q{make user input be valid xhtml and format it with gsub("\n", "<br/>") etc.
|
8
|
+
s.authors = ["Lin Jen-Shin (aka godfat \347\234\237\345\270\270)"]
|
9
|
+
s.date = %q{2009-07-31}
|
10
|
+
s.description = %q{ make user input be valid xhtml and format it with gsub("\n", "<br/>") etc.
|
11
|
+
you can partially allow some tags and don't escape them.}
|
11
12
|
s.email = %q{godfat (XD) godfat.org}
|
12
13
|
s.extra_rdoc_files = ["CHANGES", "LICENSE", "NOTICE", "README", "TODO", "friendly_format.gemspec"]
|
13
|
-
s.files = ["CHANGES", "LICENSE", "NOTICE", "README", "Rakefile", "TODO", "friendly_format.gemspec", "lib/friendly_format.rb", "lib/friendly_format/adapter/
|
14
|
-
s.has_rdoc = true
|
14
|
+
s.files = ["CHANGES", "LICENSE", "NOTICE", "README", "Rakefile", "TODO", "friendly_format.gemspec", "lib/friendly_format.rb", "lib/friendly_format/adapter/hpricot_adapter.rb", "lib/friendly_format/adapter/nokogiri_adapter.rb", "lib/friendly_format/set_common.rb", "lib/friendly_format/set_strict.rb", "lib/friendly_format/version.rb", "test/sample/complex_article.txt", "test/sample/complex_article_result.txt", "test/test_friendly_format.rb"]
|
15
15
|
s.homepage = %q{http://github.com/godfat/friendly_format}
|
16
16
|
s.rdoc_options = ["--charset=utf-8", "--inline-source", "--line-numbers", "--promiscuous", "--main", "README"]
|
17
17
|
s.require_paths = ["lib"]
|
18
18
|
s.rubyforge_project = %q{ludy}
|
19
|
-
s.rubygems_version = %q{1.3.
|
19
|
+
s.rubygems_version = %q{1.3.5}
|
20
20
|
s.summary = %q{make user input be valid xhtml and format it with gsub("\n", "<br/>") etc. you can partially allow some tags and don't escape them.}
|
21
21
|
s.test_files = ["test/test_friendly_format.rb"]
|
22
22
|
|
23
23
|
if s.respond_to? :specification_version then
|
24
24
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
-
s.specification_version =
|
25
|
+
s.specification_version = 3
|
26
26
|
|
27
27
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
-
s.add_development_dependency(%q<bones>, [">= 2.
|
29
|
-
s.add_development_dependency(%q<hpricot>, [">= 0.
|
30
|
-
s.add_development_dependency(%q<nokogiri>, [">= 1.
|
31
|
-
s.add_development_dependency(%q<libxml-ruby>, [">= 0.9"])
|
28
|
+
s.add_development_dependency(%q<bones>, [">= 2.5.1"])
|
29
|
+
s.add_development_dependency(%q<hpricot>, [">= 0.8"])
|
30
|
+
s.add_development_dependency(%q<nokogiri>, [">= 1.2"])
|
32
31
|
else
|
33
|
-
s.add_dependency(%q<bones>, [">= 2.
|
34
|
-
s.add_dependency(%q<hpricot>, [">= 0.
|
35
|
-
s.add_dependency(%q<nokogiri>, [">= 1.
|
36
|
-
s.add_dependency(%q<libxml-ruby>, [">= 0.9"])
|
32
|
+
s.add_dependency(%q<bones>, [">= 2.5.1"])
|
33
|
+
s.add_dependency(%q<hpricot>, [">= 0.8"])
|
34
|
+
s.add_dependency(%q<nokogiri>, [">= 1.2"])
|
37
35
|
end
|
38
36
|
else
|
39
|
-
s.add_dependency(%q<bones>, [">= 2.
|
40
|
-
s.add_dependency(%q<hpricot>, [">= 0.
|
41
|
-
s.add_dependency(%q<nokogiri>, [">= 1.
|
42
|
-
s.add_dependency(%q<libxml-ruby>, [">= 0.9"])
|
37
|
+
s.add_dependency(%q<bones>, [">= 2.5.1"])
|
38
|
+
s.add_dependency(%q<hpricot>, [">= 0.8"])
|
39
|
+
s.add_dependency(%q<nokogiri>, [">= 1.2"])
|
43
40
|
end
|
44
41
|
end
|
data/lib/friendly_format.rb
CHANGED
@@ -91,7 +91,7 @@ module FriendlyFormat
|
|
91
91
|
def format_newline text
|
92
92
|
# windows: \r\n
|
93
93
|
# mac os 9: \r
|
94
|
-
text.gsub("\r\n", "\n").tr("\r", "\n").gsub("\n",
|
94
|
+
text.gsub("\r\n", "\n").tr("\r", "\n").gsub("\n", "<br />\n")
|
95
95
|
end
|
96
96
|
|
97
97
|
|
@@ -148,14 +148,14 @@ module FriendlyFormat
|
|
148
148
|
# @api private
|
149
149
|
def format_autolink_rec elem, attrs = {}
|
150
150
|
elem.children.map{ |e|
|
151
|
-
if
|
151
|
+
if e.text?
|
152
152
|
format_url(e.content, attrs)
|
153
153
|
|
154
|
-
elsif
|
154
|
+
elsif e.elem?
|
155
155
|
if adapter.empty?(e)
|
156
156
|
adapter.to_xhtml(e)
|
157
157
|
else
|
158
|
-
|
158
|
+
node_tag_normal(e) +
|
159
159
|
format_autolink_rec(e, attrs) +
|
160
160
|
"</#{e.name}>"
|
161
161
|
end
|
@@ -178,30 +178,31 @@ module FriendlyFormat
|
|
178
178
|
|
179
179
|
# recursion
|
180
180
|
# @api private
|
181
|
-
def format_article_rec
|
181
|
+
def format_article_rec(elem, allowed_tags = Set.new, tag_name = nil)
|
182
|
+
|
182
183
|
elem.children.map{ |e|
|
183
|
-
if
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
format_newline(
|
184
|
+
if e.text?
|
185
|
+
result = e.to_html
|
186
|
+
case tag_name
|
187
|
+
when 'pre'; format_url( result)
|
188
|
+
when 'a'; format_newline(result)
|
189
|
+
else ; format_newline(format_url(result))
|
188
190
|
end
|
189
191
|
|
190
|
-
elsif
|
192
|
+
elsif e.elem?
|
191
193
|
if allowed_tags.member?(e.name)
|
192
|
-
if adapter.empty?(e)
|
193
|
-
|
194
|
+
if adapter.empty?(e)
|
195
|
+
node_tag_single(e)
|
194
196
|
else
|
195
|
-
|
196
|
-
format_article_rec(
|
197
|
-
e, allowed_tags, e.name == 'pre') +
|
197
|
+
node_tag_normal(e) +
|
198
|
+
format_article_rec(e, allowed_tags, e.name) +
|
198
199
|
"</#{e.name}>"
|
199
200
|
end
|
200
201
|
else
|
202
|
+
node_tag_escape(e) +
|
201
203
|
if adapter.empty?(e)
|
202
|
-
|
204
|
+
''
|
203
205
|
else
|
204
|
-
"<#{e.name}>" +
|
205
206
|
format_article_rec(e, allowed_tags) +
|
206
207
|
"</#{e.name}>"
|
207
208
|
end
|
@@ -211,10 +212,6 @@ module FriendlyFormat
|
|
211
212
|
}.join
|
212
213
|
end
|
213
214
|
|
214
|
-
# i cannot find a way to escape both lt and gt,
|
215
|
-
# so it's a trick that just escape lt and no browser
|
216
|
-
# would treat complex lt and gt structure to be a tag
|
217
|
-
# wraping content.
|
218
215
|
# @api private
|
219
216
|
def escape_ltgt text
|
220
217
|
text.gsub('<', '<').gsub('>', '>')
|
@@ -230,5 +227,29 @@ module FriendlyFormat
|
|
230
227
|
end
|
231
228
|
end
|
232
229
|
|
230
|
+
def node_tag_single node
|
231
|
+
"<#{node.name}#{node_attrs_reject_js(node)} />"
|
232
|
+
end
|
233
|
+
|
234
|
+
def node_tag_normal node
|
235
|
+
"<#{node.name}#{node_attrs_reject_js(node)}>"
|
236
|
+
end
|
237
|
+
|
238
|
+
def node_tag_escape node
|
239
|
+
"<#{node.name}#{node_attrs(node)}>"
|
240
|
+
end
|
241
|
+
|
242
|
+
def node_attrs node
|
243
|
+
attrs2str(node.attributes)
|
244
|
+
end
|
245
|
+
|
246
|
+
def node_attrs_reject_js node
|
247
|
+
attrs2str(node.attributes.reject{ |k, v| k =~ /\Aon/ })
|
248
|
+
end
|
249
|
+
|
250
|
+
def attrs2str attrs
|
251
|
+
attrs.sort.inject(''){ |i, (k, v)| i + " #{k}=\"#{v}\"" }
|
252
|
+
end
|
253
|
+
|
233
254
|
end
|
234
255
|
end
|
@@ -2,33 +2,20 @@
|
|
2
2
|
require 'hpricot'
|
3
3
|
|
4
4
|
module FriendlyFormat
|
5
|
-
|
6
|
-
|
5
|
+
module HpricotAdapter
|
6
|
+
module_function
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
def parse html
|
9
|
+
Hpricot.parse(html)
|
10
|
+
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
def to_xhtml node
|
13
|
+
node.to_html
|
14
|
+
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
def empty? node
|
17
|
+
node.empty?
|
18
|
+
end
|
19
19
|
|
20
|
-
def element? node
|
21
|
-
node.kind_of?(Hpricot::Elem)
|
22
|
-
end
|
23
|
-
|
24
|
-
def text? node
|
25
|
-
node.kind_of?(Hpricot::Text)
|
26
|
-
end
|
27
|
-
|
28
|
-
def empty? node
|
29
|
-
node.empty?
|
30
|
-
end
|
31
|
-
|
32
|
-
end # of class method for HpricotAdapter
|
33
20
|
end # of HpricotAdapter
|
34
21
|
end # of FriendlyFormat
|
@@ -1,21 +1,27 @@
|
|
1
1
|
|
2
|
-
require 'friendly_format/adapter/abstract'
|
3
2
|
require 'nokogiri'
|
4
3
|
|
5
4
|
module FriendlyFormat
|
6
|
-
|
7
|
-
|
5
|
+
module NokogiriAdapter
|
6
|
+
module_function
|
8
7
|
|
9
|
-
def
|
8
|
+
def parse html
|
10
9
|
# root is html, children is [body], first is body
|
11
|
-
# same as libxml
|
12
10
|
# drop zzz with .children.first since it would wrap a tag p for the article
|
13
11
|
Nokogiri::HTML.parse(
|
14
|
-
"<zzz>#{html}</zzz>",
|
12
|
+
"<zzz>#{html.gsub("\n", '
')}</zzz>",
|
15
13
|
nil, # url?
|
16
14
|
html.respond_to?(:encoding) ? html.encoding.name : 'utf-8'
|
17
15
|
).root.children.first.children.first
|
18
16
|
end
|
19
17
|
|
18
|
+
def to_xhtml node
|
19
|
+
node.to_xhtml
|
20
|
+
end
|
21
|
+
|
22
|
+
def empty? node
|
23
|
+
node.children.empty?
|
24
|
+
end
|
25
|
+
|
20
26
|
end # of NokogiriAdapter
|
21
27
|
end # of FriendlyFormat
|
@@ -1,4 +1,5 @@
|
|
1
|
-
<a href="http://phpbb.godfat.org/viewtopic.php?t=873" title="http://phpbb.godfat.org/viewtopic.php?t=873">http://phpbb.godfat.org/viewtopic.php?t=873</a><br
|
1
|
+
<a href="http://phpbb.godfat.org/viewtopic.php?t=873" title="http://phpbb.godfat.org/viewtopic.php?t=873">http://phpbb.godfat.org/viewtopic.php?t=873</a><br />
|
2
|
+
<pre> 作者 godfat (godfat 真常) 站內 ProjectX
|
2
3
|
標題 Re: [PSC] variants timer
|
3
4
|
時間 2008/03/04 Tue 00:34:54
|
4
5
|
<a href="http://phpbb.godfat.org/viewtopic.php?t=873" title="http://phpbb.godfat.org/viewtopic.php?t=873">http://phpbb.godfat.org/viewtopic.php?t=873</a>
|
@@ -105,4 +106,7 @@ tuple.cpp:20: error: "type_not_found" is not a member of "T"
|
|
105
106
|
|
106
107
|
--
|
107
108
|
※ Orign: 群星的眷屬 chance.twbbs.org
|
108
|
-
◆ Author: godfat From 220-135-28-18.HINET-IP.hinet.net</pre><br
|
109
|
+
◆ Author: godfat From 220-135-28-18.HINET-IP.hinet.net</pre><br />
|
110
|
+
<br />
|
111
|
+
end of article...<br />
|
112
|
+
|
@@ -89,20 +89,10 @@ http://www.amazon.co.jp/%E3%80%8C%E7%84%94~%E3%83%9B%E3%83%A0%E3%83%A9%E3%80%8D~
|
|
89
89
|
'Thirst for Knowledge
|
90
90
|
<img src="http://friends.roodo.com/images/diary_photos_large/15386/MjMyNjYtdGhpcnN0X2Zvcl9rbm93bGVkZ2U=.jpg" />
|
91
91
|
|
92
|
-
2007年12月14日
|
93
|
-
'
|
94
|
-
libxml =
|
95
|
-
'Thirst for Knowledge
|
96
|
-
<img src="http://friends.roodo.com/images/diary_photos_large/15386/MjMyNjYtdGhpcnN0X2Zvcl9rbm93bGVkZ2U=.jpg"/>
|
97
|
-
|
98
92
|
2007年12月14日
|
99
93
|
'
|
100
94
|
s = format_autolink(str)
|
101
|
-
|
102
|
-
assert_equal(libxml, s)
|
103
|
-
else
|
104
|
-
assert_equal(str, s)
|
105
|
-
end
|
95
|
+
assert_equal(str, s)
|
106
96
|
assert_equal(str, format_autolink_regexp(str))
|
107
97
|
end
|
108
98
|
|
@@ -141,19 +131,17 @@ http://www.amazon.co.jp/%E3%80%8C%E7%84%94~%E3%83%9B%E3%83%A0%E3%83%A9%E3%80%8D~
|
|
141
131
|
assert_equal '<pre>asdasd<a>orz</pre>', format_article(str, :pre)
|
142
132
|
|
143
133
|
str = 'orz<img>asd'
|
144
|
-
|
145
|
-
|
146
|
-
else
|
147
|
-
assert_equal('orz<img />asd', format_article(str, :img))
|
148
|
-
end
|
149
|
-
assert_equal 'orz<img>asd', format_article(str)
|
134
|
+
assert_equal('orz<img />asd', format_article(str, :img))
|
135
|
+
assert_equal('orz<img>asd', format_article(str))
|
150
136
|
end
|
137
|
+
|
151
138
|
def test_trim_url
|
152
139
|
str = 'test with http://890123456789012345678901234567890123456789012345678901234567890123456789.com'
|
153
140
|
|
154
141
|
assert_equal 'test with <a href="http://890123456789012345678901234567890123456789012345678901234567890123456789.com" title="http://890123456789012345678901234567890123456789012345678901234567890123456789.com">http://89012345678901234567890123456789012345678901234567890123456789012...</a>', s = format_article(str)
|
155
142
|
assert_equal s, format_autolink_regexp(str)
|
156
143
|
end
|
144
|
+
|
157
145
|
def test_escape_html
|
158
146
|
str = 'a lambda expression is λ x. x+1'
|
159
147
|
libxml = 'a lambda expression is λ x. x+1'
|
@@ -168,6 +156,7 @@ http://www.amazon.co.jp/%E3%80%8C%E7%84%94~%E3%83%9B%E3%83%A0%E3%83%A9%E3%80%8D~
|
|
168
156
|
str = 'as you can see, use <img src="asd"/> to use'
|
169
157
|
assert_equal str, format_article(str)
|
170
158
|
end
|
159
|
+
|
171
160
|
def test_html_with_pre_and_newline2br
|
172
161
|
result = File.read('test/sample/complex_article_result.txt').chop
|
173
162
|
input = File.read('test/sample/complex_article.txt')
|
@@ -196,17 +185,23 @@ compilation mode. 非常驚人的開發速度。
|
|
196
185
|
此外,其中一位開發者,<a href="http://blog.headius.com/">Charles Nutter</a> 也經常參與 <a href="http://www.ruby-forum.com/forum/14">ruby-core</a> 的討論,
|
197
186
|
對於 Ruby 的開發頗有貢獻。'
|
198
187
|
|
199
|
-
expected = '<img
|
200
|
-
|
201
|
-
|
202
|
-
|
188
|
+
expected = '<img src="http://flolac.iis.sinica.edu.tw/lambdawan/sites/default/files/ruby.png.thumb.jpg" style="float: right;" /><br />
|
189
|
+
<a href="http://www.ruby-forum.com/topic/169911">JRuby 1.1.5 Released</a><br />
|
190
|
+
<a href="http://jruby.codehaus.org/">JRuby</a> 是用 Java 寫成的 Ruby interpreter/compiler.<br />
|
191
|
+
原本 JRuby 只是普通的 open source project, 後來因為 <a href="http://www.sun.com/">Sun Microsystem</a>,<br />
|
192
|
+
也就是 Java 的開發公司,看好 JRuby, 於是僱用 JRuby team,<br />
|
193
|
+
full time 開發 JRuby. 後來 JRuby 在各方面都快速大幅成長,<br />
|
194
|
+
尤其效能有了不可思議的大幅提昇,可能是 Sun 有一些撇步沒有公開吧。<br />
|
195
|
+
<br />
|
196
|
+
效能大幅提昇之後,JRuby 開發沒有停緩,接下來是非常大量的相容性提昇。<br />
|
197
|
+
也從原本僅支援 interpret mode 到後來也支援 just in time 與 ahead of time 的<br />
|
198
|
+
compilation mode. 非常驚人的開發速度。<br />
|
199
|
+
<zzz><xd><br />
|
200
|
+
此外,其中一位開發者,<a href="http://blog.headius.com/">Charles Nutter</a> 也經常參與 <a href="http://www.ruby-forum.com/forum/14">ruby-core</a> 的討論,<br />
|
201
|
+
對於 Ruby 的開發頗有貢獻。</xd></zzz>'
|
203
202
|
|
204
203
|
result = format_article(input, SetCommon.new, :zzz)
|
205
|
-
|
206
|
-
assert(result == expected_18_hpricot)
|
207
|
-
else
|
208
|
-
assert(result == expected)
|
209
|
-
end
|
204
|
+
assert_equal(expected, result)
|
210
205
|
end
|
211
206
|
|
212
207
|
def test_empty_article
|
@@ -219,9 +214,32 @@ compilation mode. 非常驚人的開發速度。
|
|
219
214
|
s = '<z>zzz</z>'
|
220
215
|
assert_equal s, format_article(s, Set.new << :z)
|
221
216
|
end
|
217
|
+
|
218
|
+
def test_preserve_attributes
|
219
|
+
s = '<a href="#">text</a>'
|
220
|
+
assert_equal('<a href="#">text</a>', format_article(s))
|
221
|
+
|
222
|
+
s = '<div class="orz">test</div>'
|
223
|
+
assert_equal(s, format_article(s, 'div'))
|
224
|
+
|
225
|
+
assert_equal(s, format_autolink(s))
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_nested_a_tag
|
229
|
+
s = '<a href="uri"><img src="uri" /></a>'
|
230
|
+
assert_equal(s, format_article(s, 'img', 'a'))
|
231
|
+
end
|
232
|
+
|
233
|
+
def test_filter_js
|
234
|
+
s = '<a href="#" onclick="window.alert(\'attack!\')">js</a>'
|
235
|
+
assert_equal('<a href="#">js</a>', format_article(s, SetCommon.new))
|
236
|
+
|
237
|
+
s = '<a href="#" onclick="window.alert(\'attack!\')">js</a>'
|
238
|
+
assert_equal(FriendlyFormat.escape_ltgt(s), format_article(s))
|
239
|
+
end
|
222
240
|
end
|
223
241
|
|
224
|
-
%w[HpricotAdapter NokogiriAdapter
|
242
|
+
%w[HpricotAdapter NokogiriAdapter].each{ |adapter|
|
225
243
|
eval <<-RUBY
|
226
244
|
class Test#{adapter} < TestCase
|
227
245
|
include TestCases
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: godfat-friendly_format
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- "Lin Jen-Shin (
|
7
|
+
- "Lin Jen-Shin (aka godfat \xE7\x9C\x9F\xE5\xB8\xB8)"
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-07-31 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 2.
|
23
|
+
version: 2.5.1
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: hpricot
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: "0.
|
33
|
+
version: "0.8"
|
34
34
|
version:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: nokogiri
|
@@ -40,17 +40,7 @@ dependencies:
|
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: "1.
|
44
|
-
version:
|
45
|
-
- !ruby/object:Gem::Dependency
|
46
|
-
name: libxml-ruby
|
47
|
-
type: :development
|
48
|
-
version_requirement:
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - ">="
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: "0.9"
|
43
|
+
version: "1.2"
|
54
44
|
version:
|
55
45
|
description: make user input be valid xhtml and format it with gsub("\n", "<br/>") etc. you can partially allow some tags and don't escape them.
|
56
46
|
email: godfat (XD) godfat.org
|
@@ -74,9 +64,7 @@ files:
|
|
74
64
|
- TODO
|
75
65
|
- friendly_format.gemspec
|
76
66
|
- lib/friendly_format.rb
|
77
|
-
- lib/friendly_format/adapter/abstract.rb
|
78
67
|
- lib/friendly_format/adapter/hpricot_adapter.rb
|
79
|
-
- lib/friendly_format/adapter/libxml_adapter.rb
|
80
68
|
- lib/friendly_format/adapter/nokogiri_adapter.rb
|
81
69
|
- lib/friendly_format/set_common.rb
|
82
70
|
- lib/friendly_format/set_strict.rb
|
@@ -84,8 +72,9 @@ files:
|
|
84
72
|
- test/sample/complex_article.txt
|
85
73
|
- test/sample/complex_article_result.txt
|
86
74
|
- test/test_friendly_format.rb
|
87
|
-
has_rdoc:
|
75
|
+
has_rdoc: false
|
88
76
|
homepage: http://github.com/godfat/friendly_format
|
77
|
+
licenses:
|
89
78
|
post_install_message:
|
90
79
|
rdoc_options:
|
91
80
|
- --charset=utf-8
|
@@ -111,9 +100,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
100
|
requirements: []
|
112
101
|
|
113
102
|
rubyforge_project: ludy
|
114
|
-
rubygems_version: 1.
|
103
|
+
rubygems_version: 1.3.5
|
115
104
|
signing_key:
|
116
|
-
specification_version:
|
105
|
+
specification_version: 3
|
117
106
|
summary: make user input be valid xhtml and format it with gsub("\n", "<br/>") etc. you can partially allow some tags and don't escape them.
|
118
107
|
test_files:
|
119
108
|
- test/test_friendly_format.rb
|
@@ -1,31 +0,0 @@
|
|
1
|
-
|
2
|
-
module FriendlyFormat
|
3
|
-
module Abstract
|
4
|
-
|
5
|
-
def method_name node
|
6
|
-
# discard body
|
7
|
-
node.children.to_s
|
8
|
-
end
|
9
|
-
|
10
|
-
def to_xhtml node
|
11
|
-
node.to_xhtml
|
12
|
-
end
|
13
|
-
|
14
|
-
def content node
|
15
|
-
node.to_s
|
16
|
-
end
|
17
|
-
|
18
|
-
def element? node
|
19
|
-
node.element?
|
20
|
-
end
|
21
|
-
|
22
|
-
def text? node
|
23
|
-
node.text?
|
24
|
-
end
|
25
|
-
|
26
|
-
def empty? node
|
27
|
-
node.children.empty?
|
28
|
-
end
|
29
|
-
|
30
|
-
end # of Abstract
|
31
|
-
end # of FriendlyFormat
|
@@ -1,25 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'friendly_format/adapter/abstract'
|
3
|
-
require 'libxml'
|
4
|
-
|
5
|
-
module FriendlyFormat
|
6
|
-
class LibxmlAdapter
|
7
|
-
extend Abstract
|
8
|
-
|
9
|
-
def self.parse html
|
10
|
-
parser = LibXML::XML::HTMLParser.string(
|
11
|
-
"<zzz>#{html}</zzz>",
|
12
|
-
:options => LibXML::XML::HTMLParser::Options::RECOVER)
|
13
|
-
|
14
|
-
# root is html, children is [body], first is body
|
15
|
-
# same as nokogiri
|
16
|
-
# drop zzz with .children.first since it would wrap a tag p for the article
|
17
|
-
parser.parse.root.children.first.children.first
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.to_xhtml node
|
21
|
-
node.to_s
|
22
|
-
end
|
23
|
-
|
24
|
-
end # of LibxmlAdapter
|
25
|
-
end # of FriendlyFormat
|