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 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.6
2
- by Lin Jen-Shin (a.k.a. godfat-真常[http://godfat.org])
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
- * hpricot >=0.6 or
28
- * nokogiri >=1.1 or
29
- * libxml-ruby >=0.9
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
- * sudo gem install friendly_format
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 (a.k.a. godfat 真常)
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 (a.k.a. godfat 真常)'
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.6'] <<
13
- ['nokogiri', '>=1.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
@@ -1,5 +1,7 @@
1
1
  = friendly_article todo list
2
2
 
3
+ * more test cases
4
+
3
5
  * make format_article take an optional size argument that indicates
4
6
  how long should the result be. it should take &lt; as 1 character and
5
7
  <a href="/">嗯</a> as 1 character too. never cut out tag and unicode.
@@ -2,43 +2,40 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{friendly_format}
5
- s.version = "0.6.1"
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 (a.k.a. godfat \347\234\237\345\270\270)"]
9
- s.date = %q{2009-04-05}
10
- s.description = %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.}
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/abstract.rb", "lib/friendly_format/adapter/hpricot_adapter.rb", "lib/friendly_format/adapter/libxml_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"]
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.1}
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 = 2
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.4.2"])
29
- s.add_development_dependency(%q<hpricot>, [">= 0.6"])
30
- s.add_development_dependency(%q<nokogiri>, [">= 1.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.4.2"])
34
- s.add_dependency(%q<hpricot>, [">= 0.6"])
35
- s.add_dependency(%q<nokogiri>, [">= 1.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.4.2"])
40
- s.add_dependency(%q<hpricot>, [">= 0.6"])
41
- s.add_dependency(%q<nokogiri>, [">= 1.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
- class HpricotAdapter
6
- class << self
5
+ module HpricotAdapter
6
+ module_function
7
7
 
8
- def parse html
9
- Hpricot.parse(html)
10
- end
8
+ def parse html
9
+ Hpricot.parse(html)
10
+ end
11
11
 
12
- def to_xhtml node
13
- node.to_html
14
- end
12
+ def to_xhtml node
13
+ node.to_html
14
+ end
15
15
 
16
- def content node
17
- node.content
18
- end
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
- class NokogiriAdapter
7
- extend Abstract
5
+ module NokogiriAdapter
6
+ module_function
8
7
 
9
- def self.parse html
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", '&#xA;')}</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,3 +1,3 @@
1
1
  module FriendlyFormat
2
- VERSION = '0.6.1'
2
+ VERSION = '0.7.0'
3
3
  end
@@ -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", '<br />')
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 adapter.text?(e)
151
+ if e.text?
152
152
  format_url(e.content, attrs)
153
153
 
154
- elsif adapter.element?(e)
154
+ elsif e.elem?
155
155
  if adapter.empty?(e)
156
156
  adapter.to_xhtml(e)
157
157
  else
158
- "<#{e.name}>" +
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 elem, allowed_tags = Set.new, no_format_newline = false
181
+ def format_article_rec(elem, allowed_tags = Set.new, tag_name = nil)
182
+
182
183
  elem.children.map{ |e|
183
- if adapter.text?(e)
184
- if no_format_newline
185
- format_url(adapter.content(e))
186
- else
187
- format_newline(format_url(adapter.content(e)))
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 adapter.element?(e)
192
+ elsif e.elem?
191
193
  if allowed_tags.member?(e.name)
192
- if adapter.empty?(e) || e.name == 'a'
193
- adapter.to_xhtml(e)
194
+ if adapter.empty?(e)
195
+ node_tag_single(e)
194
196
  else
195
- "<#{e.name}>" +
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
- "&lt;#{e.name}&gt;"
204
+ ''
203
205
  else
204
- "&lt;#{e.name}&gt;" +
205
206
  format_article_rec(e, allowed_tags) +
206
207
  "&lt;/#{e.name}&gt;"
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('<', '&lt;').gsub('>', '&gt;')
@@ -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
+ "&lt;#{node.name}#{node_attrs(node)}&gt;"
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}
@@ -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 /><pre> 作者 godfat (godfat 真常) 站內 ProjectX
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 /><br />end of article...<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
- if FriendlyFormat.adapter == FriendlyFormat::LibxmlAdapter
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&lt;a&gt;orz</pre>', format_article(str, :pre)
142
132
 
143
133
  str = 'orz<img>asd'
144
- if FriendlyFormat.adapter == FriendlyFormat::LibxmlAdapter
145
- assert_equal('orz<img/>asd', format_article(str, :img))
146
- else
147
- assert_equal('orz<img />asd', format_article(str, :img))
148
- end
149
- assert_equal 'orz&lt;img&gt;asd', format_article(str)
134
+ assert_equal('orz<img />asd', format_article(str, :img))
135
+ assert_equal('orz&lt;img&gt;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 &lambda; 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 &lt;img src="asd"/&gt; 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 style="float: right;" src="http://flolac.iis.sinica.edu.tw/lambdawan/sites/default/files/ruby.png.thumb.jpg" /><br /><a href="http://www.ruby-forum.com/topic/169911">JRuby 1.1.5 Released</a><br /><a href="http://jruby.codehaus.org/">JRuby</a> 是用 Java 寫成的 Ruby interpreter/compiler.<br />原本 JRuby 只是普通的 open source project, 後來因為 <a href="http://www.sun.com/">Sun Microsystem</a>,<br />也就是 Java 的開發公司,看好 JRuby, 於是僱用 JRuby team,<br />full time 開發 JRuby. 後來 JRuby 在各方面都快速大幅成長,<br />尤其效能有了不可思議的大幅提昇,可能是 Sun 有一些撇步沒有公開吧。<br /><br />效能大幅提昇之後,JRuby 開發沒有停緩,接下來是非常大量的相容性提昇。<br />也從原本僅支援 interpret mode 到後來也支援 just in time 與 ahead of time 的<br />compilation mode. 非常驚人的開發速度。<br /><zzz>&lt;xd&gt;<br />此外,其中一位開發者,<a href="http://blog.headius.com/">Charles Nutter</a> 也經常參與 <a href="http://www.ruby-forum.com/forum/14">ruby-core</a> 的討論,<br />對於 Ruby 的開發頗有貢獻。&lt;/xd&gt;</zzz>'
200
-
201
- # img style after img src
202
- expected_18_hpricot = '<img src="http://flolac.iis.sinica.edu.tw/lambdawan/sites/default/files/ruby.png.thumb.jpg" style="float: right;" /><br /><a href="http://www.ruby-forum.com/topic/169911">JRuby 1.1.5 Released</a><br /><a href="http://jruby.codehaus.org/">JRuby</a> 是用 Java 寫成的 Ruby interpreter/compiler.<br />原本 JRuby 只是普通的 open source project, 後來因為 <a href="http://www.sun.com/">Sun Microsystem</a>,<br />也就是 Java 的開發公司,看好 JRuby, 於是僱用 JRuby team,<br />full time 開發 JRuby. 後來 JRuby 在各方面都快速大幅成長,<br />尤其效能有了不可思議的大幅提昇,可能是 Sun 有一些撇步沒有公開吧。<br /><br />效能大幅提昇之後,JRuby 開發沒有停緩,接下來是非常大量的相容性提昇。<br />也從原本僅支援 interpret mode 到後來也支援 just in time 與 ahead of time 的<br />compilation mode. 非常驚人的開發速度。<br /><zzz>&lt;xd&gt;<br />此外,其中一位開發者,<a href="http://blog.headius.com/">Charles Nutter</a> 也經常參與 <a href="http://www.ruby-forum.com/forum/14">ruby-core</a> 的討論,<br />對於 Ruby 的開發頗有貢獻。&lt;/xd&gt;</zzz>'
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>&lt;xd&gt;<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 的開發頗有貢獻。&lt;/xd&gt;</zzz>'
203
202
 
204
203
  result = format_article(input, SetCommon.new, :zzz)
205
- if RUBY_VERSION =~ /^1\.8/ && FriendlyFormat.adapter == FriendlyFormat::HpricotAdapter
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('&lt;a href="#"&gt;text&lt;/a&gt;', 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 LibxmlAdapter].each{ |adapter|
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.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
- - "Lin Jen-Shin (a.k.a. godfat \xE7\x9C\x9F\xE5\xB8\xB8)"
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-04-05 00:00:00 +08:00
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.4.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.6"
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.1"
43
+ version: "1.2"
44
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"
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.1
117
+ rubygems_version: 1.3.5
127
118
  signing_key:
128
- specification_version: 2
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