friendly_format 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +12 -0
- data/README +7 -8
- data/Rakefile +3 -5
- data/TODO +2 -0
- data/friendly_format.gemspec +17 -20
- 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/lib/friendly_format.rb +43 -22
- data/tasks/setup.rb +1 -1
- data/tasks/zentest.rake +36 -0
- data/test/sample/complex_article_result.txt +6 -2
- data/test/test_friendly_format.rb +45 -27
- metadata +12 -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
|
-
*
|
28
|
-
*
|
29
|
-
*
|
26
|
+
* ruby 1.8+ or 1.9.1+
|
27
|
+
* hpricot >=0.8 or
|
28
|
+
* nokogiri >=1.2 or
|
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
|
@@ -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
|
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
|
data/tasks/setup.rb
CHANGED
@@ -147,7 +147,7 @@ RCOV = "#{RUBY} -S rcov"
|
|
147
147
|
RDOC = "#{RUBY} -S rdoc"
|
148
148
|
GEM = "#{RUBY} -S gem"
|
149
149
|
|
150
|
-
%w(rcov spec/rake/spectask rubyforge bones facets/ansicode).each do |lib|
|
150
|
+
%w(rcov spec/rake/spectask rubyforge bones facets/ansicode zentest).each do |lib|
|
151
151
|
begin
|
152
152
|
require lib
|
153
153
|
Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", true}
|
data/tasks/zentest.rake
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
if HAVE_ZENTEST
|
2
|
+
|
3
|
+
# --------------------------------------------------------------------------
|
4
|
+
if test(?e, PROJ.test.file) or not PROJ.test.files.to_a.empty?
|
5
|
+
require 'autotest'
|
6
|
+
|
7
|
+
namespace :test do
|
8
|
+
task :autotest do
|
9
|
+
Autotest.run
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Run the autotest loop"
|
14
|
+
task :autotest => 'test:autotest'
|
15
|
+
|
16
|
+
end # if test
|
17
|
+
|
18
|
+
# --------------------------------------------------------------------------
|
19
|
+
if HAVE_SPEC_RAKE_SPECTASK and not PROJ.spec.files.to_a.empty?
|
20
|
+
require 'autotest/rspec'
|
21
|
+
|
22
|
+
namespace :spec do
|
23
|
+
task :autotest do
|
24
|
+
load '.autotest' if test(?f, '.autotest')
|
25
|
+
Autotest::Rspec.run
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Run the autotest loop"
|
30
|
+
task :autotest => 'spec:autotest'
|
31
|
+
|
32
|
+
end # if rspec
|
33
|
+
|
34
|
+
end # if HAVE_ZENTEST
|
35
|
+
|
36
|
+
# EOF
|
@@ -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: 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 +08: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,19 +40,9 @@ dependencies:
|
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: "1.
|
43
|
+
version: "1.2"
|
44
44
|
version:
|
45
|
-
|
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"
|
54
|
-
version:
|
55
|
-
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.
|
45
|
+
description: " make user input be valid xhtml and format it with gsub(\"\\n\", \"<br/>\") etc.\n you can partially allow some tags and don't escape them."
|
56
46
|
email: godfat (XD) godfat.org
|
57
47
|
executables: []
|
58
48
|
|
@@ -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
|
@@ -93,11 +81,14 @@ files:
|
|
93
81
|
- tasks/spec.rake
|
94
82
|
- tasks/svn.rake
|
95
83
|
- tasks/test.rake
|
84
|
+
- tasks/zentest.rake
|
96
85
|
- test/sample/complex_article.txt
|
97
86
|
- test/sample/complex_article_result.txt
|
98
87
|
- test/test_friendly_format.rb
|
99
88
|
has_rdoc: true
|
100
89
|
homepage: http://github.com/godfat/friendly_format
|
90
|
+
licenses: []
|
91
|
+
|
101
92
|
post_install_message:
|
102
93
|
rdoc_options:
|
103
94
|
- --charset=utf-8
|
@@ -123,9 +114,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
114
|
requirements: []
|
124
115
|
|
125
116
|
rubyforge_project: ludy
|
126
|
-
rubygems_version: 1.3.
|
117
|
+
rubygems_version: 1.3.5
|
127
118
|
signing_key:
|
128
|
-
specification_version:
|
119
|
+
specification_version: 3
|
129
120
|
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.
|
130
121
|
test_files:
|
131
122
|
- 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
|