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 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
@@ -24,7 +24,7 @@ module Mizuho
24
24
  TEMPLATES_DIR = "#{SOURCE_ROOT}/templates"
25
25
  ASCIIDOC = "#{SOURCE_ROOT}/asciidoc/asciidoc.py"
26
26
 
27
- VERSION_STRING = "0.9.12"
27
+ VERSION_STRING = "0.9.13"
28
28
 
29
29
  if $LOAD_PATH.first != LIBDIR
30
30
  $LOAD_PATH.unshift(LIBDIR)
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2008-2012 Hongli Lai
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
- self.class.run_asciidoc(@input_file, @output_file, @icons_dir, @conf_file, @attributes)
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 = Nokogiri.HTML(f)
123
- head = (doc / "head")[0]
124
- body = (doc / "body")[0]
134
+ doc = Nokogiri.HTML(f)
135
+ head = (doc / "head")[0]
136
+ body = (doc / "body")[0]
125
137
  title = (doc / "title")[0].text
126
- preamble = (doc / "#preamble")[0]
127
- toctitle = (doc / "#toctitle")[0]
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
- headers = (doc / "#content h2, #content h3, #content h4")
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['data-comment-topic'] = @id_map.associate(header.text)
135
- header.add_previous_sibling(create_comment_balloon)
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
- if preamble
168
+
169
+ # Move preamble from content area to header area.
170
+ if preamble = (doc / "#preamble")[0]
145
171
  preamble.remove
146
- preamble_copy = (doc / "#header > h1")[0].add_next_sibling(preamble.to_s)[0]
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
- toctitle.add_previous_sibling(create_comment_balloon)
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 associate(title)
157
+ def xassociate(title)
106
158
  if entry = @entries[title]
107
159
  if entry.associated?
108
- raise AlreadyAssociatedError, "Cannot associate an already-associated title"
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 = IdMap.extract_chapter(title)) &&
156
- (b = IdMap.extract_chapter(other.title))
212
+ if (a = Utils.extract_chapter(title)) &&
213
+ (b = Utils.extract_chapter(other.title))
157
214
  # Sort by chapter whenever possible.
158
- a[0] = IdMap.chapter_to_int_array(a[0])
159
- b[0] = IdMap.chapter_to_int_array(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+\.)+ /, '')
@@ -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 10% 1em 10%;
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;
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 "#associate" do
33
- describe "if the given title is not in the map" do
34
- describe "if no similar titles exist in the map" do
35
- before :each do
36
- @id1 = @id_map.associate "Installation"
37
- @id2 = @id_map.associate "Installation on Linux"
38
- @id3 = @id_map.associate "Configuration"
39
- end
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
- describe "if the same title exists in the map, but with a different section number" do
60
- before :each do
61
- @entry1 = @id_map.add("1.2. Installation using a tarball", nil, false, false)
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
- describe "if one or more similar titles exist in the map" do
93
- before :each do
94
- @entry1 = @id_map.add("Installation using a tarball", nil, false, false)
95
- @entry2 = @id_map.add("Installation using a Linux tarball", nil, false, false)
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
- specify "title matching is case-insensitive" do
122
- entry1 = @id_map.add("INSTALLATION USING A TARBALL", nil, false, false)
123
- id = @id_map.associate "installation using tarball"
124
- id.should == entry1.id
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 given title is in the map and it hasn't been associated before" do
60
+ describe "if the same title exists in the map, but with a different section number" do
129
61
  before :each do
130
- @entry = @id_map.add("Installation", nil, false, false)
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 "returns that title's previous ID" do
134
- id = @id_map.associate "Installation"
135
- id.should == @entry.id
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 "marks the entry as associated" do
139
- @id_map.associate "Installation"
140
- @entry.should be_associated
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 "preserves the entry's fuzziness" do
144
- @id_map.associate "Installation"
145
- @entry.should_not be_fuzzy
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
- @entry2 = @id_map.add("Installation 2", nil, true, false)
148
- @id_map.associate "Installation 2"
149
- @entry2.should be_fuzzy
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 the given title is in the map and it has been associated before" do
154
- it "raises an error" do
155
- @entry = @id_map.add("Installation", nil, false, true)
156
- lambda { @id_map.associate "Installation" }.should raise_error(IdMap::AlreadyAssociatedError)
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.12
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-01-20 00:00:00.000000000 Z
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