friendly_format 0.5.1 → 0.6.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/CHANGES +14 -1
- data/README +8 -2
- data/Rakefile +19 -32
- data/TODO +1 -0
- data/friendly_format.gemspec +18 -16
- data/lib/friendly_format/adapter/abstract.rb +31 -0
- data/lib/friendly_format/adapter/hpricot_adapter.rb +34 -0
- data/lib/friendly_format/adapter/libxml_adapter.rb +25 -0
- data/lib/friendly_format/adapter/nokogiri_adapter.rb +21 -0
- data/lib/friendly_format/set_common.rb +5 -5
- data/lib/friendly_format/set_strict.rb +2 -2
- data/lib/friendly_format/version.rb +1 -1
- data/lib/friendly_format.rb +162 -99
- data/tasks/ann.rake +1 -1
- data/tasks/gem.rake +11 -2
- data/tasks/post_load.rake +2 -7
- data/tasks/rdoc.rake +4 -3
- data/tasks/setup.rb +35 -22
- data/test/sample/complex_article_result.txt +46 -46
- data/test/test_friendly_format.rb +92 -26
- metadata +22 -10
- data/tasks/manifest.rake +0 -48
data/tasks/gem.rake
CHANGED
@@ -37,8 +37,6 @@ class GemPackageTask < Rake::PackageTask
|
|
37
37
|
local_setup = File.join(Dir.pwd, %w[tasks setup.rb])
|
38
38
|
if !test(?e, local_setup)
|
39
39
|
Dir.glob(::Bones.path(%w[lib bones tasks *])).each {|fn| bones_files << fn}
|
40
|
-
gem_spec.files = (gem_spec.files +
|
41
|
-
bones_files.map {|fn| File.join('tasks', File.basename(fn))}).sort
|
42
40
|
end
|
43
41
|
end
|
44
42
|
|
@@ -63,6 +61,10 @@ class GemPackageTask < Rake::PackageTask
|
|
63
61
|
|
64
62
|
file package_dir_path => bones_files do
|
65
63
|
mkdir_p package_dir rescue nil
|
64
|
+
|
65
|
+
gem_spec.files = (gem_spec.files +
|
66
|
+
bones_files.map {|fn| File.join('tasks', File.basename(fn))}).sort
|
67
|
+
|
66
68
|
bones_files.each do |fn|
|
67
69
|
base_fn = File.join('tasks', File.basename(fn))
|
68
70
|
f = File.join(package_dir_path, base_fn)
|
@@ -157,6 +159,13 @@ namespace :gem do
|
|
157
159
|
puts PROJ.gem._spec.to_ruby
|
158
160
|
end
|
159
161
|
|
162
|
+
desc 'Write the gemspec '
|
163
|
+
task :spec => 'gem:prereqs' do
|
164
|
+
File.open("#{PROJ.name}.gemspec", 'w') do |f|
|
165
|
+
f.write PROJ.gem._spec.to_ruby
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
160
169
|
desc 'Install the gem'
|
161
170
|
task :install => [:clobber, 'gem:package'] do
|
162
171
|
sh "#{SUDO} #{GEM} install --local pkg/#{PROJ.gem._spec.full_name}"
|
data/tasks/post_load.rake
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
# This file does not define any rake tasks. It is used to load some project
|
3
3
|
# settings if they are not defined by the user.
|
4
4
|
|
5
|
-
PROJ.rdoc.exclude << "^#{Regexp.escape(PROJ.manifest_file)}$"
|
6
5
|
PROJ.exclude << ["^#{Regexp.escape(PROJ.ann.file)}$",
|
6
|
+
"^#{Regexp.escape(PROJ.ignore_file)}$",
|
7
7
|
"^#{Regexp.escape(PROJ.rdoc.dir)}/",
|
8
8
|
"^#{Regexp.escape(PROJ.rcov.dir)}/"]
|
9
9
|
|
@@ -25,12 +25,7 @@ PROJ.description ||= paragraphs_of(PROJ.readme_file, 'description').join("\n\n")
|
|
25
25
|
|
26
26
|
PROJ.summary ||= PROJ.description.split('.').first
|
27
27
|
|
28
|
-
PROJ.gem.files ||=
|
29
|
-
if test(?f, PROJ.manifest_file)
|
30
|
-
files = File.readlines(PROJ.manifest_file).map {|fn| fn.chomp.strip}
|
31
|
-
files.delete ''
|
32
|
-
files
|
33
|
-
else [] end
|
28
|
+
PROJ.gem.files ||= manifest
|
34
29
|
|
35
30
|
PROJ.gem.executables ||= PROJ.gem.files.find_all {|fn| fn =~ %r/^bin/}
|
36
31
|
|
data/tasks/rdoc.rake
CHANGED
@@ -19,10 +19,11 @@ namespace :doc do
|
|
19
19
|
end
|
20
20
|
rd.rdoc_files.push(*files)
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
name = PROJ.name
|
24
23
|
rf_name = PROJ.rubyforge.name
|
25
|
-
|
24
|
+
|
25
|
+
title = "#{name}-#{PROJ.version} Documentation"
|
26
|
+
title = "#{rf_name}'s " + title if rf_name.valid? and rf_name != name
|
26
27
|
|
27
28
|
rd.options << "-t #{title}"
|
28
29
|
rd.options.concat(rdoc.opts)
|
data/tasks/setup.rb
CHANGED
@@ -4,8 +4,9 @@ require 'rake'
|
|
4
4
|
require 'rake/clean'
|
5
5
|
require 'fileutils'
|
6
6
|
require 'ostruct'
|
7
|
+
require 'find'
|
7
8
|
|
8
|
-
class OpenStruct; undef :gem; end
|
9
|
+
class OpenStruct; undef :gem if defined? :gem; end
|
9
10
|
|
10
11
|
# TODO: make my own openstruct type object that includes descriptions
|
11
12
|
# TODO: use the descriptions to output help on the available bones options
|
@@ -27,8 +28,8 @@ PROJ = OpenStruct.new(
|
|
27
28
|
:ruby_opts => %w(-w),
|
28
29
|
:libs => [],
|
29
30
|
:history_file => 'History.txt',
|
30
|
-
:manifest_file => 'Manifest.txt',
|
31
31
|
:readme_file => 'README.txt',
|
32
|
+
:ignore_file => '.bnsignore',
|
32
33
|
|
33
34
|
# Announce
|
34
35
|
:ann => OpenStruct.new(
|
@@ -62,7 +63,7 @@ PROJ = OpenStruct.new(
|
|
62
63
|
# File Annotations
|
63
64
|
:notes => OpenStruct.new(
|
64
65
|
:exclude => %w(^tasks/setup\.rb$),
|
65
|
-
:extensions => %w(.txt .rb .erb) << '',
|
66
|
+
:extensions => %w(.txt .rb .erb .rdoc) << '',
|
66
67
|
:tags => %w(FIXME OPTIMIZE TODO)
|
67
68
|
),
|
68
69
|
|
@@ -77,7 +78,7 @@ PROJ = OpenStruct.new(
|
|
77
78
|
# Rdoc
|
78
79
|
:rdoc => OpenStruct.new(
|
79
80
|
:opts => [],
|
80
|
-
:include => %w(^lib/ ^bin/ ^ext/ \.txt$),
|
81
|
+
:include => %w(^lib/ ^bin/ ^ext/ \.txt$ \.rdoc$),
|
81
82
|
:exclude => %w(extconf\.rb$),
|
82
83
|
:main => nil,
|
83
84
|
:dir => 'doc',
|
@@ -123,9 +124,7 @@ import(*rakefiles)
|
|
123
124
|
%w(lib ext).each {|dir| PROJ.libs << dir if test ?d, dir}
|
124
125
|
|
125
126
|
# Setup some constants
|
126
|
-
|
127
|
-
|
128
|
-
DEV_NULL = WIN32 ? 'NUL:' : '/dev/null'
|
127
|
+
DEV_NULL = File.exist?('/dev/null') ? '/dev/null' : 'NUL:'
|
129
128
|
|
130
129
|
def quiet( &block )
|
131
130
|
io = [STDOUT.dup, STDERR.dup]
|
@@ -138,21 +137,15 @@ ensure
|
|
138
137
|
$stdout, $stderr = STDOUT, STDERR
|
139
138
|
end
|
140
139
|
|
141
|
-
DIFF = if
|
142
|
-
else
|
143
|
-
if quiet {system "gdiff", __FILE__, __FILE__} then 'gdiff'
|
144
|
-
else 'diff' end
|
145
|
-
end unless defined? DIFF
|
140
|
+
DIFF = if system("gdiff '#{__FILE__}' '#{__FILE__}' > #{DEV_NULL} 2>&1") then 'gdiff'
|
141
|
+
else 'diff' end unless defined? DIFF
|
146
142
|
|
147
|
-
SUDO = if
|
148
|
-
else
|
149
|
-
if quiet {system 'which sudo'} then 'sudo'
|
150
|
-
else '' end
|
151
|
-
end
|
143
|
+
SUDO = if system("which sudo > #{DEV_NULL} 2>&1") then 'sudo'
|
144
|
+
else '' end unless defined? SUDO
|
152
145
|
|
153
|
-
RCOV =
|
154
|
-
RDOC =
|
155
|
-
GEM =
|
146
|
+
RCOV = "#{RUBY} -S rcov"
|
147
|
+
RDOC = "#{RUBY} -S rdoc"
|
148
|
+
GEM = "#{RUBY} -S gem"
|
156
149
|
|
157
150
|
%w(rcov spec/rake/spectask rubyforge bones facets/ansicode).each do |lib|
|
158
151
|
begin
|
@@ -254,9 +247,29 @@ end
|
|
254
247
|
# Scans the current working directory and creates a list of files that are
|
255
248
|
# candidates to be in the manifest.
|
256
249
|
#
|
257
|
-
def
|
250
|
+
def manifest
|
258
251
|
files = []
|
259
|
-
exclude =
|
252
|
+
exclude = PROJ.exclude.dup
|
253
|
+
comment = %r/^\s*#/
|
254
|
+
|
255
|
+
# process the ignore file and add the items there to the exclude list
|
256
|
+
if test(?f, PROJ.ignore_file)
|
257
|
+
ary = []
|
258
|
+
File.readlines(PROJ.ignore_file).each do |line|
|
259
|
+
next if line =~ comment
|
260
|
+
line.chomp!
|
261
|
+
line.strip!
|
262
|
+
next if line.nil? or line.empty?
|
263
|
+
|
264
|
+
glob = line =~ %r/\*\./ ? File.join('**', line) : line
|
265
|
+
Dir.glob(glob).each {|fn| ary << "^#{Regexp.escape(fn)}"}
|
266
|
+
end
|
267
|
+
exclude.concat ary
|
268
|
+
end
|
269
|
+
|
270
|
+
# generate a regular expression from the exclude list
|
271
|
+
exclude = Regexp.new(exclude.join('|'))
|
272
|
+
|
260
273
|
Find.find '.' do |path|
|
261
274
|
path.sub! %r/^(\.\/|\/)/o, ''
|
262
275
|
next unless test ?f, path
|
@@ -2,93 +2,93 @@
|
|
2
2
|
標題 Re: [PSC] variants timer
|
3
3
|
時間 2008/03/04 Tue 00:34:54
|
4
4
|
<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>
|
5
|
-
<a href="<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>"
|
6
|
-
測試</a
|
7
|
-
<a href="<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>"
|
8
|
-
<img src="<a href="http://phpbb.godfat.org/templates/subSilver/images/logo_phpBB.gif" title="http://phpbb.godfat.org/templates/subSilver/images/logo_phpBB.gif">http://phpbb.godfat.org/templates/subSilver/images/logo_phpBB.gif</a>"
|
5
|
+
<a href="<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>">
|
6
|
+
測試</a>
|
7
|
+
<a href="<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>">
|
8
|
+
<img src="<a href="http://phpbb.godfat.org/templates/subSilver/images/logo_phpBB.gif" title="http://phpbb.godfat.org/templates/subSilver/images/logo_phpBB.gif">http://phpbb.godfat.org/templates/subSilver/images/logo_phpBB.gif</a>"/></a>
|
9
9
|
※ 引述《godfat (godfat 真常)》之銘言:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
以上 A, B, C 是指 timer_subscriber_list<A
|
20
|
-
|
21
|
-
這個東西會需要從 T
|
10
|
+
> 3. tuple + traits, 也就是一堆 template 技巧了
|
11
|
+
> class Dispatcher{
|
12
|
+
> template <class T>
|
13
|
+
> void sub(shared_ptr<T> p){
|
14
|
+
> get_tuple_data_field_by_type<T>(data).push_back(p);
|
15
|
+
> }
|
16
|
+
> tuple<A, B, C> data;
|
17
|
+
> };
|
18
|
+
|
19
|
+
以上 A, B, C 是指 timer_subscriber_list<A>, etc.
|
20
|
+
|
21
|
+
這個東西會需要從 T => tuple index 的 mapping
|
22
22
|
現在這部份做完了...........(template 沒忘太多啊哈哈)
|
23
23
|
|
24
|
-
#include <tr1/tuple
|
25
|
-
#include <tr1/type_traits
|
26
|
-
#include <iostream
|
24
|
+
#include <tr1/tuple>
|
25
|
+
#include <tr1/type_traits>
|
26
|
+
#include <iostream>
|
27
27
|
|
28
28
|
using namespace std::tr1;
|
29
29
|
|
30
30
|
// 拿來判斷兩個整數是否相同,這是為了檢查有沒有爆表
|
31
|
-
// 像是 tuple_element<3, tuple<int,int,int
|
31
|
+
// 像是 tuple_element<3, tuple<int,int,int> >::type
|
32
32
|
// 這樣就是爆表,因為這 tuple 沒這麼大
|
33
|
-
template <bool
|
34
|
-
template <
|
33
|
+
template <bool> struct is_equal_type { typedef true_type type; };
|
34
|
+
template <> struct is_equal_type<false>{ typedef false_type type; };
|
35
35
|
|
36
|
-
// 定義相等的話,is_equal<1,1
|
37
|
-
// is_equal<1,2
|
36
|
+
// 定義相等的話,is_equal<1,1>::value 會是 1
|
37
|
+
// is_equal<1,2>::value 會是 0
|
38
38
|
// ::type 會是 true_type/false_type (from tr1)
|
39
|
-
template <int Lhs, int Rhs
|
39
|
+
template <int Lhs, int Rhs> struct is_equal{
|
40
40
|
enum{ value = Lhs == Rhs };
|
41
|
-
typedef typename is_equal_type<value
|
41
|
+
typedef typename is_equal_type<value>::type type;
|
42
42
|
};
|
43
43
|
|
44
|
-
template <class T, class Tuple, int Index
|
44
|
+
template <class T, class Tuple, int Index> struct type_index_imp;
|
45
45
|
|
46
46
|
// 如果跑到這裡,表示爆表了,在我的 g++4.3 上會顯示:
|
47
47
|
// tuple.cpp:20: error: ‘type_not_found’ is not a member of "T"
|
48
|
-
template <class T, class Tuple, int Index, class Bool
|
48
|
+
template <class T, class Tuple, int Index, class Bool>
|
49
49
|
struct type_index_check{
|
50
50
|
enum{ value = T::type_not_found };
|
51
51
|
};
|
52
52
|
|
53
53
|
// 沒有爆表就繼續找吧
|
54
|
-
template <class T, class Tuple, int Index
|
55
|
-
struct type_index_check<T, Tuple, Index, false_type
|
56
|
-
enum{ value = type_index_imp<T, Tuple, Index+1
|
54
|
+
template <class T, class Tuple, int Index>
|
55
|
+
struct type_index_check<T, Tuple, Index, false_type>{
|
56
|
+
enum{ value = type_index_imp<T, Tuple, Index+1>::value };
|
57
57
|
};
|
58
58
|
|
59
59
|
// 找到了!
|
60
|
-
template <class T, class Tuple, int Index, class Bool
|
60
|
+
template <class T, class Tuple, int Index, class Bool>
|
61
61
|
struct type_index_if{
|
62
62
|
enum{ value = Index }; // found, stop recursion
|
63
63
|
};
|
64
64
|
|
65
65
|
// 不直接呼叫 imp, 呼叫 check 檢查是否爆表
|
66
|
-
template <class T, class Tuple, int Index
|
67
|
-
struct type_index_if<T, Tuple, Index, false_type
|
66
|
+
template <class T, class Tuple, int Index>
|
67
|
+
struct type_index_if<T, Tuple, Index, false_type>{
|
68
68
|
enum{ value = type_index_check<T, Tuple, Index,
|
69
|
-
typename is_equal<Index+1, tuple_size<Tuple
|
69
|
+
typename is_equal<Index+1, tuple_size<Tuple>::value>::type>::value };
|
70
70
|
};
|
71
71
|
|
72
72
|
// 檢查兩個型別是否相同
|
73
|
-
template <class T, class Tuple, int Index
|
73
|
+
template <class T, class Tuple, int Index>
|
74
74
|
struct type_index_imp{
|
75
75
|
enum{ value = type_index_if<T, Tuple, Index,
|
76
|
-
typename is_same<T, typename tuple_element<Index, Tuple
|
76
|
+
typename is_same<T, typename tuple_element<Index, Tuple>::type>::type>::value };
|
77
77
|
};
|
78
78
|
|
79
79
|
// simple wrapper
|
80
|
-
template <class T, class Tuple
|
80
|
+
template <class T, class Tuple>
|
81
81
|
struct type_index{
|
82
|
-
enum{ value = type_index_imp<T, Tuple, 0
|
82
|
+
enum{ value = type_index_imp<T, Tuple, 0>::value };
|
83
83
|
};
|
84
84
|
|
85
85
|
int main(){
|
86
|
-
typedef tuple<int, char, void
|
87
|
-
std::cout << type_index<int, test_t
|
88
|
-
std::cout << type_index<char, test_t
|
89
|
-
std::cout << type_index<void, test_t
|
90
|
-
std::cout << tuple_size<test_t
|
91
|
-
// std::cout << type_index<int*, test_t
|
86
|
+
typedef tuple<int, char, void> test_t;
|
87
|
+
std::cout << type_index<int, test_t>::value << std::endl;
|
88
|
+
std::cout << type_index<char, test_t>::value << std::endl;
|
89
|
+
std::cout << type_index<void, test_t>::value << std::endl;
|
90
|
+
std::cout << tuple_size<test_t>::value << std::endl;
|
91
|
+
// std::cout << type_index<int*, test_t>::value << std::endl;
|
92
92
|
}
|
93
93
|
|
94
94
|
輸出:
|
@@ -105,4 +105,4 @@ tuple.cpp:20: error: "type_not_found" is not a member of "T"
|
|
105
105
|
|
106
106
|
--
|
107
107
|
※ Orign: 群星的眷屬 chance.twbbs.org
|
108
|
-
◆ Author: godfat From 220-135-28-18.HINET-IP.hinet.net</pre><br /><br />end of article...<br />
|
108
|
+
◆ Author: godfat From 220-135-28-18.HINET-IP.hinet.net</pre><br /><br />end of article...<br />
|
@@ -1,17 +1,23 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
-
|
5
|
-
|
4
|
+
|
5
|
+
TestCase = begin
|
6
|
+
require 'minitest/unit'
|
7
|
+
MiniTest::Unit.autorun
|
8
|
+
MiniTest::Unit::TestCase
|
9
|
+
rescue LoadError
|
10
|
+
require 'test/unit'
|
11
|
+
Test::Unit::TestCase
|
12
|
+
end
|
6
13
|
|
7
14
|
require 'friendly_format'
|
8
15
|
|
9
|
-
|
10
|
-
class TestFriendlyFormat < MiniTest::Unit::TestCase
|
16
|
+
module TestCases
|
11
17
|
include FriendlyFormat
|
12
18
|
|
13
19
|
def test_article
|
14
|
-
str =
|
20
|
+
str =
|
15
21
|
' http://friends.roodo.com/forum/viewTopic/10170
|
16
22
|
用 Haskell 寫成的名軟體?
|
17
23
|
|
@@ -37,7 +43,9 @@ OpenGL, 還有一些 web cgi 之類的東西也有。
|
|
37
43
|
|
38
44
|
現在切入正是時機啊... XD'
|
39
45
|
|
40
|
-
|
46
|
+
s = format_autolink(str)
|
47
|
+
|
48
|
+
assert(
|
41
49
|
' <a href="http://friends.roodo.com/forum/viewTopic/10170" title="http://friends.roodo.com/forum/viewTopic/10170">http://friends.roodo.com/forum/viewTopic/10170</a>
|
42
50
|
用 Haskell 寫成的名軟體?
|
43
51
|
|
@@ -61,29 +69,43 @@ svn 其實也差不多是要慢慢式微了...
|
|
61
69
|
很多知名 library 都有 haskell binding 了,wxWidgets,
|
62
70
|
OpenGL, 還有一些 web cgi 之類的東西也有。
|
63
71
|
|
64
|
-
現在切入正是時機啊... XD'
|
65
|
-
assert_equal
|
72
|
+
現在切入正是時機啊... XD' == s)
|
73
|
+
assert_equal(s, format_autolink_regexp(str))
|
66
74
|
end
|
67
75
|
def test_persent
|
68
76
|
str =
|
69
77
|
'XDDDD
|
70
78
|
http://www.amazon.co.jp/%E3%80%8C%E7%84%94~%E3%83%9B%E3%83%A0%E3%83%A9%E3%80%8D~Ar-tonelico2-hymmnos-concert-Side-%E7%B4%85~/dp/B000VKZL30/ref=pd_sbs_sw_img_2 orz'
|
71
79
|
|
72
|
-
|
80
|
+
s = format_autolink(str)
|
81
|
+
|
82
|
+
assert_equal(
|
73
83
|
'XDDDD
|
74
|
-
<a href="http://www.amazon.co.jp/%E3%80%8C%E7%84%94~%E3%83%9B%E3%83%A0%E3%83%A9%E3%80%8D~Ar-tonelico2-hymmnos-concert-Side-%E7%B4%85~/dp/B000VKZL30/ref=pd_sbs_sw_img_2" title="http://www.amazon.co.jp/%E3%80%8C%E7%84%94~%E3%83%9B%E3%83%A0%E3%83%A9%E3%80%8D~Ar-tonelico2-hymmnos-concert-Side-%E7%B4%85~/dp/B000VKZL30/ref=pd_sbs_sw_img_2">http://www.amazon.co.jp/%E3%80%8C%E7%84%94~%E3%83%9B%E3%83%A0%E3%83%A9%E...</a> orz', s
|
84
|
+
<a href="http://www.amazon.co.jp/%E3%80%8C%E7%84%94~%E3%83%9B%E3%83%A0%E3%83%A9%E3%80%8D~Ar-tonelico2-hymmnos-concert-Side-%E7%B4%85~/dp/B000VKZL30/ref=pd_sbs_sw_img_2" title="http://www.amazon.co.jp/%E3%80%8C%E7%84%94~%E3%83%9B%E3%83%A0%E3%83%A9%E3%80%8D~Ar-tonelico2-hymmnos-concert-Side-%E7%B4%85~/dp/B000VKZL30/ref=pd_sbs_sw_img_2">http://www.amazon.co.jp/%E3%80%8C%E7%84%94~%E3%83%9B%E3%83%A0%E3%83%A9%E...</a> orz', s)
|
75
85
|
assert_equal s, format_autolink_regexp(str)
|
76
86
|
end
|
77
87
|
def test_img_src
|
78
|
-
str =
|
88
|
+
str =
|
79
89
|
'Thirst for Knowledge
|
80
90
|
<img src="http://friends.roodo.com/images/diary_photos_large/15386/MjMyNjYtdGhpcnN0X2Zvcl9rbm93bGVkZ2U=.jpg" />
|
81
91
|
|
82
92
|
2007年12月14日
|
83
93
|
'
|
84
|
-
|
85
|
-
|
94
|
+
libxml =
|
95
|
+
'Thirst for Knowledge
|
96
|
+
<img src="http://friends.roodo.com/images/diary_photos_large/15386/MjMyNjYtdGhpcnN0X2Zvcl9rbm93bGVkZ2U=.jpg"/>
|
97
|
+
|
98
|
+
2007年12月14日
|
99
|
+
'
|
100
|
+
s = format_autolink(str)
|
101
|
+
if FriendlyFormat.adapter == FriendlyFormat::LibxmlAdapter
|
102
|
+
assert_equal(libxml, s)
|
103
|
+
else
|
104
|
+
assert_equal(str, s)
|
105
|
+
end
|
106
|
+
assert_equal(str, format_autolink_regexp(str))
|
86
107
|
end
|
108
|
+
|
87
109
|
def test_wikipedia_persent
|
88
110
|
str = 'http://en.wikipedia.org/wiki/Haskell_%28programming_language%29'
|
89
111
|
assert_equal \
|
@@ -111,14 +133,20 @@ http://www.amazon.co.jp/%E3%80%8C%E7%84%94~%E3%83%9B%E3%83%A0%E3%83%A9%E3%80%8D~
|
|
111
133
|
def test_escape_html_and_correct_html
|
112
134
|
str = 'test<p>if missing end of p'
|
113
135
|
assert_equal 'test<p>if missing end of p</p>', format_article(str, :p)
|
114
|
-
assert_equal 'test<p
|
136
|
+
assert_equal 'test<p>if missing end of p</p>', format_article(str, :a)
|
137
|
+
|
115
138
|
str = '<pre>asdasd<a>orz'
|
116
|
-
assert_equal '<pre>asdasd<a
|
117
|
-
assert_equal '<pre
|
118
|
-
assert_equal '<pre>asdasd<a
|
139
|
+
assert_equal '<pre>asdasd<a>orz</pre>', format_article(str, :a, :pre)
|
140
|
+
assert_equal '<pre>asdasd<a>orz</a></pre>', format_article(str, :a)
|
141
|
+
assert_equal '<pre>asdasd<a>orz</pre>', format_article(str, :pre)
|
142
|
+
|
119
143
|
str = 'orz<img>asd'
|
120
|
-
|
121
|
-
|
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<img>asd', format_article(str)
|
122
150
|
end
|
123
151
|
def test_trim_url
|
124
152
|
str = 'test with http://890123456789012345678901234567890123456789012345678901234567890123456789.com'
|
@@ -127,17 +155,25 @@ http://www.amazon.co.jp/%E3%80%8C%E7%84%94~%E3%83%9B%E3%83%A0%E3%83%A9%E3%80%8D~
|
|
127
155
|
assert_equal s, format_autolink_regexp(str)
|
128
156
|
end
|
129
157
|
def test_escape_html
|
130
|
-
|
131
|
-
|
158
|
+
str = 'a lambda expression is λ x. x+1'
|
159
|
+
libxml = 'a lambda expression is λ x. x+1'
|
160
|
+
result = format_article(str)
|
161
|
+
|
162
|
+
if FriendlyFormat.adapter == FriendlyFormat::HpricotAdapter
|
163
|
+
assert_equal(str, result)
|
164
|
+
else
|
165
|
+
assert_equal(libxml, result)
|
166
|
+
end
|
167
|
+
|
132
168
|
str = 'as you can see, use <img src="asd"/> to use'
|
133
169
|
assert_equal str, format_article(str)
|
134
170
|
end
|
135
171
|
def test_html_with_pre_and_newline2br
|
136
|
-
result = File.read('test/sample/complex_article_result.txt')
|
172
|
+
result = File.read('test/sample/complex_article_result.txt').chop
|
137
173
|
input = File.read('test/sample/complex_article.txt')
|
138
174
|
|
139
|
-
assert_equal
|
140
|
-
assert_equal
|
175
|
+
assert_equal(result, format_article(input, :pre))
|
176
|
+
assert_equal(result, format_article(input, SetCommon.new))
|
141
177
|
end
|
142
178
|
def test_simple_link
|
143
179
|
s = '今天是我一歲生日 <a href="http://godfat.org/" title="http://godfat.org/">http://godfat.org/</a> 真的嗎?'
|
@@ -160,9 +196,39 @@ compilation mode. 非常驚人的開發速度。
|
|
160
196
|
此外,其中一位開發者,<a href="http://blog.headius.com/">Charles Nutter</a> 也經常參與 <a href="http://www.ruby-forum.com/forum/14">ruby-core</a> 的討論,
|
161
197
|
對於 Ruby 的開發頗有貢獻。'
|
162
198
|
|
163
|
-
expected = '<img src="http://flolac.iis.sinica.edu.tw/lambdawan/sites/default/files/ruby.png.thumb.jpg"
|
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><xd><br />此外,其中一位開發者,<a href="http://blog.headius.com/">Charles Nutter</a> 也經常參與 <a href="http://www.ruby-forum.com/forum/14">ruby-core</a> 的討論,<br />對於 Ruby 的開發頗有貢獻。</xd></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><xd><br />此外,其中一位開發者,<a href="http://blog.headius.com/">Charles Nutter</a> 也經常參與 <a href="http://www.ruby-forum.com/forum/14">ruby-core</a> 的討論,<br />對於 Ruby 的開發頗有貢獻。</xd></zzz>'
|
203
|
+
|
204
|
+
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
|
210
|
+
end
|
164
211
|
|
165
|
-
|
212
|
+
def test_empty_article
|
213
|
+
assert_equal '', format_article('')
|
214
|
+
assert_equal ' ', format_article(' ')
|
215
|
+
assert_equal 'a', format_article('a')
|
216
|
+
end
|
166
217
|
|
218
|
+
def test_custom_set
|
219
|
+
s = '<z>zzz</z>'
|
220
|
+
assert_equal s, format_article(s, Set.new << :z)
|
167
221
|
end
|
168
222
|
end
|
223
|
+
|
224
|
+
%w[HpricotAdapter NokogiriAdapter LibxmlAdapter].each{ |adapter|
|
225
|
+
eval <<-RUBY
|
226
|
+
class Test#{adapter} < TestCase
|
227
|
+
include TestCases
|
228
|
+
|
229
|
+
def setup
|
230
|
+
FriendlyFormat.adapter = FriendlyFormat::#{adapter}
|
231
|
+
end
|
232
|
+
end
|
233
|
+
RUBY
|
234
|
+
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: friendly_format
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Lin Jen-Shin (a.k.a. godfat \xE7\x9C\x9F\xE5\xB8\xB8)"
|
@@ -9,38 +9,48 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-04-05 00:00:00 +08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: bones
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.4.2
|
24
|
+
version:
|
15
25
|
- !ruby/object:Gem::Dependency
|
16
26
|
name: hpricot
|
17
|
-
type: :
|
27
|
+
type: :development
|
18
28
|
version_requirement:
|
19
29
|
version_requirements: !ruby/object:Gem::Requirement
|
20
30
|
requirements:
|
21
31
|
- - ">="
|
22
32
|
- !ruby/object:Gem::Version
|
23
|
-
version: 0.6
|
33
|
+
version: "0.6"
|
24
34
|
version:
|
25
35
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
36
|
+
name: nokogiri
|
27
37
|
type: :development
|
28
38
|
version_requirement:
|
29
39
|
version_requirements: !ruby/object:Gem::Requirement
|
30
40
|
requirements:
|
31
41
|
- - ">="
|
32
42
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
43
|
+
version: "1.1"
|
34
44
|
version:
|
35
45
|
- !ruby/object:Gem::Dependency
|
36
|
-
name:
|
46
|
+
name: libxml-ruby
|
37
47
|
type: :development
|
38
48
|
version_requirement:
|
39
49
|
version_requirements: !ruby/object:Gem::Requirement
|
40
50
|
requirements:
|
41
51
|
- - ">="
|
42
52
|
- !ruby/object:Gem::Version
|
43
|
-
version:
|
53
|
+
version: "0.9"
|
44
54
|
version:
|
45
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.
|
46
56
|
email: godfat (XD) godfat.org
|
@@ -64,6 +74,10 @@ files:
|
|
64
74
|
- TODO
|
65
75
|
- friendly_format.gemspec
|
66
76
|
- lib/friendly_format.rb
|
77
|
+
- lib/friendly_format/adapter/abstract.rb
|
78
|
+
- lib/friendly_format/adapter/hpricot_adapter.rb
|
79
|
+
- lib/friendly_format/adapter/libxml_adapter.rb
|
80
|
+
- lib/friendly_format/adapter/nokogiri_adapter.rb
|
67
81
|
- lib/friendly_format/set_common.rb
|
68
82
|
- lib/friendly_format/set_strict.rb
|
69
83
|
- lib/friendly_format/version.rb
|
@@ -71,7 +85,6 @@ files:
|
|
71
85
|
- tasks/bones.rake
|
72
86
|
- tasks/gem.rake
|
73
87
|
- tasks/git.rake
|
74
|
-
- tasks/manifest.rake
|
75
88
|
- tasks/notes.rake
|
76
89
|
- tasks/post_load.rake
|
77
90
|
- tasks/rdoc.rake
|
@@ -87,7 +100,6 @@ has_rdoc: true
|
|
87
100
|
homepage: http://github.com/godfat/friendly_format
|
88
101
|
post_install_message:
|
89
102
|
rdoc_options:
|
90
|
-
- --diagram
|
91
103
|
- --charset=utf-8
|
92
104
|
- --inline-source
|
93
105
|
- --line-numbers
|