tdiary 4.0.2 → 4.0.2.20140201

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/Gemfile +8 -7
  4. data/Gemfile.lock +17 -15
  5. data/config.ru +0 -2
  6. data/doc/INSTALL-paas.md +17 -5
  7. data/misc/plugin/amazon/amazonimg.rb +1 -1
  8. data/misc/plugin/category.rb +7 -7
  9. data/misc/plugin/image.rb +4 -1
  10. data/misc/plugin/search-default.rb +269 -0
  11. data/misc/theme_convert/theme_convert.rb +3 -3
  12. data/plugin/50sp.rb +3 -2
  13. data/spec/acceptance/append_comment_spec.rb +8 -8
  14. data/spec/acceptance/append_diary_spec.rb +9 -9
  15. data/spec/acceptance/save_conf_comment_spec.rb +7 -7
  16. data/spec/acceptance/save_conf_default_spec.rb +31 -31
  17. data/spec/acceptance/save_conf_dnsbl_spec.rb +28 -28
  18. data/spec/acceptance/save_conf_referer_spec.rb +6 -6
  19. data/spec/acceptance/save_conf_security_spec.rb +37 -37
  20. data/spec/acceptance/support/helpers.rb +8 -8
  21. data/spec/acceptance/update_diary_spec.rb +21 -21
  22. data/spec/acceptance/view_category_spec.rb +5 -5
  23. data/spec/acceptance/view_comment_spec.rb +6 -6
  24. data/spec/acceptance/view_diary_spec.rb +12 -12
  25. data/spec/acceptance/view_referer_spec.rb +3 -3
  26. data/spec/acceptance_helper.rb +2 -2
  27. data/spec/core/configuration_spec.rb +1 -1
  28. data/spec/core/io/default_spec.rb +30 -2
  29. data/spec/core/plugin_spec.rb +1 -1
  30. data/tdiary/application/configuration.rb +0 -1
  31. data/tdiary/application/extensions/omniauth.rb +1 -1
  32. data/tdiary/application.rb +6 -9
  33. data/tdiary/cli.rb +6 -6
  34. data/tdiary/configuration.rb +2 -2
  35. data/tdiary/extensions/core.rb +18 -0
  36. data/tdiary/extensions.rb +6 -0
  37. data/tdiary/io/base.rb +11 -7
  38. data/tdiary/lang/ja.rb +2 -2
  39. data/tdiary/server.rb +1 -1
  40. data/tdiary/version.rb +1 -1
  41. data/tdiary.rb +2 -1
  42. data/test/test_plugin_helper.rb +54 -10
  43. data/test/test_plugin_helper_test.rb +27 -5
  44. data/test/weather_test.rb +26 -22
  45. data/tmp/.gitkeep +0 -0
  46. metadata +7 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e3b1d5ff9c5be93ee04e88c9d5e1a1894e7e42dd
4
- data.tar.gz: dc3abc8a1d49859c4db89e70c1f84c34d8176227
3
+ metadata.gz: 3c52de43dc119883d82cc39f570b3b2f5999b96d
4
+ data.tar.gz: 517e13ad91be78f16ae61c3d4fd678d9d29e327c
5
5
  SHA512:
6
- metadata.gz: a4fd13995035a6a6ac9a4a62cee6fdd567d9c0d5a4c3fbe88368d7ba082bc339dc918149164a2dc9fc0824ed1e8a63f9cc378a69b322f32ebab6832288811ab5
7
- data.tar.gz: 5b7c08feb7f14e2cd6b002cd7a5105dcb6dde0d8b3278a11f8f22736ad6f54e39eb657b99b0467135c0b0faa1fbf7ecaebec4852aa3a48206019b3065b3c329e
6
+ metadata.gz: 857ecaf2c9a4466f323710df41d0341dbb19bb02332c96ede67ec6f5966d20e25de11215ac3d7dbea86df89e6f6ffce2c3dc1fc2f0fd6569f36efd483833e897
7
+ data.tar.gz: f60cfac1eec83552533d86cf30b4ce6468470eb54d2009570afd70903c51807b259fc386cf77e78a89b78dbab5ae45ad0d503fc1509145afd0ca01a913939b4d
data/.travis.yml CHANGED
@@ -6,6 +6,8 @@ rvm:
6
6
  - 1.9.3
7
7
  - 2.0.0
8
8
 
9
+ cache: bundler
10
+
9
11
  # ignored --deployment option
10
12
  bundler_args: ""
11
13
 
data/Gemfile CHANGED
@@ -21,23 +21,24 @@ group :server do
21
21
  end
22
22
 
23
23
  group :development do
24
- gem 'pit', :require => false
25
- gem 'racksh', :require => false
24
+ gem 'pit', require: false
25
+ gem 'racksh', require: false
26
26
  gem 'rake'
27
+ gem 'redcarpet'
27
28
 
28
29
  group :test do
29
30
  gem 'pry'
30
31
  gem 'tapp'
31
- gem 'test-unit', :require => 'test/unit'
32
+ gem 'test-unit', require: 'test/unit'
32
33
  gem 'rspec'
33
- gem 'capybara', :require => 'capybara/rspec'
34
+ gem 'capybara', require: 'capybara/rspec'
34
35
  gem 'selenium-webdriver'
35
36
  gem 'launchy'
36
37
  gem 'sequel'
37
38
  gem 'sqlite3'
38
- gem 'jasmine'
39
- gem 'simplecov', :require => false
40
- gem 'coveralls', :require => false
39
+ gem 'jasmine', '~> 1.3'
40
+ gem 'simplecov', require: false
41
+ gem 'coveralls', require: false
41
42
  end
42
43
  end
43
44
 
data/Gemfile.lock CHANGED
@@ -2,19 +2,19 @@ GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
4
  addressable (2.3.5)
5
- capybara (2.2.0)
5
+ capybara (2.2.1)
6
6
  mime-types (>= 1.16)
7
7
  nokogiri (>= 1.3.3)
8
8
  rack (>= 1.0.0)
9
9
  rack-test (>= 0.5.4)
10
10
  xpath (~> 2.0)
11
- childprocess (0.3.9)
11
+ childprocess (0.4.0)
12
12
  ffi (~> 1.0, >= 1.0.11)
13
13
  coderay (1.1.0)
14
14
  coffee-script (2.2.0)
15
15
  coffee-script-source
16
16
  execjs
17
- coffee-script-source (1.6.3)
17
+ coffee-script-source (1.7.0)
18
18
  coveralls (0.7.0)
19
19
  multi_json (~> 1.3)
20
20
  rest-client
@@ -23,10 +23,10 @@ GEM
23
23
  thor
24
24
  daemons (1.1.9)
25
25
  diff-lcs (1.2.5)
26
- docile (1.1.1)
26
+ docile (1.1.2)
27
27
  eventmachine (1.0.3)
28
28
  execjs (2.0.2)
29
- fastimage (1.5.4)
29
+ fastimage (1.6.0)
30
30
  addressable (~> 2.3, >= 2.3.5)
31
31
  ffi (1.9.3)
32
32
  hike (1.2.3)
@@ -41,13 +41,13 @@ GEM
41
41
  addressable (~> 2.3)
42
42
  libv8 (3.16.14.3)
43
43
  method_source (0.8.2)
44
- mime-types (2.0)
44
+ mime-types (2.1)
45
45
  mini_portile (0.5.2)
46
- multi_json (1.8.2)
47
- nokogiri (1.6.0)
46
+ multi_json (1.8.4)
47
+ nokogiri (1.6.1)
48
48
  mini_portile (~> 0.5.0)
49
49
  pit (0.0.7)
50
- pry (0.9.12.4)
50
+ pry (0.9.12.6)
51
51
  coderay (~> 1.0)
52
52
  method_source (~> 0.8)
53
53
  slop (~> 3.4)
@@ -57,7 +57,8 @@ GEM
57
57
  racksh (1.0.0)
58
58
  rack (>= 1.0)
59
59
  rack-test (>= 0.5)
60
- rake (10.1.0)
60
+ rake (10.1.1)
61
+ redcarpet (3.0.0)
61
62
  ref (1.0.5)
62
63
  rest-client (1.6.7)
63
64
  mime-types (>= 1.16)
@@ -69,13 +70,13 @@ GEM
69
70
  rspec-expectations (2.14.4)
70
71
  diff-lcs (>= 1.1.3, < 2.0)
71
72
  rspec-mocks (2.14.4)
72
- rubyzip (1.0.0)
73
- selenium-webdriver (2.37.0)
73
+ rubyzip (1.1.0)
74
+ selenium-webdriver (2.39.0)
74
75
  childprocess (>= 0.2.5)
75
76
  multi_json (~> 1.0)
76
- rubyzip (~> 1.0.0)
77
+ rubyzip (~> 1.0)
77
78
  websocket (~> 1.0.4)
78
- sequel (4.4.0)
79
+ sequel (4.6.0)
79
80
  simplecov (0.8.2)
80
81
  docile (~> 1.1.0)
81
82
  multi_json
@@ -116,13 +117,14 @@ DEPENDENCIES
116
117
  coveralls
117
118
  fastimage
118
119
  hikidoc
119
- jasmine
120
+ jasmine (~> 1.3)
120
121
  launchy
121
122
  pit
122
123
  pry
123
124
  rack
124
125
  racksh
125
126
  rake
127
+ redcarpet
126
128
  rspec
127
129
  selenium-webdriver
128
130
  sequel
data/config.ru CHANGED
@@ -1,6 +1,4 @@
1
1
  $:.unshift( File::dirname( __FILE__ ).untaint )
2
- require 'tdiary'
3
- require 'tdiary/environment'
4
2
  require 'tdiary/application'
5
3
 
6
4
  use ::Rack::Reloader unless ENV['RACK_ENV'] == 'production'
data/doc/INSTALL-paas.md CHANGED
@@ -27,10 +27,16 @@ tDiary の最新版を取得します。
27
27
  git clone git://github.com/tdiary/tdiary-core.git
28
28
  ```
29
29
 
30
- heroku コマンドを用いて Heroku でアプリケーションを作成します。なお、Heroku のアカウント作成方法は本ドキュメントでは省略します。tDiary のルートディレクトリ(Gemfile が存在する箇所) で以下のコマンドを実行します。
30
+ 続いて、依存するライブラリをインストールするために bundle install コマンドを実行します。
31
31
 
32
32
  ```
33
33
  % cd tdiary-core
34
+ % bundle install
35
+ ```
36
+
37
+ heroku コマンドを用いて Heroku でアプリケーションを作成します。なお、Heroku のアカウント作成方法は本ドキュメントでは省略します。tDiary のルートディレクトリ(Gemfile が存在する箇所) で以下のコマンドを実行します。
38
+
39
+ ```
34
40
  % heroku apps:create [アプリケーション名]
35
41
  ```
36
42
 
@@ -51,7 +57,7 @@ heroku コマンドを用いて Heroku でアプリケーションを作成し
51
57
  日記更新時に必要となるユーザー名とパスワードを保存する .htpasswd ファイルを作成します。この情報は重要なので、外部には公開しないでください。
52
58
 
53
59
  ```
54
- % rake auth:password:create
60
+ % bundle exec rake auth:password:create
55
61
  ```
56
62
 
57
63
  ここまでの変更内容を deploy ブランチにコミットし、Heroku にアプリケーションを転送します。
@@ -73,10 +79,16 @@ tDiary の最新版を取得します。
73
79
  git clone git://github.com/tdiary/tdiary-core.git
74
80
  ```
75
81
 
76
- sqale.jp にアクセスして新しいアプリケーションを作成します。作成後にアプリケーションの URL を git のリモートリポジトリに追加します。tDiary のルートディレクトリ(Gemfile が存在する箇所) で以下のコマンドを実行します。
82
+ 続いて、依存するライブラリをインストールするために bundle install コマンドを実行します。
77
83
 
78
84
  ```
79
85
  % cd tdiary-core
86
+ % bundle install
87
+ ```
88
+
89
+ sqale.jp にアクセスして新しいアプリケーションを作成します。作成後にアプリケーションの URL を git のリモートリポジトリに追加します。tDiary のルートディレクトリ(Gemfile が存在する箇所) で以下のコマンドを実行します。
90
+
91
+ ```
80
92
  % git remote add sqale ssh://sqale@gateway.sqale.jp:2222/[username]/[application].git
81
93
  ```
82
94
 
@@ -97,7 +109,7 @@ username と application の値は別途読み替えてください。続いて
97
109
  日記更新時に必要となるユーザー名とパスワードを保存する .htpasswd ファイルを作成します。この情報は重要なので、外部には公開しないでください。
98
110
 
99
111
  ```
100
- % rake auth:password:create
112
+ % bundle exec rake auth:password:create
101
113
  ```
102
114
 
103
115
  dot.env ファイルを .env にリネームして、データベースの接続情報を記入します。データベースの接続情報は sqale のアプリケーションダッシュボードから参照してください。接続情報は以下の形式で記入します。
@@ -109,7 +121,7 @@ DATABASE_URL=mysql2://username:password@hostname/database
109
121
  sqale では javascript や css ファイルを作業ディレクトリの public/assets 配下に置く必要があります。以下のコマンドを実行して対象のファイルをコピーしてください。
110
122
 
111
123
  ```
112
- rake assets:copy
124
+ % bundle exec rake assets:copy
113
125
  ```
114
126
 
115
127
  ここまでの変更内容を deploy ブランチにコミットし、Heroku にアプリケーションを転送します。
@@ -66,7 +66,7 @@ def amazon_call_ecs( asin, country = nil )
66
66
  url << "&Version=#{@amazon_require_version}"
67
67
 
68
68
  timeout( 10 ) do
69
- open( url, :proxy => @proxy ) {|f| f.read}
69
+ open( url, proxy: @proxy ) {|f| f.read}
70
70
  end
71
71
  end
72
72
 
@@ -78,8 +78,8 @@ def category_navi
78
78
  result = ''
79
79
  case mode
80
80
  when :year, :half, :quarter, :month
81
- all_diary = Category::Info.new(@cgi, @years, @conf, :year => -1, :month => -1)
82
- all = Category::Info.new(@cgi, @years, @conf, :category => ['ALL'], :year => -1, :month => -1)
81
+ all_diary = Category::Info.new(@cgi, @years, @conf, year: -1, month: -1)
82
+ all = Category::Info.new(@cgi, @years, @conf, category: ['ALL'], year: -1, month: -1)
83
83
  result << category_navi_anchor(info.prev, @conf['category.prev_' + mode.to_s], mobile)
84
84
  result << category_navi_anchor(info.next, @conf['category.next_' + mode.to_s], mobile)
85
85
  unless mobile then
@@ -87,17 +87,17 @@ def category_navi
87
87
  result << category_navi_anchor(all, @conf['category.all'])
88
88
  end
89
89
  when :all
90
- year = Category::Info.new(@cgi, @years, @conf, :year => Time.now.year.to_s)
91
- half = Category::Info.new(@cgi, @years, @conf, :year => Time.now.year.to_s, :month => "#{((Time.now.month - 1) / 6 + 1)}H")
92
- quarter = Category::Info.new(@cgi, @years, @conf, :year => Time.now.year.to_s, :month => "#{((Time.now.month - 1) / 3 + 1)}Q")
93
- month = Category::Info.new(@cgi, @years, @conf, :year => Time.now.year.to_s, :month => '%02d' % Time.now.month)
90
+ year = Category::Info.new(@cgi, @years, @conf, year: Time.now.year.to_s)
91
+ half = Category::Info.new(@cgi, @years, @conf, year: Time.now.year.to_s, month: "#{((Time.now.month - 1) / 6 + 1)}H")
92
+ quarter = Category::Info.new(@cgi, @years, @conf, year: Time.now.year.to_s, month: "#{((Time.now.month - 1) / 3 + 1)}Q")
93
+ month = Category::Info.new(@cgi, @years, @conf, year: Time.now.year.to_s, month: '%02d' % Time.now.month)
94
94
  result << category_navi_anchor(year, @conf['category.this_year'], mobile)
95
95
  result << category_navi_anchor(half, @conf['category.this_half'], mobile)
96
96
  result << category_navi_anchor(quarter, @conf['category.this_quarter'], mobile)
97
97
  result << category_navi_anchor(month, @conf['category.this_month'], mobile)
98
98
  end
99
99
  if !info.category.include?('ALL') and !mobile then
100
- all_category = Category::Info.new(@cgi, @years, @conf, :category => ['ALL'])
100
+ all_category = Category::Info.new(@cgi, @years, @conf, category: ['ALL'])
101
101
  result << category_navi_anchor(all_category, @conf['category.all_category'])
102
102
  end
103
103
  result
data/misc/plugin/image.rb CHANGED
@@ -120,10 +120,13 @@ end
120
120
  #
121
121
  # initialize
122
122
  #
123
- @image_dir = @options && @options['image.dir'] || './images/'
123
+ @image_dir = (@options && @options['image.dir']) || File.join(TDiary.server_root, @cgi.is_a?(RackCGI) ? 'public/images' : 'images')
124
124
  @image_dir.chop! if /\/$/ =~ @image_dir
125
+ FileUtils.mkdir_p @image_dir unless File.exist?(@image_dir)
126
+
125
127
  @image_url = @options && @options['image.url'] || "#{base_url}images/"
126
128
  @image_url.chop! if /\/$/ =~ @image_url
129
+
127
130
  @image_maxwidth = @options && @options['image.maxwidth'] || nil
128
131
 
129
132
  add_body_enter_proc do |date|
@@ -0,0 +1,269 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # search-default.rb - site search plugin sample using DefaultIO.
4
+ #
5
+ # Copyright (C) 2003-2005 Minero Aoki
6
+ # Copyright (C) 2012, TADA Tadashi <t@tdtds.jp>
7
+ # You can redistribute it and/or modify it under GPL2.
8
+ #
9
+ #
10
+
11
+ def search_title
12
+ '全文検索'
13
+ end
14
+
15
+ class WrongQuery < StandardError; end
16
+
17
+ module DefaultIOSearch
18
+
19
+ module_function
20
+ def setup_patterns(query)
21
+ patterns = split_string(query).map {|pat|
22
+ check_pattern pat
23
+ Regexp.new( Regexp.quote(pat), Regexp::IGNORECASE )
24
+ }
25
+ raise WrongQuery, 'no pattern' if patterns.empty?
26
+ raise WrongQuery, 'too many sub patterns' if patterns.length > 8
27
+ patterns
28
+ end
29
+
30
+ def check_pattern(pat)
31
+ raise WrongQuery, 'no pattern' unless pat
32
+ raise WrongQuery, 'empty pattern' if pat.empty?
33
+ raise WrongQuery, "pattern too short: #{pat}" if pat.length < 2
34
+ raise WrongQuery, 'pattern too long' if pat.length > 128
35
+ end
36
+
37
+ def split_string(str)
38
+ str.split(/[\s ]+/ou).reject {|w| w.empty? }
39
+ end
40
+
41
+ INF = 1 / 0.0
42
+
43
+ def match_components(patterns, data_path)
44
+ foreach_diary_from_latest(data_path) do |diary|
45
+ next unless diary.visible?
46
+ num = 1
47
+ diary.each_section do |sec|
48
+ if patterns.all? {|re| re =~ sec.to_src }
49
+ yield diary, fragment('p', num), sec
50
+ end
51
+ num += 1
52
+ end
53
+ diary.each_visible_comment(INF) do |cmt, num|
54
+ if patterns.all? {|re| re =~ cmt.body }
55
+ yield diary, fragment('c', num), cmt
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ def fragment(type, num)
62
+ sprintf('%s%02d', type, num)
63
+ end
64
+
65
+ #
66
+ # tDiary Implementation Dependent
67
+ #
68
+ def foreach_diary_from_latest(data_path, &block)
69
+ foreach_data_file(data_path.sub(%r</+\z>, '')) do |path|
70
+ read_diaries(path).sort_by {|diary| diary.date }.reverse_each(&block)
71
+ end
72
+ end
73
+
74
+ def foreach_data_file(data_path, &block)
75
+ Dir.glob("#{data_path}/[0-9]*/*.td2").sort.reverse_each do |path|
76
+ yield path.untaint
77
+ end
78
+ end
79
+
80
+ def read_diaries(path)
81
+ d = nil
82
+ diaries = {}
83
+ load_tdiary_textdb(path) do |header, body|
84
+ begin
85
+ d = diary_class(header['Format']).new(header['Date'], '', body)
86
+ rescue ArgumentError
87
+ next
88
+ end
89
+ d.show(header['Visible'] != 'false')
90
+ diaries[d.ymd] = d
91
+ end
92
+ (Years[d.y] ||= []).push(d.m) if d
93
+ load_comments diaries, path
94
+ diaries.values
95
+ end
96
+
97
+ DIARY_CLASS_CACHE = {}
98
+
99
+ def diary_class(style)
100
+ c = DIARY_CLASS_CACHE[style]
101
+ return c if c
102
+ if TDiary.const_defined?('Style')
103
+ require "tdiary/style/#{style.downcase}.rb"
104
+ c = eval("TDiary::Style::#{style.capitalize}Diary")
105
+ else
106
+ require "tdiary/style/#{style.downcase}_style.rb"
107
+ c = eval("TDiary::#{style.capitalize}Diary")
108
+ end
109
+ c.__send__(:include, DiaryClassDelta)
110
+ DIARY_CLASS_CACHE[style] = c
111
+ c
112
+ end
113
+
114
+ module DiaryClassDelta
115
+ def ymd
116
+ date().strftime('%Y%m%d')
117
+ end
118
+
119
+ def y_m_d
120
+ date().strftime('%Y-%m-%d')
121
+ end
122
+
123
+ def y
124
+ '%04d' % date().year
125
+ end
126
+
127
+ def m
128
+ '%02d' % date().month
129
+ end
130
+ end
131
+
132
+ def load_comments(diaries, path)
133
+ cmtfile = path.sub(/2\z/, 'c')
134
+ return unless File.file?(cmtfile)
135
+ load_tdiary_textdb(cmtfile) do |header, body|
136
+ c = TDiary::Comment.new(header['Name'], header['Mail'], body,
137
+ Time.at(header['Last-Modified'].to_i))
138
+ c.show = (header['Visible'] != 'false')
139
+ d = diaries[header['Date']]
140
+ d.add_comment c if d
141
+ end
142
+ end
143
+
144
+ def load_tdiary_textdb(path)
145
+ File.open(path) {|f|
146
+ ver = f.gets.strip
147
+ raise "unkwnown format: #{ver}" unless ver == 'TDIARY2.00.00' or ver == 'TDIARY2.01.00'
148
+ f.each('') do |header|
149
+ h = {}
150
+ header.untaint.strip.each_line do |line|
151
+ begin
152
+ n, v = *line.split(':', 2)
153
+ rescue ArgumentError
154
+ next
155
+ end
156
+ h[n.strip] = v.strip
157
+ end
158
+ body = f.gets("\n.\n").chomp(".\n").untaint
159
+ yield h, body
160
+ end
161
+ }
162
+ end
163
+
164
+ def short_html(component)
165
+ # Section classes do not have common superclass, we can't use class here.
166
+ case component.class.name
167
+ when /Section/
168
+ section = component
169
+ if section.subtitle
170
+ sprintf('%s<br>%s',
171
+ tdiary2text(section.subtitle_to_html),
172
+ tdiary2text(section.body_to_html))
173
+ else
174
+ tdiary2text(section.body_to_html)
175
+ end
176
+ when /Comment/
177
+ cmt = component
178
+ shorten(escape((cmt.name + ': ' + cmt.body)))
179
+ else
180
+ raise "must not happen: #{component.class}"
181
+ end
182
+ end
183
+
184
+ def tdiary2text(html)
185
+ re = Regexp.new('<[^>]*>', Regexp::EXTENDED)
186
+ shorten(apply_tdiary_plugins(html).gsub(re, ''))
187
+ end
188
+
189
+ Years = {}
190
+
191
+ TDiary::Plugin.__send__(:public, :apply_plugin)
192
+ def apply_tdiary_plugins(html)
193
+ #@plugin.apply_plugin(html, false)
194
+ html
195
+ end
196
+
197
+ @plugin = nil
198
+
199
+ #
200
+ # Utils
201
+ #
202
+ HTML_ESCAPE_TABLE = {
203
+ '&' => '&amp;',
204
+ '<' => '&lt;',
205
+ '>' => '&gt;',
206
+ '"' => '&quot;'
207
+ }
208
+
209
+ def escape(str)
210
+ tbl = HTML_ESCAPE_TABLE
211
+ str.gsub(/[&"<>]/) {|ch| tbl[ch] }
212
+ end
213
+
214
+ def shorten(str, len = 200)
215
+ matched = str.gsub( /\n/, ' ' ).scan( /^.{0,#{len - 3}}/u )[0]
216
+ if $'.nil? || $'.empty?
217
+ matched
218
+ else
219
+ matched + '...'
220
+ end
221
+ end
222
+ end
223
+
224
+ def search_input_form( q )
225
+ r = <<-HTML
226
+ <form method="GET" action="#{@conf.index}"><div>
227
+ 検索キーワード:
228
+ <input name="q" value="#{h q}">
229
+ <input type="submit" value="OK">
230
+ </div></form>
231
+ HTML
232
+ end
233
+
234
+ def search_result
235
+ unless @conf.io_class == (TDiary.const_defined?('DefaultIO') ? TDiary::DefaultIO : TDiary::IO::Default)
236
+ return %Q|<p class="message">could not use this plugin under #{@conf.io_class}.</p>|
237
+ end
238
+
239
+ query = CGI::unescape( @cgi.params['q'][0] )
240
+ start = CGI::unescape( @cgi.params['start'][0] || '0' ).to_i
241
+
242
+ begin
243
+ patterns = DefaultIOSearch::setup_patterns(query)
244
+ r = search_input_form( query )
245
+
246
+ r << '<dl class="search-result autopagerize_page_element">'
247
+ count = 0
248
+ too_many = false
249
+ DefaultIOSearch::match_components(patterns, @conf.data_path) do |diary, fragment, component|
250
+ count += 1
251
+ if count > 50 # TO MANY HITS
252
+ too_many = true
253
+ break
254
+ end
255
+ href = @conf.index + anchor( "#{diary.ymd}#{fragment}" )
256
+ r << %Q|<dt><a href="#{href}">#{h diary.y_m_d}</a></dt>|
257
+ r << %Q|<dd>#{DefaultIOSearch::short_html(component)}</dd>|
258
+ end
259
+ r << '</dl>'
260
+
261
+ r << '<div class="search-navi">'
262
+ r << "<p>#{too_many ? 'too many' : count} hits.</p>"
263
+ r << '</div>'
264
+
265
+ r
266
+ rescue WrongQuery
267
+ search_input_form( query ) + %Q|<p class="message">#{$!.message}</p>|
268
+ end
269
+ end
@@ -167,12 +167,12 @@ racc_goto_default = [
167
167
  racc_token_table = {
168
168
  false => 0,
169
169
  Object.new => 1,
170
- :IDENT => 2,
170
+ IDENT: 2,
171
171
  ":" => 3,
172
172
  "{" => 4,
173
173
  "}" => 5,
174
- :QUOTE => 6,
175
- :EOL => 7 }
174
+ QUOTE: 6,
175
+ EOL: 7 }
176
176
 
177
177
  racc_use_result_var = true
178
178
 
data/plugin/50sp.rb CHANGED
@@ -8,8 +8,9 @@ SP_PREFIX = 'sp'
8
8
  end
9
9
  @sp_path << "#{TDiary::PATH}/misc/plugin" if @sp_path.include?('misc/plugin')
10
10
 
11
- # FIXME: dirty hack, it should create TDiary::Server::Config.plugin_path
12
- TDiary::Contrib::Plugin.setup( @sp_path ) if defined?(TDiary::Contrib)
11
+ @sp_path.concat TDiary::Extensions::constants.map {|extension|
12
+ TDiary::Extensions::const_get( extension ).sp_path
13
+ }.flatten.compact.uniq
13
14
 
14
15
  # get plugin option
15
16
  def sp_option( key )
@@ -6,8 +6,8 @@ feature 'ツッコミの更新' do
6
6
  append_default_diary
7
7
  visit '/'
8
8
  click_link 'ツッコミを入れる'
9
- fill_in "name", :with => "alpha"
10
- fill_in "body", :with => <<-BODY
9
+ fill_in "name", with: "alpha"
10
+ fill_in "body", with: <<-BODY
11
11
  こんにちは!こんにちは!
12
12
  BODY
13
13
 
@@ -22,7 +22,7 @@ BODY
22
22
  page.should have_content "こんにちは!こんにちは!"
23
23
  }
24
24
  today = Date.today.strftime('%Y年%m月%d日')
25
- page.find('h2', :text => today).click_link today
25
+ page.find('h2', text: today).click_link today
26
26
  within('div.day div.comment div.commentbody') {
27
27
  within('div.commentator'){
28
28
  t = Time.now
@@ -38,8 +38,8 @@ BODY
38
38
  append_default_comment
39
39
  visit "/"
40
40
  click_link 'ツッコミを入れる'
41
- fill_in "name", :with => "bravo"
42
- fill_in "body", :with => <<-BODY
41
+ fill_in "name", with: "bravo"
42
+ fill_in "body", with: <<-BODY
43
43
  こんばんは!こんばんは!
44
44
  BODY
45
45
 
@@ -55,7 +55,7 @@ BODY
55
55
  }
56
56
 
57
57
  today = Date.today.strftime('%Y年%m月%d日')
58
- page.find('h2', :text => today).click_link today
58
+ page.find('h2', text: today).click_link today
59
59
  within('div.day div.comment div.commentbody') {
60
60
  t = Time.now
61
61
  page.should have_content "%04d年%02d月%02d日" % [t.year, t.month, t.day]
@@ -70,8 +70,8 @@ BODY
70
70
  append_default_diary
71
71
  visit '/'
72
72
  click_link 'ツッコミを入れる'
73
- fill_in "name", :with => "alpha"
74
- fill_in "body", :with => <<-BODY
73
+ fill_in "name", with: "alpha"
74
+ fill_in "body", with: <<-BODY
75
75
  こんにちは!こんにちは!
76
76
  BODY
77
77