honyomi 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/HISTORY.md +16 -1
- data/README.md +3 -0
- data/lib/honyomi/util.rb +70 -0
- data/lib/honyomi/version.rb +1 -1
- data/lib/honyomi/web/app.rb +68 -47
- data/lib/honyomi/web/public/css/honyomi.css +41 -27
- data/lib/honyomi/web/views/index.haml +12 -6
- data/lib/honyomi/web/views/layout.haml +3 -3
- metadata +2 -3
- data/lib/honyomi/web/views/raw.haml +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 68f371dc5130aa8dc7f02f3464902d28628ba38a
|
4
|
+
data.tar.gz: dceceb65a54d4944993a91ae8d8a75b7576d9a0e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ca2111c247ee0bea1a11e74a3b6d57479e361bd148b76fb8f3873c3e349c079fbf39e3c14ceb6744053b1007b5cb2e6b0e287edbaf2dd7d8a825f2a3bc17ebd
|
7
|
+
data.tar.gz: c733a8d9b8420a5b92fb0df4b317931a10ac1bd03cf336bf265e4521ab08abbd26ff1d6711a812cefdbf5b4977dd05c7150921cedef13ebe8a51bb7f07fb330e
|
data/HISTORY.md
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
# HISTORY - Honyomi
|
2
2
|
|
3
|
-
## 0.
|
3
|
+
## 0.2 - 2014-10-07
|
4
|
+
|
5
|
+
* Improve search result
|
6
|
+
* Highlight keywords
|
7
|
+
* Take over the search query
|
8
|
+
* Improve text mode
|
9
|
+
* Rename from 'raw' to 'text'
|
10
|
+
* Highlight keywords
|
11
|
+
* Take over the search query
|
12
|
+
* Change rendering tag from <pre> to <div>
|
13
|
+
* Change background color
|
14
|
+
* Change Navbar to static
|
15
|
+
* Add link to honyomi-web
|
16
|
+
* Refactor page tag
|
17
|
+
|
18
|
+
## 0.1 - 2014-10-02
|
4
19
|
|
5
20
|
* Search in book
|
6
21
|
* Display the book list
|
data/README.md
CHANGED
@@ -18,6 +18,9 @@ When you faild to install Rroonga, Please refer.
|
|
18
18
|
And need external tools.
|
19
19
|
* pdftotext - For reading pdf (poppler, xpdf)
|
20
20
|
|
21
|
+
## Install to server
|
22
|
+
* [ongaeshi/honyomi-web](https://github.com/ongaeshi/honyomi-web)
|
23
|
+
|
21
24
|
## Usage
|
22
25
|
|
23
26
|
### Create a database
|
data/lib/honyomi/util.rb
CHANGED
@@ -37,5 +37,75 @@ module Honyomi
|
|
37
37
|
def strip_page(page)
|
38
38
|
page.gsub(/[ \t]/, "")
|
39
39
|
end
|
40
|
+
|
41
|
+
def highlight_keywords(src, keywords, css_class)
|
42
|
+
# Init highlight_map
|
43
|
+
hightlight_map = Array.new(src.length, nil)
|
44
|
+
|
45
|
+
keywords.each do |keyword|
|
46
|
+
pos = 0
|
47
|
+
|
48
|
+
loop do
|
49
|
+
r = src.match(/#{Regexp.escape(keyword)}/i, pos) do |m|
|
50
|
+
s = m.begin(0)
|
51
|
+
l = keyword.length
|
52
|
+
e = s+l
|
53
|
+
(s...e).each {|i| hightlight_map[i] = 1 }
|
54
|
+
pos = e
|
55
|
+
end
|
56
|
+
|
57
|
+
break if r.nil?
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Delete html tag
|
62
|
+
index = 0
|
63
|
+
in_tag = false
|
64
|
+
src.each_char do |char|
|
65
|
+
in_tag = true if char == '<'
|
66
|
+
hightlight_map[index] = nil if in_tag
|
67
|
+
in_tag = false if char == '>'
|
68
|
+
index += 1
|
69
|
+
end
|
70
|
+
|
71
|
+
# Output
|
72
|
+
result = ""
|
73
|
+
|
74
|
+
index = 0
|
75
|
+
prev = nil
|
76
|
+
src.each_char do |char|
|
77
|
+
current = hightlight_map[index]
|
78
|
+
|
79
|
+
if prev.nil? && current
|
80
|
+
result += "<span class='#{css_class}'>"
|
81
|
+
elsif prev && current.nil?
|
82
|
+
result += "</span>"
|
83
|
+
end
|
84
|
+
|
85
|
+
result += char
|
86
|
+
|
87
|
+
index += 1
|
88
|
+
prev = current
|
89
|
+
end
|
90
|
+
result += "</span>" if prev
|
91
|
+
|
92
|
+
result
|
93
|
+
end
|
94
|
+
|
95
|
+
def extract_keywords(query)
|
96
|
+
query.split.reduce([]) do |a, e|
|
97
|
+
e = e.gsub(/^\(|\)|AND|OR$/, "")
|
98
|
+
|
99
|
+
if e =~ /^"(.+)"$/
|
100
|
+
a + [$1]
|
101
|
+
elsif e =~ /^-/
|
102
|
+
a
|
103
|
+
elsif e =~ /:/
|
104
|
+
a
|
105
|
+
else
|
106
|
+
a + [e]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
40
110
|
end
|
41
111
|
end
|
data/lib/honyomi/version.rb
CHANGED
data/lib/honyomi/web/app.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'haml'
|
2
2
|
require 'honyomi/database'
|
3
|
+
require 'honyomi/util'
|
3
4
|
require 'sinatra'
|
4
5
|
require 'sinatra/reloader' if ENV['SINATRA_RELOADER']
|
5
6
|
|
@@ -34,15 +35,15 @@ get '/v/:id' do
|
|
34
35
|
|
35
36
|
book = @database.books[params[:id].to_i]
|
36
37
|
|
37
|
-
if params[:
|
38
|
-
|
38
|
+
if params[:text] == '1'
|
39
|
+
text_all(book)
|
39
40
|
elsif params[:pdf] == '1'
|
40
41
|
send_file(book.path, :disposition => 'inline')
|
41
42
|
elsif params[:dl] == '1'
|
42
43
|
send_file(book.path, :disposition => 'download')
|
43
44
|
else
|
44
45
|
if params[:page]
|
45
|
-
|
46
|
+
text_page(book, params[:page].to_i)
|
46
47
|
else
|
47
48
|
if @params[:query] && !@params[:query].empty?
|
48
49
|
search_book_home(book)
|
@@ -56,6 +57,8 @@ end
|
|
56
57
|
helpers do
|
57
58
|
|
58
59
|
def home
|
60
|
+
@header_info = %Q|#{@database.books.size} books, #{@database.pages.size} pages.|
|
61
|
+
|
59
62
|
r = @database.books.map { |book|
|
60
63
|
<<EOF
|
61
64
|
<li>#{book.id}: <a href="/v/#{book.id}">#{book.title}</a> (#{book.page_num}P)</li>
|
@@ -63,12 +66,9 @@ EOF
|
|
63
66
|
}.reverse
|
64
67
|
|
65
68
|
@content = <<EOF
|
66
|
-
<
|
67
|
-
<div class="result">
|
68
|
-
<ul>
|
69
|
+
<ul>
|
69
70
|
#{r.join("\n")}
|
70
|
-
|
71
|
-
</div>
|
71
|
+
</ul>
|
72
72
|
EOF
|
73
73
|
|
74
74
|
haml :index
|
@@ -83,22 +83,15 @@ EOF
|
|
83
83
|
|
84
84
|
def book_home(book)
|
85
85
|
@book_id = book.id
|
86
|
-
@
|
87
|
-
@
|
88
|
-
|
89
|
-
|
90
|
-
@content = <<EOF
|
91
|
-
<div class="result">
|
92
|
-
<div class="matches">#{book.page_num} pages. <a href="/v/#{book.id}?dl=1">Download</a> <span class="result-file-size">(#{file_mb}M)</span> <a href="/v/#{book.id}?pdf=1">Pdf</a> <a href="/v/#{book.id}?raw=1">Raw</a></div>
|
93
|
-
</div>
|
94
|
-
EOF
|
86
|
+
@header_title = header_title_book(book, @params[:query])
|
87
|
+
@header_info = header_info_book(book, @params[:query])
|
88
|
+
@content = ""
|
95
89
|
haml :index
|
96
90
|
end
|
97
91
|
|
98
92
|
def search_book_home(book)
|
99
93
|
@book_id = book.id
|
100
|
-
@
|
101
|
-
@navbar_title = book.title
|
94
|
+
@header_title = header_title_book(book, @params[:query])
|
102
95
|
|
103
96
|
search_common(@params[:query] + " book: #{book.id}",
|
104
97
|
[["page_no", :asc]],
|
@@ -106,38 +99,32 @@ EOF
|
|
106
99
|
)
|
107
100
|
end
|
108
101
|
|
109
|
-
def
|
110
|
-
|
102
|
+
def text_all(book)
|
103
|
+
@book_id = book.id
|
104
|
+
@header_title = header_title_book(book, @params[:query])
|
105
|
+
@header_info = header_info_book(book, @params[:query])
|
111
106
|
|
112
|
-
|
113
|
-
|
107
|
+
pages = @database.book_pages(book.id)
|
108
|
+
keywords = Util.extract_keywords(@params[:query])
|
114
109
|
|
115
110
|
@content = pages.map { |page|
|
116
|
-
|
117
|
-
<div class="raw-page" id="#{page.page_no}">
|
118
|
-
<div class="raw-page-no"><i class="fa fa-file-text-o"></i> <a href="##{page.page_no}">P#{page.page_no}</a></div>
|
119
|
-
<pre>#{escape_html page.text}</pre>
|
120
|
-
</div>
|
121
|
-
EOF
|
111
|
+
render_page(page, keywords: keywords, with_number: true)
|
122
112
|
}.join("\n")
|
123
113
|
|
124
|
-
haml :
|
114
|
+
haml :index
|
125
115
|
end
|
126
116
|
|
127
|
-
def
|
128
|
-
@navbar_href = "/v/#{book.id}"
|
129
|
-
@navbar_title = book.title
|
117
|
+
def text_page(book, page_no)
|
130
118
|
page = @database.book_pages(book.id)[page_no]
|
131
|
-
|
119
|
+
keywords = Util.extract_keywords(@params[:query])
|
132
120
|
|
133
|
-
@
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
haml :raw
|
121
|
+
@book_id = book.id
|
122
|
+
@header_title = header_title_book(book, @params[:query])
|
123
|
+
@header_info = header_info_book(book, @params[:query], page)
|
124
|
+
|
125
|
+
@content = render_page(page, keywords: keywords)
|
126
|
+
|
127
|
+
haml :index
|
141
128
|
end
|
142
129
|
|
143
130
|
RPAGE_SIZE = 20
|
@@ -156,7 +143,7 @@ EOF
|
|
156
143
|
EOF
|
157
144
|
end
|
158
145
|
|
159
|
-
snippet = results.expression.snippet([["<
|
146
|
+
snippet = results.expression.snippet([["<span class=\"highlight\">", "</span>"]], {html_escape: true, normalize: true, max_results: 5})
|
160
147
|
|
161
148
|
books = {}
|
162
149
|
|
@@ -164,6 +151,8 @@ EOF
|
|
164
151
|
books[page.book.path] = 1
|
165
152
|
end
|
166
153
|
|
154
|
+
@header_info = %Q|#{books.size} books, #{results.size} pages|
|
155
|
+
|
167
156
|
r = rpage_entries.map do |page|
|
168
157
|
if is_filter
|
169
158
|
query_plus = escape "#{query} book:#{page.book.id}"
|
@@ -175,11 +164,11 @@ EOF
|
|
175
164
|
|
176
165
|
<<EOF
|
177
166
|
<div class="result">
|
178
|
-
<div class="
|
179
|
-
<div class="row
|
167
|
+
<div class="title"><a href="/v/#{page.book.id}?query=#{escape(@params[:query])}&page=#{page.page_no}">#{page.book.title}</a> (P#{page.page_no})</div>
|
168
|
+
<div class="row info">
|
180
169
|
#{filter_str}
|
181
170
|
</div>
|
182
|
-
<div class="
|
171
|
+
<div class="main">
|
183
172
|
#{snippet.execute(page.text).map {|segment| "<div class=\"result-body-element\">" + segment.gsub("\n", "") + "</div>"}.join("\n") }
|
184
173
|
</div>
|
185
174
|
</div>
|
@@ -187,7 +176,6 @@ EOF
|
|
187
176
|
end
|
188
177
|
|
189
178
|
@content = <<EOF
|
190
|
-
<div class="matches">#{books.size} books, #{results.size} pages</div>
|
191
179
|
<div class="autopagerize_page_element">
|
192
180
|
#{r.join("\n")}
|
193
181
|
</div>
|
@@ -196,4 +184,37 @@ EOF
|
|
196
184
|
|
197
185
|
haml :index
|
198
186
|
end
|
187
|
+
|
188
|
+
def header_title_book(book, query)
|
189
|
+
query = query ? "?query=#{query}" : ""
|
190
|
+
"<a href='/#{query}'>HOME</a> > <a href='/v/#{book.id}#{query}'>#{book.title}</a>"
|
191
|
+
end
|
192
|
+
|
193
|
+
def header_info_book(book, query, page = nil)
|
194
|
+
query = query ? "&query=#{query}" : ""
|
195
|
+
file_mb = File.stat(book.path).size / (1024 * 1024)
|
196
|
+
|
197
|
+
if page.nil?
|
198
|
+
%Q|#{book.page_num} pages. <a href="/v/#{book.id}?dl=1">Download</a> <span class="file-size">(#{file_mb}M)</span> <a href="/v/#{book.id}?pdf=1">Pdf</a> <a href="/v/#{book.id}?text=1#{query}">Text</a>|
|
199
|
+
else
|
200
|
+
%Q|<i class="fa fa-file-text-o"></i> P#{page.page_no} <a href="/v/#{book.id}?dl=1">Download</a> <span class="file-size">(#{file_mb}M)</span> <a href="/v/#{book.id}?pdf=1#page=#{page.page_no}">Pdf</a> <a href="/v/#{book.id}?text=1#{query}##{page.page_no}">Text</a>|
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def render_page(page, options = {})
|
205
|
+
with_number = options[:with_number] ? %Q|<div class="no"><i class="fa fa-file-text-o"></i> <a href="##{page.page_no}">P#{page.page_no}</a></div>| : ""
|
206
|
+
|
207
|
+
text = escape_html(page.text)
|
208
|
+
text = Util.highlight_keywords(text, options[:keywords], 'highlight') if options[:keywords]
|
209
|
+
text = text.gsub("\n\n", "<br/><br/>")
|
210
|
+
|
211
|
+
<<EOF
|
212
|
+
<div class="page" id="#{page.page_no}">
|
213
|
+
#{with_number}
|
214
|
+
<div class="main">
|
215
|
+
#{text}
|
216
|
+
</div>
|
217
|
+
</div>
|
218
|
+
EOF
|
219
|
+
end
|
199
220
|
end
|
@@ -1,58 +1,72 @@
|
|
1
|
-
|
1
|
+
/* header */
|
2
|
+
.header {
|
3
|
+
}
|
4
|
+
|
5
|
+
.header .title {
|
6
|
+
font-size: 130%;
|
2
7
|
margin: 0px 0px 10px 0px;
|
3
8
|
}
|
4
9
|
|
5
|
-
.
|
10
|
+
.header .info {
|
6
11
|
margin: 10px 0px 0px 5px;
|
7
12
|
}
|
8
13
|
|
9
|
-
|
14
|
+
/* content */
|
15
|
+
.content {
|
10
16
|
margin: 10px 0px 0px 5px;
|
11
17
|
}
|
12
18
|
|
13
|
-
.
|
19
|
+
/* .content .home */
|
20
|
+
.content ul {
|
14
21
|
font-size: 120%;
|
22
|
+
list-style: none;
|
23
|
+
padding-left: 0px;
|
15
24
|
}
|
16
25
|
|
17
|
-
.result
|
18
|
-
|
19
|
-
|
26
|
+
/* .content .result */
|
27
|
+
.result .title {
|
28
|
+
margin: 10px 0px 0px 0px;
|
20
29
|
}
|
21
30
|
|
22
|
-
.result
|
23
|
-
font-size:
|
31
|
+
.result .title {
|
32
|
+
font-size: 120%;
|
24
33
|
}
|
25
34
|
|
26
|
-
.result
|
35
|
+
.result .info {
|
36
|
+
/* margin: 5px 0px 0px 0px; */
|
37
|
+
font-size: 100%;
|
38
|
+
}
|
39
|
+
|
40
|
+
.result .main {
|
27
41
|
margin: 5px 0px 0px 0px;
|
28
42
|
font-size: 95%;
|
29
43
|
}
|
30
44
|
|
31
|
-
.
|
32
|
-
margin: 0px 20px;
|
33
|
-
}
|
45
|
+
/* .content .text */
|
34
46
|
|
35
|
-
.
|
36
|
-
|
47
|
+
.page {
|
48
|
+
/* margin: 0px 0px; */
|
37
49
|
}
|
38
50
|
|
39
|
-
.
|
40
|
-
|
51
|
+
.page .no {
|
52
|
+
padding: 20px 0px 10px 0px;
|
41
53
|
}
|
42
54
|
|
43
|
-
.
|
44
|
-
|
55
|
+
.page .main {
|
56
|
+
background-color: #fbfbfb;
|
57
|
+
border: solid 1px #d0d0d0;
|
58
|
+
font-size: 95%;
|
45
59
|
}
|
46
60
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
padding-left: 0px;
|
61
|
+
/* common */
|
62
|
+
.file-size {
|
63
|
+
font-size: 95%;
|
51
64
|
}
|
52
65
|
|
53
|
-
.
|
54
|
-
|
55
|
-
|
56
|
-
|
66
|
+
.highlight {
|
67
|
+
/* background-color: #B4D5FF; */
|
68
|
+
/* background-color: #FFF17A; */
|
69
|
+
background-color: #FEEFA2;
|
70
|
+
font-weight: bold;
|
57
71
|
}
|
58
72
|
|
@@ -3,9 +3,15 @@
|
|
3
3
|
.container
|
4
4
|
.row
|
5
5
|
.col-md-12
|
6
|
-
|
7
|
-
.
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
.header
|
7
|
+
.title
|
8
|
+
= @header_title
|
9
|
+
%form(class="form-inline" method="post" action="/search")
|
10
|
+
.form-group
|
11
|
+
%input(class="form-control" type="text" size=40 name="query" value="#{@params[:query]}")
|
12
|
+
%input(type="hidden" name="book_id" value="#{@book_id}")
|
13
|
+
%input(class="btn btn-primary" type="submit" value="Search")
|
14
|
+
.info
|
15
|
+
= @header_info
|
16
|
+
.content
|
17
|
+
= @content
|
@@ -10,8 +10,8 @@
|
|
10
10
|
%link(rel="stylesheet" href="/css/honyomi.css")
|
11
11
|
%link(rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css")
|
12
12
|
|
13
|
-
%body
|
14
|
-
.navbar.navbar-default.navbar-
|
13
|
+
%body
|
14
|
+
.navbar.navbar-default.navbar-static-top
|
15
15
|
.navbar-header
|
16
16
|
%button(type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse")
|
17
17
|
%span(class="icon-bar")
|
@@ -22,7 +22,7 @@
|
|
22
22
|
.navbar-collapse.collapse
|
23
23
|
%ul(class="nav navbar-nav")
|
24
24
|
%li
|
25
|
-
<a href="
|
25
|
+
<a href="/help">Help</a>
|
26
26
|
|
27
27
|
!= yield
|
28
28
|
%script(src="https://code.jquery.com/jquery.js")
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: honyomi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ongaeshi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: grn_mini
|
@@ -197,7 +197,6 @@ files:
|
|
197
197
|
- lib/honyomi/web/public/image/favicon.ico
|
198
198
|
- lib/honyomi/web/views/index.haml
|
199
199
|
- lib/honyomi/web/views/layout.haml
|
200
|
-
- lib/honyomi/web/views/raw.haml
|
201
200
|
- test/minitest_helper.rb
|
202
201
|
- test/test.pdf
|
203
202
|
- test/test2.pdf
|