bitclust-core 1.2.1 → 1.2.6

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/data/bitclust/catalog/ja_JP.UTF-8 +4 -0
  3. data/data/bitclust/template.lillia/layout +1 -1
  4. data/data/bitclust/template.offline/class +127 -34
  5. data/data/bitclust/template.offline/class-index +33 -6
  6. data/data/bitclust/template.offline/doc +41 -8
  7. data/data/bitclust/template.offline/function +42 -9
  8. data/data/bitclust/template.offline/function-index +33 -7
  9. data/data/bitclust/template.offline/layout +21 -14
  10. data/data/bitclust/template.offline/library +48 -12
  11. data/data/bitclust/template.offline/library-index +33 -6
  12. data/data/bitclust/template.offline/method +56 -11
  13. data/lib/bitclust/classentry.rb +13 -2
  14. data/lib/bitclust/compat.rb +8 -0
  15. data/lib/bitclust/completion.rb +1 -0
  16. data/lib/bitclust/docentry.rb +4 -2
  17. data/lib/bitclust/entry.rb +3 -0
  18. data/lib/bitclust/functionentry.rb +8 -7
  19. data/lib/bitclust/functionreferenceparser.rb +2 -0
  20. data/lib/bitclust/libraryentry.rb +4 -1
  21. data/lib/bitclust/lineinput.rb +6 -2
  22. data/lib/bitclust/methoddatabase.rb +3 -0
  23. data/lib/bitclust/methodentry.rb +10 -8
  24. data/lib/bitclust/methodid.rb +1 -0
  25. data/lib/bitclust/nameutils.rb +15 -11
  26. data/lib/bitclust/preprocessor.rb +26 -21
  27. data/lib/bitclust/rdcompiler.rb +29 -19
  28. data/lib/bitclust/requesthandler.rb +3 -3
  29. data/lib/bitclust/ridatabase.rb +2 -1
  30. data/lib/bitclust/rrdparser.rb +19 -20
  31. data/lib/bitclust/screen.rb +39 -4
  32. data/lib/bitclust/silent_progress_bar.rb +8 -4
  33. data/lib/bitclust/simplesearcher.rb +1 -1
  34. data/lib/bitclust/subcommand.rb +9 -0
  35. data/lib/bitclust/subcommands/chm_command.rb +3 -3
  36. data/lib/bitclust/subcommands/methods_command.rb +1 -1
  37. data/lib/bitclust/subcommands/server_command.rb +6 -1
  38. data/lib/bitclust/subcommands/setup_command.rb +2 -2
  39. data/lib/bitclust/subcommands/statichtml_command.rb +44 -21
  40. data/lib/bitclust/syntax_highlighter.rb +5 -3
  41. data/lib/bitclust/version.rb +1 -1
  42. data/test/test_bitclust.rb +1 -1
  43. data/test/test_entry.rb +14 -1
  44. data/test/test_functionreferenceparser.rb +4 -4
  45. data/test/test_preprocessor.rb +21 -0
  46. data/test/test_rdcompiler.rb +240 -0
  47. data/test/test_rrdparser.rb +16 -0
  48. data/test/test_syntax_highlighter.rb +22 -4
  49. data/theme/default/rurema.png +0 -0
  50. data/theme/default/rurema.svg +31 -0
  51. data/theme/default/script.js +34 -0
  52. data/theme/default/style.css +112 -8
  53. metadata +32 -19
@@ -71,6 +71,7 @@ class Ent
71
71
  attr_reader :entry
72
72
 
73
73
  def ==(other)
74
+ return false if self.class != other.class
74
75
  @name == other.name
75
76
  end
76
77
 
@@ -121,7 +122,7 @@ class RiMethodEntry < Ent
121
122
  end
122
123
 
123
124
  def fullname
124
- c, t, m = @entry.fullname.split(/([\.\#])/, 2)
125
+ c, t = @entry.fullname.split(/([\.\#])/, 2)
125
126
  "#{c}#{t}#{@name}"
126
127
  end
127
128
  end
@@ -10,11 +10,11 @@
10
10
  require 'bitclust/compat'
11
11
  require 'bitclust/preprocessor'
12
12
  require 'bitclust/methodid'
13
+ require 'bitclust/methoddatabase'
13
14
  require 'bitclust/lineinput'
14
15
  require 'bitclust/parseutils'
15
16
  require 'bitclust/nameutils'
16
17
  require 'bitclust/exception'
17
- require 'bitclust/methoddatabase'
18
18
 
19
19
  module BitClust
20
20
 
@@ -70,7 +70,7 @@ module BitClust
70
70
 
71
71
  def parse_file(path, libname, params = {})
72
72
  fopen(path, 'r:UTF-8') {|f|
73
- return parse(f, libname, params)
73
+ return parse(f, libname, params).tap { |lib| lib.source_location = Location.new(path, 1) }
74
74
  }
75
75
  end
76
76
 
@@ -114,18 +114,14 @@ module BitClust
114
114
  type, name, superclass = *parse_level1_header(line)
115
115
  case type
116
116
  when 'class'
117
- @context.define_class name, (superclass || 'Object')
117
+ @context.define_class name, (superclass || 'Object'), location: line.location
118
118
  read_class_body f
119
119
  when 'module'
120
120
  parse_error "superclass given for module", line if superclass
121
- @context.define_module name
121
+ @context.define_module name, location: line.location
122
122
  read_class_body f
123
123
  when 'object'
124
- if superclass
125
- # FIXME
126
- tty_warn "#{line.location}: singleton object class not implemented yet"
127
- end
128
- @context.define_object name
124
+ @context.define_object name, superclass, location: line.location
129
125
  read_object_body f
130
126
  when 'reopen'
131
127
  @context.reopen_class name
@@ -353,29 +349,31 @@ module BitClust
353
349
  @library.sublibrary @db.get_library(libname)
354
350
  end
355
351
 
356
- def define_class(name, supername)
352
+ def define_class(name, supername, location: nil)
357
353
  if @db.properties['version'] >= "1.9.0"
358
354
  top = 'BasicObject'
359
355
  else
360
356
  top = 'Object'
361
357
  end
362
358
  superclass = (name == top ? nil : @db.get_class(supername))
363
- register_class :class, name, superclass
359
+ register_class :class, name, superclass, location: location
364
360
  end
365
361
 
366
- def define_module(name)
367
- register_class :module, name, nil
362
+ def define_module(name, location: nil)
363
+ register_class :module, name, nil, location: location
368
364
  end
369
365
 
370
- def define_object(name)
371
- register_class :object, name, nil
366
+ def define_object(name, singleton_object_class, location: nil)
367
+ singleton_object_class = @db.get_class(singleton_object_class) if singleton_object_class
368
+ register_class :object, name, singleton_object_class, location: location
372
369
  end
373
370
 
374
- def register_class(type, name, superclass)
371
+ def register_class(type, name, superclass, location: nil)
375
372
  @klass = @db.open_class(name) {|c|
376
373
  c.type = type
377
374
  c.superclass = superclass
378
375
  c.library = @library
376
+ c.source_location = location
379
377
  @library.add_class c
380
378
  }
381
379
  @kind = :defined
@@ -452,10 +450,11 @@ module BitClust
452
450
  def define_method(chunk)
453
451
  id = method_id(chunk)
454
452
  @db.open_method(id) {|m|
455
- m.names = chunk.names.sort
456
- m.kind = @kind
457
- m.visibility = @visibility || :public
458
- m.source = chunk.source
453
+ m.names = chunk.names.sort
454
+ m.kind = chunk.source.match?(/^@undef$/) ? :undefined : @kind
455
+ m.visibility = @visibility || :public
456
+ m.source = chunk.source
457
+ m.source_location = chunk.source.location
459
458
  case @kind
460
459
  when :added, :redefined
461
460
  @library.add_method m
@@ -13,7 +13,9 @@ require 'bitclust/htmlutils'
13
13
  require 'bitclust/nameutils'
14
14
  require 'bitclust/messagecatalog'
15
15
  require 'erb'
16
+ require 'json'
16
17
  require 'stringio'
18
+ require 'uri'
17
19
 
18
20
  module BitClust
19
21
 
@@ -185,7 +187,7 @@ module BitClust
185
187
  private
186
188
 
187
189
  def preproc(template)
188
- template.gsub(/^\.include ([\w\-]+)/) { load($1.untaint) }.untaint
190
+ template.gsub(/^\.include ([\w\-]+)/) { load($1) }
189
191
  end
190
192
  end
191
193
 
@@ -366,6 +368,10 @@ module BitClust
366
368
  @urlmapper.canonical_url(current_url)
367
369
  end
368
370
 
371
+ def edit_url(location)
372
+ @urlmapper.edit_url(location)
373
+ end
374
+
369
375
  def opensearchdescription_url
370
376
  @urlmapper.opensearchdescription_url
371
377
  end
@@ -394,8 +400,11 @@ module BitClust
394
400
  @hlevel -= 1
395
401
  end
396
402
 
397
- def headline(str)
398
- "<h#{@hlevel}>#{escape_html(str)}</h#{@hlevel}>"
403
+ def headline(str, edit_url: nil)
404
+ edit_link = edit_url ? <<~HTML : ''
405
+ <span class="permalink">[<a href="#{edit_url}">edit</a>]</span>
406
+ HTML
407
+ "<h#{@hlevel}>#{escape_html(str)}</h#{@hlevel}>" + edit_link
399
408
  end
400
409
 
401
410
  def headline_noescape(str)
@@ -415,8 +424,12 @@ module BitClust
415
424
  end
416
425
  end
417
426
 
427
+ def manual_home_name
428
+ _('Ruby %s Reference Manual', ruby_version())
429
+ end
430
+
418
431
  def manual_home_link
419
- document_link('index', _('Ruby %s Reference Manual', ruby_version()))
432
+ document_link('index', manual_home_name)
420
433
  end
421
434
 
422
435
  def friendly_library_link(id)
@@ -452,6 +465,28 @@ module BitClust
452
465
  yield sigs, body
453
466
  end
454
467
  end
468
+
469
+ def breadcrumb_json_ld(items)
470
+ {
471
+ '@context': 'http://schema.org',
472
+ '@type': 'BreadcrumbList',
473
+ 'itemListElement' => items.map.with_index(1) do |item, index|
474
+ {
475
+ '@type' => 'ListItem',
476
+ 'item' => item[:url],
477
+ 'name' => item[:name],
478
+ 'position' => index
479
+ }
480
+ end
481
+ }.to_json
482
+ end
483
+
484
+ def absolute_url_to(path)
485
+ ::URI.join(
486
+ canonical_url,
487
+ path
488
+ )
489
+ end
455
490
  end
456
491
 
457
492
  class IndexScreen < TemplateScreen
@@ -3,13 +3,17 @@ module BitClust
3
3
  # Null-object version of ProgressBar.
4
4
  class SilentProgressBar
5
5
 
6
- attr_reader :title
6
+ attr_accessor :title
7
7
 
8
- def initialize(title, total, out = $stderr)
9
- @title, @total, @out = title, total, out
8
+ def self.create(output: $stderr, title:, total:)
9
+ self.new(output: output, title: title, total: total)
10
10
  end
11
11
 
12
- def inc(step = 1)
12
+ def initialize(output:, title:, total:)
13
+ @title, @total, @output = title, total, output
14
+ end
15
+
16
+ def increment
13
17
  end
14
18
 
15
19
  def finish
@@ -13,7 +13,7 @@ module BitClust
13
13
  pat = to_pattern(pat)
14
14
  return [] if pat.empty? or /\A\s+\z/ =~ pat
15
15
  cname, type, mname = parse_method_spec_pattern(pat)
16
- ret = cs = ms = []
16
+ cs = ms = []
17
17
  if cname and not cname.empty?
18
18
  if mname
19
19
  ms = find_class_method(db, cname, type, mname)
@@ -52,6 +52,15 @@ module BitClust
52
52
  def srcdir_root
53
53
  Pathname.new(__FILE__).realpath.dirname.parent.parent
54
54
  end
55
+
56
+ def align_progress_bar_title(title)
57
+ size = title.size
58
+ if size > 14
59
+ title[0..13]
60
+ else
61
+ title + ' ' * (14 - size)
62
+ end
63
+ end
55
64
  end
56
65
  end
57
66
 
@@ -176,7 +176,7 @@ EOS
176
176
  end
177
177
 
178
178
  entries = db.docs + db.libraries.sort + db.classes.sort + methods.values.sort
179
- pb = ProgressBar.new('entry', entries.size)
179
+ pb = ProgressBar.create(title: 'entry', total: entries.size)
180
180
  entries.each do |c|
181
181
  filename = create_html_file(c, manager, @outputdir, db)
182
182
  @html_files << filename
@@ -206,8 +206,8 @@ EOS
206
206
  Sitemap::Content.new("#{e.klass.name}#{e.typemark}#{name} (#{e.library.name})", filename)
207
207
  end
208
208
  end
209
- pb.title.replace(e.name)
210
- pb.inc
209
+ pb.title = align_progress_bar_title(e.name)
210
+ pb.increment
211
211
  end
212
212
  pb.finish
213
213
  end
@@ -102,7 +102,7 @@ module BitClust
102
102
  ORDER = { '.' => 1, '#' => 2, '::' => 3 }
103
103
 
104
104
  def m_order(m)
105
- m, t, c = *m.reverse.split(/(\#|\.|::)/, 2)
105
+ m, t = *m.reverse.split(/(\#|\.|::)/, 2)
106
106
  [ORDER[t] || 0, m.reverse]
107
107
  end
108
108
 
@@ -27,7 +27,12 @@ module BitClust
27
27
  @srcdir = @datadir = @themedir = @theme = @templatedir = nil
28
28
  @encoding = 'utf-8' # encoding of view
29
29
  if Object.const_defined?(:Encoding)
30
- Encoding.default_external = @encoding
30
+ begin
31
+ verbose, $VERBOSE = $VERBOSE, false
32
+ Encoding.default_external = @encoding
33
+ ensure
34
+ $VERBOSE = verbose
35
+ end
31
36
  end
32
37
 
33
38
  @debugp = false
@@ -19,13 +19,13 @@ module BitClust
19
19
  @prepare = nil
20
20
  @cleanup = nil
21
21
  @purge = nil
22
- @versions = ["2.1.0", "2.2.0", "2.3.0", "2.4.0"]
22
+ @versions = ["2.4.0", "2.5.0", "2.6.0"]
23
23
  @update = true
24
24
  @parser.banner = "Usage: #{File.basename($0, '.*')} setup [options]"
25
25
  @parser.on('--prepare', 'Prepare config file and checkout repository. Do not create database.') {
26
26
  @prepare = true
27
27
  }
28
- @parser.on('--cleanup', 'Cleanup datebase before create database.') {
28
+ @parser.on('--cleanup', 'Cleanup database before create database.') {
29
29
  @cleanup = true
30
30
  }
31
31
  @parser.on('--purge', 'Purge all downloaded and generated files and exit.') {
@@ -28,6 +28,7 @@ module BitClust
28
28
  @suffix = h[:suffix]
29
29
  @fs_casesensitive = h[:fs_casesensitive]
30
30
  @canonical_base_url = h[:canonical_base_url]
31
+ @edit_base_url = h[:edit_base_url]
31
32
  end
32
33
 
33
34
  def library_url(name)
@@ -67,6 +68,10 @@ module BitClust
67
68
  @bitclust_html_base + "/" + filename
68
69
  end
69
70
 
71
+ def custom_js_url(filename)
72
+ @bitclust_html_base + "/" + filename
73
+ end
74
+
70
75
  def favicon_url
71
76
  @bitclust_html_base + "/" + @favicon_url
72
77
  end
@@ -83,6 +88,10 @@ module BitClust
83
88
  (@canonical_base_url + "/#{current_url}").sub(@bitclust_html_base, "").sub(/([^:])\/\/+/, "\\1/")
84
89
  end
85
90
 
91
+ def edit_url(location)
92
+ "#{@edit_base_url}/#{location.file}#L#{location.line}".sub(/([^:])\/\/+/, "\\1/")
93
+ end
94
+
86
95
  def encodename_package(str)
87
96
  if @fs_casesensitive
88
97
  encodename_url(str)
@@ -94,7 +103,12 @@ module BitClust
94
103
 
95
104
  def initialize
96
105
  if Object.const_defined?(:Encoding)
97
- Encoding.default_external = 'utf-8'
106
+ begin
107
+ verbose, $VERBOSE = $VERBOSE, false
108
+ Encoding.default_external = 'utf-8'
109
+ ensure
110
+ $VERBOSE = verbose
111
+ end
98
112
  end
99
113
  super
100
114
  @verbose = true
@@ -104,6 +118,7 @@ module BitClust
104
118
  @suffix = ".html"
105
119
  @gtm_tracking_id = nil
106
120
  @meta_robots_content = ["noindex"]
121
+ @stop_on_syntax_error = true
107
122
  @parser.banner = "Usage: #{File.basename($0, '.*')} statichtml [options]"
108
123
  @parser.on('-o', '--outputdir=PATH', 'Output directory') do |path|
109
124
  begin
@@ -131,12 +146,18 @@ module BitClust
131
146
  @parser.on('--canonical-base-url=URL', 'Canonical base URL') do |url|
132
147
  @canonical_base_url = url
133
148
  end
149
+ @parser.on('--edit-base-url=URL', 'Edit base URL') do |url|
150
+ @edit_base_url = url
151
+ end
134
152
  @parser.on('--tracking-id=ID', 'Google Tag Manager Tracking ID') do |id|
135
153
  @gtm_tracking_id = id
136
154
  end
137
155
  @parser.on('--meta-robots-content=VALUE1,VALUE2,...', Array, 'HTML <meta> element: <meta name="robots" content="VALUE1,VALUE2..."') do |values|
138
156
  @meta_robots_content = values
139
157
  end
158
+ @parser.on('--no-stop-on-syntax-error', 'Do not stop on syntax error') do |boolean|
159
+ @stop_on_syntax_error = boolean
160
+ end
140
161
  @parser.on('--[no-]quiet', 'Be quiet') do |quiet|
141
162
  @verbose = !quiet
142
163
  end
@@ -165,7 +186,6 @@ module BitClust
165
186
  end
166
187
 
167
188
  fdb.transaction do
168
- functions = {}
169
189
  create_html_entries("capi", fdb.functions, manager, fdb)
170
190
  end
171
191
 
@@ -181,19 +201,21 @@ module BitClust
181
201
  :verbose => @verbose)
182
202
  create_index_html(@outputdir)
183
203
  FileUtils.cp(@manager_config[:themedir] + @manager_config[:css_url],
184
- @outputdir.to_s, {:verbose => @verbose, :preserve => true})
204
+ @outputdir.to_s, :verbose => @verbose, :preserve => true)
185
205
  FileUtils.cp(@manager_config[:themedir] + "syntax-highlight.css",
186
- @outputdir.to_s, {:verbose => @verbose, :preserve => true})
206
+ @outputdir.to_s, :verbose => @verbose, :preserve => true)
207
+ FileUtils.cp(@manager_config[:themedir] + "script.js",
208
+ @outputdir.to_s, :verbose => @verbose, :preserve => true)
187
209
  FileUtils.cp(@manager_config[:themedir] + @manager_config[:favicon_url],
188
- @outputdir.to_s, {:verbose => @verbose, :preserve => true})
210
+ @outputdir.to_s, :verbose => @verbose, :preserve => true)
189
211
  Dir.mktmpdir do |tmpdir|
190
212
  FileUtils.cp_r(@manager_config[:themedir] + 'images', tmpdir,
191
- {:verbose => @verbose, :preserve => true})
213
+ :verbose => @verbose, :preserve => true)
192
214
  Dir.glob(File.join(tmpdir, 'images', '/**/.svn')).each do |d|
193
- FileUtils.rm_r(d, {:verbose => @verbose})
215
+ FileUtils.rm_r(d, :verbose => @verbose)
194
216
  end
195
217
  FileUtils.cp_r(File.join(tmpdir, 'images'), @outputdir.to_s,
196
- {:verbose => @verbose, :preserve => true})
218
+ :verbose => @verbose, :preserve => true)
197
219
  end
198
220
  end
199
221
 
@@ -211,42 +233,46 @@ module BitClust
211
233
  :tochm_mode => true,
212
234
  :fs_casesensitive => @fs_casesensitive,
213
235
  :canonical_base_url => @canonical_base_url,
236
+ :edit_base_url => @edit_base_url,
214
237
  :gtm_tracking_id => @gtm_tracking_id,
215
238
  :meta_robots_content => @meta_robots_content,
239
+ :stop_on_syntax_error => @stop_on_syntax_error,
216
240
  }
217
241
  @manager_config[:urlmapper] = URLMapperEx.new(@manager_config)
218
242
  @urlmapper = @manager_config[:urlmapper]
219
243
  end
220
244
 
221
245
  def create_html_entries(title, entries, manager, db)
246
+ title = align_progress_bar_title(title)
222
247
  original_title = title.dup
223
248
  if @verbose
224
- progressbar = ProgressBar.new(title, entries.size)
249
+ progressbar = ProgressBar.create(title: title, total: entries.size)
225
250
  else
226
- progressbar = SilentProgressBar.new(title, entries.size)
251
+ progressbar = SilentProgressBar.create(title: title, total: entries.size)
227
252
  end
228
253
  entries.each do |entry|
229
254
  create_html_file(entry, manager, @outputdir, db)
230
- progressbar.title.replace([entry].flatten.first.name)
231
- progressbar.inc
255
+ progressbar.title = align_progress_bar_title([entry].flatten.first.name)
256
+ progressbar.increment
232
257
  end
233
- progressbar.title.replace(original_title)
258
+ progressbar.title = original_title
234
259
  progressbar.finish
235
260
  end
236
261
 
237
262
  def create_html_methods(title, methods, manager, db)
263
+ title = align_progress_bar_title(title)
238
264
  original_title = title.dup
239
265
  if @verbose
240
- progressbar = ProgressBar.new(title, methods.size)
266
+ progressbar = ProgressBar.create(title: title, total: methods.size)
241
267
  else
242
- progressbar = SilentProgressBar.new(title, methods.size)
268
+ progressbar = SilentProgressBar.create(title: title, total: methods.size)
243
269
  end
244
270
  methods.each do |method_name, method_entries|
245
271
  create_html_method_file(method_name, method_entries, manager, @outputdir, db)
246
- progressbar.title.replace(method_name)
247
- progressbar.inc
272
+ progressbar.title = align_progress_bar_title(method_name)
273
+ progressbar.increment
248
274
  end
249
- progressbar.title.replace(original_title)
275
+ progressbar.title = original_title
250
276
  progressbar.finish
251
277
  end
252
278
 
@@ -268,7 +294,6 @@ HERE
268
294
  @urlmapper.bitclust_html_base = '..'
269
295
  path = outputdir + e.type_id.to_s + html_filename(encodename_package(e.name), @suffix)
270
296
  create_html_file_p(entry, manager, path, db)
271
- path.relative_path_from(outputdir).to_s
272
297
  when :function
273
298
  create_html_function_file(entry, manager, outputdir, db)
274
299
  else
@@ -285,7 +310,6 @@ HERE
285
310
  path = outputdir + e.type_id.to_s + encodename_package(e.klass.name) +
286
311
  e.typechar + html_filename(encodename_package(name), @suffix)
287
312
  create_html_file_p(entries, manager, path, db)
288
- path.relative_path_from(outputdir).to_s
289
313
  end
290
314
 
291
315
  def create_html_function_file(entry, manager, outputdir, db)
@@ -293,7 +317,6 @@ HERE
293
317
  @urlmapper.bitclust_html_base = '..'
294
318
  path = outputdir + entry.type_id.to_s + html_filename(entry.name, @suffix)
295
319
  create_html_file_p(entry, manager, path, db)
296
- path.relative_path_from(outputdir).to_s
297
320
  end
298
321
 
299
322
  def create_html_file_p(entry, manager, path, db)