mizuho 0.9.12 → 0.9.13
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/mizuho +26 -0
- data/lib/mizuho.rb +1 -1
- data/lib/mizuho/generator.rb +133 -17
- data/lib/mizuho/id_map.rb +68 -36
- data/lib/mizuho/utils.rb +65 -0
- data/templates/mizuho.css +7 -1
- data/templates/toc.html +0 -0
- data/templates/topbar.css +9 -0
- data/templates/topbar.js +7 -0
- data/test/id_map_spec.rb +91 -108
- metadata +20 -2
data/bin/mizuho
CHANGED
@@ -1,4 +1,23 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# Copyright (c) 2008-2013 Hongli Lai
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
2
21
|
require File.expand_path(File.dirname(__FILE__) + "/../lib/mizuho")
|
3
22
|
require 'optparse'
|
4
23
|
require 'rubygems'
|
@@ -45,6 +64,13 @@ parser = OptionParser.new do |opts|
|
|
45
64
|
opts.on("-o", "--output FILE", String, "Specify the output filename.") do |value|
|
46
65
|
options[:output] = value
|
47
66
|
end
|
67
|
+
opts.on("--index", "Generate a full-text index.") do
|
68
|
+
options[:index] = true
|
69
|
+
end
|
70
|
+
opts.on("--no-run", "Do not run Asciidoc. Developer option#{nl}" <<
|
71
|
+
"only, don't use.") do
|
72
|
+
options[:no_run] = true
|
73
|
+
end
|
48
74
|
end
|
49
75
|
begin
|
50
76
|
parser.parse!
|
data/lib/mizuho.rb
CHANGED
data/lib/mizuho/generator.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2008-
|
1
|
+
# Copyright (c) 2008-2013 Hongli Lai
|
2
2
|
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
# of this software and associated documentation files (the "Software"), to deal
|
@@ -22,6 +22,7 @@ require 'nokogiri'
|
|
22
22
|
require 'mizuho'
|
23
23
|
require 'mizuho/source_highlight'
|
24
24
|
require 'mizuho/id_map'
|
25
|
+
require 'mizuho/utils'
|
25
26
|
|
26
27
|
module Mizuho
|
27
28
|
|
@@ -38,7 +39,10 @@ class Generator
|
|
38
39
|
@conf_file = options[:conf_file]
|
39
40
|
@attributes = options[:attributes] || []
|
40
41
|
@enable_topbar = options[:topbar]
|
42
|
+
@no_run = options[:no_run]
|
41
43
|
@commenting_system = options[:commenting_system]
|
44
|
+
@index = options[:index]
|
45
|
+
@index_filename = options[:index_filename] || default_index_filename(input)
|
42
46
|
if @commenting_system == 'juvia'
|
43
47
|
require_options(options, :juvia_url, :juvia_site_key)
|
44
48
|
end
|
@@ -53,7 +57,10 @@ class Generator
|
|
53
57
|
warn "No ID map file, generating one (#{@id_map_file})..."
|
54
58
|
end
|
55
59
|
end
|
56
|
-
|
60
|
+
if !@no_run
|
61
|
+
self.class.run_asciidoc(@input_file, @output_file, @icons_dir,
|
62
|
+
@conf_file, @attributes)
|
63
|
+
end
|
57
64
|
transform(@output_file)
|
58
65
|
if @commenting_system
|
59
66
|
@id_map.save(@id_map_file)
|
@@ -71,9 +78,7 @@ class Generator
|
|
71
78
|
args = [
|
72
79
|
"python", ASCIIDOC,
|
73
80
|
"-b", "html5",
|
74
|
-
"-a", "toc",
|
75
81
|
"-a", "theme=flask",
|
76
|
-
"-a", "toclevels=3",
|
77
82
|
"-a", "icons",
|
78
83
|
"-n"
|
79
84
|
]
|
@@ -112,6 +117,13 @@ private
|
|
112
117
|
File.basename(input, File.extname(input)) +
|
113
118
|
".idmap.txt"
|
114
119
|
end
|
120
|
+
|
121
|
+
def default_index_filename(input)
|
122
|
+
return File.dirname(input) +
|
123
|
+
"/" +
|
124
|
+
File.basename(input, File.extname(input)) +
|
125
|
+
".index.sqlite3"
|
126
|
+
end
|
115
127
|
|
116
128
|
def warn(message)
|
117
129
|
STDERR.puts(message)
|
@@ -119,36 +131,85 @@ private
|
|
119
131
|
|
120
132
|
def transform(filename)
|
121
133
|
File.open(filename, 'r+') do |f|
|
122
|
-
doc
|
123
|
-
head
|
124
|
-
body
|
134
|
+
doc = Nokogiri.HTML(f)
|
135
|
+
head = (doc / "head")[0]
|
136
|
+
body = (doc / "body")[0]
|
125
137
|
title = (doc / "title")[0].text
|
126
|
-
|
127
|
-
|
138
|
+
header_div = (doc / "#header")[0]
|
139
|
+
headers = (doc / "#content" / "h1, h2, h3, h4")
|
128
140
|
|
129
141
|
head.add_child(stylesheet_tag)
|
130
142
|
|
143
|
+
# Add commenting balloons.
|
131
144
|
if @commenting_system
|
132
|
-
|
145
|
+
titles = []
|
146
|
+
headers.each do |header|
|
147
|
+
if header['class'] !~ /float/
|
148
|
+
titles << header.text
|
149
|
+
end
|
150
|
+
end
|
151
|
+
@id_map.generate_associations(titles)
|
133
152
|
headers.each do |header|
|
134
|
-
header['
|
135
|
-
|
153
|
+
if header['class'] !~ /float/
|
154
|
+
titles << header.text
|
155
|
+
header['data-comment-topic'] = @id_map.associations[header.text]
|
156
|
+
header.add_previous_sibling(create_comment_balloon)
|
157
|
+
end
|
136
158
|
end
|
137
159
|
end
|
138
160
|
|
161
|
+
# Add top bar.
|
139
162
|
if @enable_topbar
|
140
163
|
body.children.first.add_previous_sibling(topbar(title))
|
141
164
|
end
|
165
|
+
|
166
|
+
# Add Mizuho Javascript.
|
142
167
|
body.add_child(javascript_tag)
|
143
|
-
|
144
|
-
|
168
|
+
|
169
|
+
# Move preamble from content area to header area.
|
170
|
+
if preamble = (doc / "#preamble")[0]
|
145
171
|
preamble.remove
|
146
|
-
|
147
|
-
preamble_copy['id'] = 'preamble'
|
172
|
+
header_div.add_child(preamble)
|
148
173
|
end
|
149
174
|
|
175
|
+
# Create a TOC after the preamble.
|
176
|
+
toc_div = header_div.add_child(%Q{<div id="toc"></div>})[0]
|
150
177
|
if @commenting_system
|
151
|
-
|
178
|
+
# Add a commenting balloon to the TOC title.
|
179
|
+
toc_div.add_child(create_comment_balloon)
|
180
|
+
end
|
181
|
+
toc_div.add_child(%Q{<div id="toctitle">Table of Contents</div>})
|
182
|
+
headers.each do |header|
|
183
|
+
if header['class'] !~ /float/
|
184
|
+
level = header.name.scan(/\d+/).first
|
185
|
+
div = toc_div.add_child("<div class=\"foo toclevel#{level}\"></div>")[0]
|
186
|
+
link = div.add_child("<a></a>")[0]
|
187
|
+
link['href'] = '#' + header['id']
|
188
|
+
link.content = header.text
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
if @enable_topbar
|
193
|
+
# Add invisible spans before each header so that anchor jumps
|
194
|
+
# don't hide the header behind the top bar.
|
195
|
+
# http://nicolasgallagher.com/jump-links-and-viewport-positioning/
|
196
|
+
headers.each do |header|
|
197
|
+
span = header.add_previous_sibling('<span class="anchor_helper"></span>')[0]
|
198
|
+
span['id'] = header['data-anchor'] = header['id']
|
199
|
+
header.remove_attribute('id')
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
if @index
|
204
|
+
# Add docid attributes to headers.
|
205
|
+
headers.each do |header|
|
206
|
+
next if header['class'] =~ /float/
|
207
|
+
docid = Utils.title_to_docid(header.text)
|
208
|
+
header['data-docid'] = docid.to_s
|
209
|
+
header['class'] = "#{header['class']} docid-#{docid}".strip
|
210
|
+
end
|
211
|
+
|
212
|
+
create_search_index(headers, @index_filename)
|
152
213
|
end
|
153
214
|
|
154
215
|
f.rewind
|
@@ -238,6 +299,61 @@ private
|
|
238
299
|
end
|
239
300
|
exit 1 if fail
|
240
301
|
end
|
302
|
+
|
303
|
+
def gather_content(header)
|
304
|
+
result = []
|
305
|
+
elem = header
|
306
|
+
while true
|
307
|
+
elem = elem.next_sibling
|
308
|
+
if !elem || elem.name =~ /^h/i
|
309
|
+
break
|
310
|
+
else
|
311
|
+
text = elem.text.strip
|
312
|
+
if !text.empty?
|
313
|
+
text.gsub!(/\r?\n/, " ")
|
314
|
+
result << text
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
return result.join(" ")
|
319
|
+
end
|
320
|
+
|
321
|
+
def create_search_index(headers, filename)
|
322
|
+
require 'sqlite3'
|
323
|
+
db = SQLite3::Database.new("#{filename}.tmp")
|
324
|
+
db.transaction do
|
325
|
+
db.execute(%q{
|
326
|
+
CREATE VIRTUAL TABLE book USING fts4(
|
327
|
+
title TEXT NOT NULL,
|
328
|
+
content TEXT NOT NULL,
|
329
|
+
content="",
|
330
|
+
tokenize=porter
|
331
|
+
)
|
332
|
+
})
|
333
|
+
db.execute(%q{
|
334
|
+
CREATE TABLE version(
|
335
|
+
version INTEGER NOT NULL
|
336
|
+
)
|
337
|
+
})
|
338
|
+
db.execute("INSERT INTO version VALUES(1)")
|
339
|
+
db.prepare("INSERT INTO book(docid, title, content) VALUES(?, ?, ?)") do |stmt|
|
340
|
+
headers.each do |header|
|
341
|
+
next if header['class'] =~ /float/
|
342
|
+
title = header.text.strip
|
343
|
+
docid = Utils.title_to_docid(title)
|
344
|
+
content = gather_content(header)
|
345
|
+
stmt.execute(docid, title, content)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
db.execute("INSERT INTO book(book) VALUES('optimize')")
|
350
|
+
db.execute("VACUUM")
|
351
|
+
db.close
|
352
|
+
File.rename("#{filename}.tmp", filename)
|
353
|
+
rescue Exception => e
|
354
|
+
File.unlink("#{filename}.tmp") rescue nil
|
355
|
+
raise e
|
356
|
+
end
|
241
357
|
end
|
242
358
|
|
243
359
|
end
|
data/lib/mizuho/id_map.rb
CHANGED
@@ -19,6 +19,7 @@
|
|
19
19
|
# THE SOFTWARE.
|
20
20
|
|
21
21
|
require 'mizuho/fuzzystringmatch'
|
22
|
+
require 'mizuho/utils'
|
22
23
|
|
23
24
|
module Mizuho
|
24
25
|
|
@@ -26,6 +27,8 @@ class IdMap
|
|
26
27
|
class AlreadyAssociatedError < StandardError
|
27
28
|
end
|
28
29
|
|
30
|
+
include Utils
|
31
|
+
|
29
32
|
URANDOM = File.open("/dev/urandom", "rb")
|
30
33
|
MATCHER = JaroWinklerPure.new
|
31
34
|
BANNER =
|
@@ -43,17 +46,14 @@ class IdMap
|
|
43
46
|
"# and that Mizuho has found an ID which appears to be associated with that\n" <<
|
44
47
|
"# section. You should check whether it is correct, and if not, fix it.\n\n"
|
45
48
|
|
46
|
-
attr_reader :entries
|
49
|
+
attr_reader :entries, :associations
|
47
50
|
|
48
51
|
def initialize
|
49
52
|
@entries = {}
|
53
|
+
@associations = {}
|
50
54
|
#@namespace = slug(File.basename(filename, File.extname(filename)))
|
51
55
|
end
|
52
56
|
|
53
|
-
def [](title)
|
54
|
-
return @entries[title]
|
55
|
-
end
|
56
|
-
|
57
57
|
def load(filename_or_io)
|
58
58
|
@entries.clear
|
59
59
|
open_io(filename_or_io, :read) do |io|
|
@@ -101,16 +101,73 @@ class IdMap
|
|
101
101
|
f.write(output)
|
102
102
|
end
|
103
103
|
end
|
104
|
+
|
105
|
+
def generate_associations(titles)
|
106
|
+
@associations = {}
|
107
|
+
|
108
|
+
# Associate exact matches.
|
109
|
+
titles = titles.reject do |title|
|
110
|
+
if (entry = @entries[title]) && !entry.associated?
|
111
|
+
entry.associated = true
|
112
|
+
@associations[title] = entry.id
|
113
|
+
true
|
114
|
+
else
|
115
|
+
false
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# For the remaining titles, associate with moved or similar-looking entry.
|
120
|
+
titles.reject! do |title|
|
121
|
+
if entry = find_moved(title)
|
122
|
+
@entries.delete(entry.title)
|
123
|
+
@entries[title] = entry
|
124
|
+
entry.title = title
|
125
|
+
entry.associated = true
|
126
|
+
entry.fuzzy = false
|
127
|
+
@associations[title] = entry.id
|
128
|
+
true
|
129
|
+
else
|
130
|
+
false
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# For the remaining titles, associate with similar-looking entry.
|
135
|
+
titles.reject! do |title|
|
136
|
+
if entry = find_similar(title)
|
137
|
+
@entries.delete(entry.title)
|
138
|
+
@entries[title] = entry
|
139
|
+
entry.title = title
|
140
|
+
entry.associated = true
|
141
|
+
entry.fuzzy = true
|
142
|
+
@associations[title] = entry.id
|
143
|
+
true
|
144
|
+
else
|
145
|
+
false
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# For the remaining titles, create new entries.
|
150
|
+
titles.each do |title|
|
151
|
+
id = create_unique_id(title)
|
152
|
+
add(title, id, false, true)
|
153
|
+
@associations[title] = id
|
154
|
+
end
|
155
|
+
end
|
104
156
|
|
105
|
-
def
|
157
|
+
def xassociate(title)
|
106
158
|
if entry = @entries[title]
|
107
159
|
if entry.associated?
|
108
|
-
raise AlreadyAssociatedError, "Cannot associate an already
|
160
|
+
raise AlreadyAssociatedError, "Cannot associate an already associated title (#{title.inspect})"
|
109
161
|
else
|
110
162
|
entry.associated = true
|
111
163
|
id = entry.id
|
112
164
|
end
|
113
165
|
elsif (moved_entry = find_moved(title)) || (similar_entry = find_similar(title))
|
166
|
+
if moved_entry
|
167
|
+
puts "moved entry: #{title.inspect} -> #{moved_entry.title.inspect}"
|
168
|
+
elsif similar_entry
|
169
|
+
puts "similar entry: #{title.inspect} -> #{similar_entry.title.inspect}"
|
170
|
+
end
|
114
171
|
entry = (moved_entry || similar_entry)
|
115
172
|
@entries.delete(entry.title)
|
116
173
|
@entries[title] = entry
|
@@ -152,11 +209,11 @@ private
|
|
152
209
|
alias associated? associated
|
153
210
|
|
154
211
|
def <=>(other)
|
155
|
-
if (a =
|
156
|
-
(b =
|
212
|
+
if (a = Utils.extract_chapter(title)) &&
|
213
|
+
(b = Utils.extract_chapter(other.title))
|
157
214
|
# Sort by chapter whenever possible.
|
158
|
-
a[0] =
|
159
|
-
b[0] =
|
215
|
+
a[0] = Utils.chapter_to_int_array(a[0])
|
216
|
+
b[0] = Utils.chapter_to_int_array(b[0])
|
160
217
|
return a <=> b
|
161
218
|
else
|
162
219
|
return title <=> other.title
|
@@ -232,31 +289,6 @@ private
|
|
232
289
|
end
|
233
290
|
end
|
234
291
|
|
235
|
-
# Given a title with a chapter number, e.g. "6.1 Installation using tarball",
|
236
|
-
# splits the two up.
|
237
|
-
def self.extract_chapter(title)
|
238
|
-
title =~ /^((\d+\.)*) (.+)$/
|
239
|
-
chapter = $1
|
240
|
-
pure_title = $3
|
241
|
-
if !chapter.nil? && !chapter.empty? && pure_title && !pure_title.empty?
|
242
|
-
return [chapter, pure_title]
|
243
|
-
else
|
244
|
-
return nil
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
def extract_chapter(title)
|
249
|
-
return IdMap.extract_chapter(title)
|
250
|
-
end
|
251
|
-
|
252
|
-
def self.chapter_to_int_array(chapter)
|
253
|
-
return chapter.split('.').map { |x| x.to_i }
|
254
|
-
end
|
255
|
-
|
256
|
-
def chapter_to_int_array(chapter)
|
257
|
-
return IdMap.chapter_to_int_array(chapter)
|
258
|
-
end
|
259
|
-
|
260
292
|
def slug(text)
|
261
293
|
text = text.downcase
|
262
294
|
text.gsub!(/^(\d+\.)+ /, '')
|
data/lib/mizuho/utils.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# Copyright (c) 2013 Hongli Lai
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
module Mizuho
|
22
|
+
|
23
|
+
module Utils
|
24
|
+
extend self
|
25
|
+
|
26
|
+
def self.included(klass)
|
27
|
+
# When included into another class, make sure that Utils
|
28
|
+
# methods are made private.
|
29
|
+
public_instance_methods(false).each do |method_name|
|
30
|
+
klass.send(:private, method_name)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Given a title with a chapter number, e.g. "6.1 Installation using tarball",
|
35
|
+
# splits the two up.
|
36
|
+
def extract_chapter(title)
|
37
|
+
title =~ /^((\d+\.)*) (.+)$/
|
38
|
+
chapter = $1
|
39
|
+
pure_title = $3
|
40
|
+
if !chapter.nil? && !chapter.empty? && pure_title && !pure_title.empty?
|
41
|
+
return [chapter, pure_title]
|
42
|
+
else
|
43
|
+
return nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def chapter_to_int_array(chapter)
|
48
|
+
return chapter.split('.').map { |x| x.to_i }
|
49
|
+
end
|
50
|
+
|
51
|
+
def title_to_docid(title)
|
52
|
+
chapter, pure_title = extract_chapter(title)
|
53
|
+
p title
|
54
|
+
numbers = chapter_to_int_array(chapter)
|
55
|
+
result = 0
|
56
|
+
bit_offset = 0
|
57
|
+
numbers.each do |num|
|
58
|
+
result = result | (num << bit_offset)
|
59
|
+
bit_offset += 5
|
60
|
+
end
|
61
|
+
return result
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
data/templates/mizuho.css
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
body {
|
2
|
-
margin: 1em
|
2
|
+
margin: 1em auto 1em auto;
|
3
|
+
padding: 0 1em 0 1em;
|
4
|
+
max-width: 800px;
|
3
5
|
}
|
4
6
|
|
5
7
|
a.image {
|
@@ -78,6 +80,10 @@ a.image {
|
|
78
80
|
margin: 2em;
|
79
81
|
}
|
80
82
|
|
83
|
+
pre {
|
84
|
+
overflow: auto;
|
85
|
+
}
|
86
|
+
|
81
87
|
@media print {
|
82
88
|
body {
|
83
89
|
font-size: 18pt;
|
data/templates/toc.html
ADDED
File without changes
|
data/templates/topbar.css
CHANGED
@@ -114,3 +114,12 @@
|
|
114
114
|
border-bottom-left-radius: 0;
|
115
115
|
border-bottom-right-radius: 0;
|
116
116
|
}
|
117
|
+
|
118
|
+
/* http://nicolasgallagher.com/jump-links-and-viewport-positioning/ */
|
119
|
+
.anchor_helper {
|
120
|
+
position: relative;
|
121
|
+
display: block;
|
122
|
+
top: -50px;
|
123
|
+
width: 1px;
|
124
|
+
height: 1px;
|
125
|
+
}
|
data/templates/topbar.js
CHANGED
@@ -8,6 +8,7 @@ Mizuho.initializeTopBar = $.proxy(function() {
|
|
8
8
|
var isMobileDevice = this.isMobileDevice();
|
9
9
|
var timerId;
|
10
10
|
|
11
|
+
// Create the floating table of contents used in the top bar.
|
11
12
|
var $floattoc = $('<div id="floattoc"></div>').html($('#toc').html());
|
12
13
|
$floattoc.find('#toctitle').remove();
|
13
14
|
$floattoc.find('.comments').remove();
|
@@ -26,6 +27,8 @@ Mizuho.initializeTopBar = $.proxy(function() {
|
|
26
27
|
self.internalLinkClicked(this, event);
|
27
28
|
});
|
28
29
|
|
30
|
+
// Callback for when the user clicks on the Table of Contents
|
31
|
+
// button on the top bar.
|
29
32
|
function showFloatingToc() {
|
30
33
|
var scrollUpdateTimerId;
|
31
34
|
|
@@ -118,6 +121,9 @@ Mizuho.initializeTopBar = $.proxy(function() {
|
|
118
121
|
$window.bind('scroll', onScroll);
|
119
122
|
}
|
120
123
|
|
124
|
+
// Called whenever the user scrolls. Updates the title of the
|
125
|
+
// Table of Contents button in the top bar to the section that
|
126
|
+
// the user is currently reading.
|
121
127
|
function update() {
|
122
128
|
if ($title.offset().top + $title.height() < $document.scrollTop()) {
|
123
129
|
if (!$topbar.is(':visible')) {
|
@@ -161,6 +167,7 @@ Mizuho.initializeTopBar = $.proxy(function() {
|
|
161
167
|
}, 100);
|
162
168
|
}
|
163
169
|
|
170
|
+
|
164
171
|
if (isMobileDevice) {
|
165
172
|
// Mobile devices don't support position fixed.
|
166
173
|
$topbar.css('position', 'absolute');
|
data/test/id_map_spec.rb
CHANGED
@@ -29,133 +29,116 @@ describe IdMap do
|
|
29
29
|
@id_map = IdMap.new
|
30
30
|
end
|
31
31
|
|
32
|
-
describe "#
|
33
|
-
describe "if
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
it "returns a new unique ID" do
|
42
|
-
@id1.should_not == @id2
|
43
|
-
@id1.should_not == @id3
|
44
|
-
end
|
45
|
-
|
46
|
-
it "marks the entry as associated" do
|
47
|
-
@id_map["Installation"].should be_associated
|
48
|
-
@id_map["Installation on Linux"].should be_associated
|
49
|
-
@id_map["Configuration"].should be_associated
|
50
|
-
end
|
51
|
-
|
52
|
-
it "doesn't mark the corresponding entry as fuzzy" do
|
53
|
-
@id_map["Installation"].should_not be_fuzzy
|
54
|
-
@id_map["Installation on Linux"].should_not be_fuzzy
|
55
|
-
@id_map["Configuration"].should_not be_fuzzy
|
56
|
-
end
|
32
|
+
describe "#generate_associations" do
|
33
|
+
describe "if no similar titles exist in the map" do
|
34
|
+
before :each do
|
35
|
+
@id_map.generate_associations(["Installation",
|
36
|
+
"Installation on Linux", "Configuration"])
|
37
|
+
@id1 = @id_map.associations["Installation"]
|
38
|
+
@id2 = @id_map.associations["Installation on Linux"]
|
39
|
+
@id3 = @id_map.associations["Configuration"]
|
57
40
|
end
|
58
41
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
@entry2 = @id_map.add("5.6. Installation using a tarball", nil, false, false)
|
63
|
-
@entry3 = @id_map.add("6.0. Installation using a tarball", nil, false, false)
|
64
|
-
@id1 = @id_map.associate "5.4. Installation using a tarball"
|
65
|
-
@id2 = @id_map.associate "2.1. Installation using a tarball"
|
66
|
-
end
|
67
|
-
|
68
|
-
it "associates with the title whose section number is closest to the new section number" do
|
69
|
-
@id1.should == @entry2.id
|
70
|
-
@id2.should == @entry1.id
|
71
|
-
end
|
72
|
-
|
73
|
-
it "changes the original entries' titles" do
|
74
|
-
@entry1.title.should == "2.1. Installation using a tarball"
|
75
|
-
@entry2.title.should == "5.4. Installation using a tarball"
|
76
|
-
@entry3.title.should == "6.0. Installation using a tarball"
|
77
|
-
end
|
78
|
-
|
79
|
-
it "marks the corresponding entry as associated" do
|
80
|
-
@entry1.should be_associated
|
81
|
-
@entry2.should be_associated
|
82
|
-
@entry3.should_not be_associated
|
83
|
-
end
|
84
|
-
|
85
|
-
it "doesn't mark the corresponding entry as fuzzy" do
|
86
|
-
@entry1.should_not be_fuzzy
|
87
|
-
@entry2.should_not be_fuzzy
|
88
|
-
@entry3.should_not be_fuzzy
|
89
|
-
end
|
42
|
+
it "returns a new unique ID" do
|
43
|
+
@id1.should_not == @id2
|
44
|
+
@id1.should_not == @id3
|
90
45
|
end
|
91
46
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
end
|
97
|
-
|
98
|
-
it "associates with the most similar title and returns its ID" do
|
99
|
-
@id3 = @id_map.associate "Installation using tarball"
|
100
|
-
@id3.should == @entry1.id
|
101
|
-
@entry1.title.should == "Installation using tarball"
|
102
|
-
end
|
103
|
-
|
104
|
-
it "only associates with a title that hasn't been associated before" do
|
105
|
-
@entry1.associated = true
|
106
|
-
@id3 = @id_map.associate "Installation using tarball"
|
107
|
-
@id3.should == @entry2.id
|
108
|
-
end
|
109
|
-
|
110
|
-
it "marks the corresponding entry as associated" do
|
111
|
-
@id_map.associate "Installation using tarball"
|
112
|
-
@id_map["Installation using tarball"].should be_associated
|
113
|
-
end
|
114
|
-
|
115
|
-
it "marks the corresponding entry as fuzzy" do
|
116
|
-
@id_map.associate "Installation using tarball"
|
117
|
-
@id_map["Installation using tarball"].should be_fuzzy
|
118
|
-
end
|
47
|
+
it "marks the entry as associated" do
|
48
|
+
@id_map.entries["Installation"].should be_associated
|
49
|
+
@id_map.entries["Installation on Linux"].should be_associated
|
50
|
+
@id_map.entries["Configuration"].should be_associated
|
119
51
|
end
|
120
52
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
53
|
+
it "doesn't mark the corresponding entry as fuzzy" do
|
54
|
+
@id_map.entries["Installation"].should_not be_fuzzy
|
55
|
+
@id_map.entries["Installation on Linux"].should_not be_fuzzy
|
56
|
+
@id_map.entries["Configuration"].should_not be_fuzzy
|
125
57
|
end
|
126
58
|
end
|
127
59
|
|
128
|
-
describe "if the
|
60
|
+
describe "if the same title exists in the map, but with a different section number" do
|
129
61
|
before :each do
|
130
|
-
@
|
62
|
+
@entry1 = @id_map.add("1.2. Installation using a tarball", nil, false, false)
|
63
|
+
@entry2 = @id_map.add("5.6. Installation using a tarball", nil, false, false)
|
64
|
+
@entry3 = @id_map.add("6.0. Installation using a tarball", nil, false, false)
|
65
|
+
@id_map.generate_associations(["5.4. Installation using a tarball",
|
66
|
+
"2.1. Installation using a tarball"])
|
67
|
+
@id1 = @id_map.associations["5.4. Installation using a tarball"]
|
68
|
+
@id2 = @id_map.associations["2.1. Installation using a tarball"]
|
131
69
|
end
|
132
70
|
|
133
|
-
it "
|
134
|
-
|
135
|
-
|
71
|
+
it "associates with the title whose section number is closest to the new section number" do
|
72
|
+
@id1.should == @entry2.id
|
73
|
+
@id2.should == @entry1.id
|
136
74
|
end
|
137
75
|
|
138
|
-
it "
|
139
|
-
@
|
140
|
-
@
|
76
|
+
it "changes the original entries' titles" do
|
77
|
+
@entry1.title.should == "2.1. Installation using a tarball"
|
78
|
+
@entry2.title.should == "5.4. Installation using a tarball"
|
79
|
+
@entry3.title.should == "6.0. Installation using a tarball"
|
80
|
+
end
|
81
|
+
|
82
|
+
it "marks the corresponding entry as associated" do
|
83
|
+
@entry1.should be_associated
|
84
|
+
@entry2.should be_associated
|
85
|
+
@entry3.should_not be_associated
|
86
|
+
end
|
87
|
+
|
88
|
+
it "doesn't mark the corresponding entry as fuzzy" do
|
89
|
+
@entry1.should_not be_fuzzy
|
90
|
+
@entry2.should_not be_fuzzy
|
91
|
+
@entry3.should_not be_fuzzy
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "if one or more similar titles exist in the map" do
|
96
|
+
before :each do
|
97
|
+
@entry1 = @id_map.add("Installation using a tarball", nil, false, false)
|
98
|
+
@entry2 = @id_map.add("Installation using a Linux tarball", nil, false, false)
|
141
99
|
end
|
142
100
|
|
143
|
-
it "
|
144
|
-
@id_map.
|
145
|
-
@
|
101
|
+
it "associates with the most similar title and returns its ID" do
|
102
|
+
@id_map.generate_associations(["Installation using tarball"])
|
103
|
+
@id3 = @id_map.associations["Installation using tarball"]
|
104
|
+
@id3.should == @entry1.id
|
105
|
+
@entry1.title.should == "Installation using tarball"
|
106
|
+
end
|
107
|
+
|
108
|
+
it "only associates with a title that hasn't been associated before" do
|
109
|
+
@entry1.associated = true
|
110
|
+
@id_map.generate_associations(["Installation using tarball"])
|
111
|
+
@id3 = @id_map.associations["Installation using tarball"]
|
112
|
+
@id3.should == @entry2.id
|
113
|
+
end
|
146
114
|
|
147
|
-
|
148
|
-
@id_map.
|
149
|
-
@
|
115
|
+
it "marks the corresponding entry as associated" do
|
116
|
+
@id_map.generate_associations(["Installation using tarball"])
|
117
|
+
@id_map.entries["Installation using tarball"].should be_associated
|
118
|
+
end
|
119
|
+
|
120
|
+
it "marks the corresponding entry as fuzzy" do
|
121
|
+
@id_map.generate_associations(["Installation using tarball"])
|
122
|
+
@id_map.entries["Installation using tarball"].should be_fuzzy
|
150
123
|
end
|
151
124
|
end
|
152
125
|
|
153
|
-
describe "if
|
154
|
-
it "
|
155
|
-
@
|
156
|
-
|
126
|
+
describe "if a one title has a similar match, but a later title has an exact match" do
|
127
|
+
it "associates the later title with the exact match, then associates the first title with the similar match" do
|
128
|
+
@id_map.add("Hello Dear World", "id-1", false, false)
|
129
|
+
@id_map.add("Hallaa Dear World", "id-2", false, false)
|
130
|
+
@id_map.generate_associations(["Helloo Dear World", "Hello Dear World"])
|
131
|
+
@id_map.associations["Helloo Dear World"].should == "id-2"
|
132
|
+
@id_map.associations["Hello Dear World"].should == "id-1"
|
157
133
|
end
|
158
134
|
end
|
135
|
+
|
136
|
+
specify "title matching is case-insensitive" do
|
137
|
+
entry1 = @id_map.add("INSTALLATION USING A TARBALL", nil, false, false)
|
138
|
+
@id_map.generate_associations(["installation using tarball"])
|
139
|
+
id = @id_map.associations["installation using tarball"]
|
140
|
+
id.should == entry1.id
|
141
|
+
end
|
159
142
|
end
|
160
143
|
|
161
144
|
describe "entries" do
|
@@ -193,17 +176,17 @@ describe IdMap do
|
|
193
176
|
|
194
177
|
@id_map.entries.should have(3).items
|
195
178
|
|
196
|
-
entry = @id_map["Installation"]
|
179
|
+
entry = @id_map.entries["Installation"]
|
197
180
|
entry.title.should == "Installation"
|
198
181
|
entry.id.should == "installation-1"
|
199
182
|
entry.should_not be_fuzzy
|
200
183
|
|
201
|
-
entry = @id_map["Configuration"]
|
184
|
+
entry = @id_map.entries["Configuration"]
|
202
185
|
entry.title.should == "Configuration"
|
203
186
|
entry.id.should == "configuration-2"
|
204
187
|
entry.should_not be_fuzzy
|
205
188
|
|
206
|
-
entry = @id_map["Troubleshooting"]
|
189
|
+
entry = @id_map.entries["Troubleshooting"]
|
207
190
|
entry.title.should == "Troubleshooting"
|
208
191
|
entry.id.should == "troubleshooting-1"
|
209
192
|
entry.should be_fuzzy
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mizuho
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.13
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-02-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: sqlite3
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
30
46
|
description: A documentation formatting tool. Mizuho converts Asciidoc input files
|
31
47
|
into nicely outputted HTML, possibly one file per chapter. Multiple templates are
|
32
48
|
supported, so you can write your own.
|
@@ -46,6 +62,7 @@ files:
|
|
46
62
|
- lib/mizuho/generator.rb
|
47
63
|
- lib/mizuho/id_map.rb
|
48
64
|
- lib/mizuho/source_highlight.rb
|
65
|
+
- lib/mizuho/utils.rb
|
49
66
|
- lib/mizuho.rb
|
50
67
|
- test/generator_spec.rb
|
51
68
|
- test/id_map_spec.rb
|
@@ -60,6 +77,7 @@ files:
|
|
60
77
|
- templates/juvia.js
|
61
78
|
- templates/mizuho.css
|
62
79
|
- templates/mizuho.js
|
80
|
+
- templates/toc.html
|
63
81
|
- templates/topbar.css
|
64
82
|
- templates/topbar.html
|
65
83
|
- templates/topbar.js
|