yard 0.9.37 → 0.9.41

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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -1
  3. data/README.md +27 -30
  4. data/docs/GettingStarted.md +41 -15
  5. data/docs/Tags.md +5 -5
  6. data/docs/Templates.md +5 -4
  7. data/docs/WhatsNew.md +59 -7
  8. data/docs/templates/default/yard_tags/html/setup.rb +1 -1
  9. data/lib/yard/autoload.rb +17 -0
  10. data/lib/yard/cli/diff.rb +7 -2
  11. data/lib/yard/code_objects/base.rb +1 -1
  12. data/lib/yard/code_objects/extra_file_object.rb +1 -0
  13. data/lib/yard/code_objects/proxy.rb +1 -1
  14. data/lib/yard/handlers/base.rb +23 -1
  15. data/lib/yard/handlers/processor.rb +1 -0
  16. data/lib/yard/handlers/rbs/attribute_handler.rb +43 -0
  17. data/lib/yard/handlers/rbs/base.rb +38 -0
  18. data/lib/yard/handlers/rbs/constant_handler.rb +18 -0
  19. data/lib/yard/handlers/rbs/method_handler.rb +327 -0
  20. data/lib/yard/handlers/rbs/mixin_handler.rb +20 -0
  21. data/lib/yard/handlers/rbs/namespace_handler.rb +26 -0
  22. data/lib/yard/handlers/ruby/attribute_handler.rb +7 -4
  23. data/lib/yard/handlers/ruby/constant_handler.rb +24 -6
  24. data/lib/yard/handlers/ruby/legacy/visibility_handler.rb +2 -1
  25. data/lib/yard/handlers/ruby/visibility_handler.rb +1 -0
  26. data/lib/yard/i18n/locale.rb +1 -1
  27. data/lib/yard/i18n/pot_generator.rb +1 -1
  28. data/lib/yard/parser/rbs/rbs_parser.rb +325 -0
  29. data/lib/yard/parser/rbs/statement.rb +75 -0
  30. data/lib/yard/parser/ruby/ast_node.rb +5 -4
  31. data/lib/yard/parser/ruby/legacy/irb/slex.rb +19 -1
  32. data/lib/yard/parser/ruby/legacy/ruby_lex.rb +1 -1
  33. data/lib/yard/parser/ruby/ruby_parser.rb +109 -24
  34. data/lib/yard/parser/source_parser.rb +3 -2
  35. data/lib/yard/registry_resolver.rb +7 -0
  36. data/lib/yard/rubygems/specification.rb +1 -1
  37. data/lib/yard/server/library_version.rb +1 -1
  38. data/lib/yard/server/templates/default/fulldoc/html/js/autocomplete.js +208 -12
  39. data/lib/yard/server/templates/default/layout/html/breadcrumb.erb +1 -17
  40. data/lib/yard/server/templates/default/method_details/html/permalink.erb +4 -2
  41. data/lib/yard/server/templates/doc_server/library_list/html/headers.erb +3 -3
  42. data/lib/yard/server/templates/doc_server/library_list/html/library_list.erb +2 -3
  43. data/lib/yard/server/templates/doc_server/processing/html/processing.erb +22 -16
  44. data/lib/yard/tags/directives.rb +7 -0
  45. data/lib/yard/tags/library.rb +3 -3
  46. data/lib/yard/tags/overload_tag.rb +2 -1
  47. data/lib/yard/tags/tag.rb +1 -1
  48. data/lib/yard/tags/types_explainer.rb +5 -4
  49. data/lib/yard/templates/helpers/base_helper.rb +1 -1
  50. data/lib/yard/templates/helpers/html_helper.rb +21 -6
  51. data/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +6 -1
  52. data/lib/yard/templates/helpers/markup/hybrid_markdown.rb +2147 -0
  53. data/lib/yard/templates/helpers/markup/rdoc_markup.rb +2 -0
  54. data/lib/yard/templates/helpers/markup_helper.rb +4 -2
  55. data/lib/yard/version.rb +1 -1
  56. data/po/ja.po +82 -82
  57. data/templates/default/fulldoc/html/css/style.css +33 -15
  58. data/templates/default/fulldoc/html/full_list.erb +4 -4
  59. data/templates/default/fulldoc/html/js/app.js +567 -271
  60. data/templates/default/fulldoc/html/js/full_list.js +341 -211
  61. data/templates/default/layout/html/headers.erb +1 -1
  62. data/templates/default/layout/html/layout.erb +2 -1
  63. data/templates/default/method/html/header.erb +3 -3
  64. data/templates/default/module/html/defines.erb +3 -3
  65. data/templates/default/module/html/inherited_methods.erb +1 -0
  66. data/templates/default/module/html/method_summary.erb +8 -0
  67. data/templates/default/module/setup.rb +20 -0
  68. data/templates/default/onefile/html/layout.erb +3 -4
  69. data/templates/guide/fulldoc/html/js/app.js +57 -26
  70. data/templates/guide/layout/html/layout.erb +9 -11
  71. metadata +18 -8
@@ -236,14 +236,26 @@ module YARD
236
236
 
237
237
  def visit_event(node)
238
238
  map = @map[MAPPINGS[node.type]]
239
- lstart, sstart = *(map ? map.pop : [lineno, @ns_charno - 1])
239
+
240
+ # Pattern matching and `in` syntax creates :case nodes without 'case' tokens,
241
+ # fall back to the first child node.
242
+ if node.type == :case && (!map || map.empty?) && (child_node = node[0])
243
+ lstart = child_node.line_range.first
244
+ sstart = child_node.source_range.first
245
+ else
246
+ lstart, sstart = *(map ? map.pop : [lineno, @ns_charno - 1])
247
+ (@map[:rbrace] ||= []).shift if map && MAPPINGS[node.type] == :lbrace
248
+ end
249
+
250
+ raise "Cannot determine start of node #{node} around #{file}:#{lineno}" if lstart.nil? || sstart.nil?
251
+
240
252
  node.source_range = Range.new(sstart, @ns_charno - 1)
241
253
  node.line_range = Range.new(lstart, lineno)
242
254
  if node.respond_to?(:block)
243
255
  sr = node.block.source_range
244
256
  lr = node.block.line_range
245
- node.block.source_range = Range.new(sr.first, @tokens.last[2][1] - 1)
246
- node.block.line_range = Range.new(lr.first, @tokens.last[2][0])
257
+ node.block.source_range = Range.new(sr.begin, @tokens.last[2][1] - 1)
258
+ node.block.line_range = Range.new(lr.begin, @tokens.last[2][0])
247
259
  end
248
260
  node
249
261
  end
@@ -259,7 +271,10 @@ module YARD
259
271
  def visit_ns_token(token, data, ast_token = false)
260
272
  add_token(token, data)
261
273
  ch = charno
262
- @last_ns_token = [token, data]
274
+
275
+ # For purposes of tracking parsing state, don't treat keywords as such
276
+ # where used as a symbol identifier.
277
+ @last_ns_token = [@last_ns_token && @last_ns_token.first == :symbeg ? :symbol : token, data]
263
278
  @charno += data.length
264
279
  @ns_charno = charno
265
280
  @newline = [:semicolon, :comment, :kw, :op, :lparen, :lbrace].include?(token)
@@ -272,14 +287,14 @@ module YARD
272
287
  if @percent_ary
273
288
  if token == :words_sep && data !~ /\s\z/
274
289
  rng = @percent_ary.source_range
275
- rng = Range.new(rng.first, rng.last + data.length)
290
+ rng = Range.new(rng.begin, rng.end.to_i + data.length)
276
291
  @percent_ary.source_range = rng
277
292
  @tokens << [token, data, [lineno, charno]]
278
293
  @percent_ary = nil
279
294
  return
280
295
  elsif token == :tstring_end && data =~ /\A\s/
281
296
  rng = @percent_ary.source_range
282
- rng = Range.new(rng.first, rng.last + data.length)
297
+ rng = Range.new(rng.begin, rng.end.to_i + data.length)
283
298
  @percent_ary.source_range = rng
284
299
  @tokens << [token, data, [lineno, charno]]
285
300
  @percent_ary = nil
@@ -294,7 +309,7 @@ module YARD
294
309
  @heredoc_tokens << [token, data, [lineno, charno]]
295
310
 
296
311
  # fix ripper encoding of heredoc bug
297
- # (see http://bugs.ruby-lang.org/issues/6200)
312
+ # (see https://bugs.ruby-lang.org/issues/6200)
298
313
  data.force_encoding(file_encoding) if file_encoding
299
314
 
300
315
  @heredoc_state = :ended if token == :heredoc_end
@@ -322,6 +337,7 @@ module YARD
322
337
  undef on_aref_field
323
338
  undef on_lbracket
324
339
  undef on_rbracket
340
+ undef on_rbrace
325
341
  undef on_string_literal
326
342
  undef on_lambda
327
343
  undef on_unary
@@ -357,6 +373,20 @@ module YARD
357
373
  visit_event AstNode.new(:hash, args.first || [])
358
374
  end
359
375
 
376
+ # Ruby 3.0+ pattern matching: braced hash patterns ({key: val} syntax) fire
377
+ # on_lbrace and on_rbrace scanner events. The corresponding parser event is
378
+ # on_hshptn (not on_hash), so we must clean up the brace maps to prevent stale
379
+ # entries from corrupting source ranges of later hash literals and brace blocks.
380
+ # Bare hash patterns (key: val without braces) fire no brace scanner events, so
381
+ # we only clean up when @map[:rbrace] confirms a closing brace was scanned.
382
+ def on_hshptn(*args)
383
+ if (@map[:rbrace] ||= []).any?
384
+ (@map[:lbrace] ||= []).pop
385
+ @map[:rbrace].shift
386
+ end
387
+ AstNode.new(:hshptn, args)
388
+ end
389
+
360
390
  def on_bare_assoc_hash(*args)
361
391
  AstNode.new(:list, args.first)
362
392
  end
@@ -377,20 +407,22 @@ module YARD
377
407
  def on_aref(*args)
378
408
  @map[:lbracket].pop
379
409
  ll, lc = *@map[:aref].shift
380
- sr = args.first.source_range.first..lc
381
- lr = args.first.line_range.first..ll
410
+ sr = args.first.source_range.begin..lc
411
+ lr = args.first.line_range.begin..ll
382
412
  AstNode.new(:aref, args, :char => sr, :line => lr)
383
413
  end
384
414
 
385
415
  def on_aref_field(*args)
386
416
  @map[:lbracket].pop
387
- AstNode.new(:aref_field, args,
388
- :listline => lineno..lineno, :listchar => charno...charno)
417
+ ll, lc = *@map[:aref].shift
418
+ sr = args.first.source_range.begin..lc
419
+ lr = args.first.line_range.begin..ll
420
+ AstNode.new(:aref_field, args, :char => sr, :line => lr)
389
421
  end
390
422
 
391
423
  def on_array(other)
392
424
  node = AstNode.node_class_for(:array).new(:array, [other])
393
- map = @map[MAPPINGS[node.type]]
425
+ map = @map[MAPPINGS[node.type]] if other.nil? || other.type == :list
394
426
  if map && !map.empty?
395
427
  lstart, sstart = *map.pop
396
428
  node.source_range = Range.new(sstart, @ns_charno - 1)
@@ -406,6 +438,27 @@ module YARD
406
438
  node
407
439
  end
408
440
 
441
+ # Ruby 3.0+ pattern matching: array patterns (SomeClass[a, b]) and find patterns
442
+ # (SomeClass[*pre, val, *post]) use [...] brackets, which fire on_lbracket and
443
+ # on_rbracket scanner events. The corresponding parser events are on_aryptn/on_fndptn
444
+ # (not on_aref), so we must clean up the bracket maps to prevent stale entries from
445
+ # corrupting source ranges of later array indexing expressions.
446
+ def on_aryptn(*args)
447
+ (@map[:lbracket] ||= []).pop
448
+ (@map[:aref] ||= []).shift
449
+ # Source range is intentionally not set; no handler is registered for
450
+ # pattern-match nodes, so they produce no documentation output.
451
+ AstNode.new(:aryptn, args)
452
+ end
453
+
454
+ def on_fndptn(*args)
455
+ (@map[:lbracket] ||= []).pop
456
+ (@map[:aref] ||= []).shift
457
+ # Source range is intentionally not set; no handler is registered for
458
+ # pattern-match nodes, so they produce no documentation output.
459
+ AstNode.new(:fndptn, args)
460
+ end
461
+
409
462
  def on_lbracket(tok)
410
463
  (@map[:lbracket] ||= []) << [lineno, charno]
411
464
  visit_ns_token(:lbracket, tok, false)
@@ -416,6 +469,13 @@ module YARD
416
469
  visit_ns_token(:rbracket, tok, false)
417
470
  end
418
471
 
472
+ # Maintained explicitly (unlike on_lbracket/on_rbracket) so on_hshptn can
473
+ # distinguish braced from bare hash patterns in Ruby 3.0+ pattern matching.
474
+ def on_rbrace(tok)
475
+ (@map[:rbrace] ||= []) << [lineno, charno]
476
+ visit_ns_token(:rbrace, tok, false)
477
+ end
478
+
419
479
  def on_dyna_symbol(sym)
420
480
  rng = if sym.source_range.to_a.size == 0 # rubocop:disable Style/ZeroLengthPredicate
421
481
  (sym.source_range.begin - 3)...sym.source_range.end
@@ -449,8 +509,8 @@ module YARD
449
509
  def on_#{kw}(*args)
450
510
  mapping = @map[#{kw.to_s.sub(/_mod$/, '').inspect}]
451
511
  mapping.pop if mapping
452
- sr = args.last.source_range.first..args.first.source_range.last
453
- lr = args.last.line_range.first..args.first.line_range.last
512
+ sr = args.last.source_range.begin..args.first.source_range.end
513
+ lr = args.last.line_range.begin..args.first.line_range.end
454
514
  #{node_class}.new(:#{kw}, args, :line => lr, :char => sr)
455
515
  end
456
516
  eof
@@ -473,8 +533,8 @@ module YARD
473
533
  begin; undef on_#{kw}_add; rescue NameError; end
474
534
  def on_#{kw}_add(list, item)
475
535
  last = @source[@ns_charno,1] == "\n" ? @ns_charno - 1 : @ns_charno
476
- list.source_range = (list.source_range.first..last)
477
- list.line_range = (list.line_range.first..lineno)
536
+ list.source_range = (list.source_range.begin..last)
537
+ list.line_range = (list.line_range.begin..lineno)
478
538
  list.push(item)
479
539
  list
480
540
  end
@@ -485,9 +545,9 @@ module YARD
485
545
  node = visit_event_arr(LiteralNode.new(:string_literal, args))
486
546
  if args.size == 1
487
547
  r = args[0].source_range
488
- if node.source_range != Range.new(r.first - 1, r.last + 1)
548
+ if node.source_range != Range.new(r.begin - 1, r.end + 1)
489
549
  klass = AstNode.node_class_for(node[0].type)
490
- r = Range.new(node.source_range.first + 1, node.source_range.last - 1)
550
+ r = Range.new(node.source_range.begin + 1, node.source_range.end - 1)
491
551
  node[0] = klass.new(node[0].type, [@source[r]], :line => node.line_range, :char => r)
492
552
  end
493
553
  end
@@ -573,7 +633,7 @@ module YARD
573
633
  @comments_flags[lineno] = @comments_flags[lineno - 1]
574
634
  @comments_flags.delete(lineno - 1)
575
635
  range = @comments_range.delete(lineno - 1)
576
- source_range = range.first..source_range.last
636
+ source_range = range.begin..source_range.end
577
637
  comment = append_comment + "\n" + comment
578
638
  end
579
639
 
@@ -609,6 +669,7 @@ module YARD
609
669
  alias compile_error on_parse_error
610
670
 
611
671
  def comment_starts_line?(charno)
672
+ return true if @source[charno] == "\n"
612
673
  (charno - 1).downto(0) do |i|
613
674
  ch = @source[i]
614
675
  break if ch == "\n"
@@ -627,11 +688,13 @@ module YARD
627
688
  end
628
689
 
629
690
  # check upwards from line before node; check node's line at the end
630
- ((node.line - 1).downto(node.line - 2).to_a + [node.line]).each do |line|
631
- comment = @comments[line]
632
- if comment && !comment.empty?
633
- add_comment(line, node)
634
- break
691
+ if (n_l = node.line)
692
+ ((n_l - 1).downto(n_l - 2).to_a + [n_l]).each do |line|
693
+ comment = @comments[line]
694
+ if comment && !comment.empty?
695
+ add_comment(line, node)
696
+ break
697
+ end
635
698
  end
636
699
  end
637
700
 
@@ -656,6 +719,23 @@ module YARD
656
719
  end
657
720
  end unless @comments.empty?
658
721
 
722
+ # Attach comments that fall within an otherwise empty
723
+ # class or module body. Without this step, a comment used
724
+ # solely for directives (like @!method) would be treated as
725
+ # a top-level comment and its directives would not be scoped
726
+ # to the namespace.
727
+ unless @comments.empty?
728
+ root.traverse do |node|
729
+ next unless [:class, :module, :sclass].include?(node.type)
730
+ body = node.children.last
731
+ next unless body && body.type == :list && body.empty?
732
+ @comments.keys.each do |line|
733
+ next unless node.line_range.include?(line)
734
+ add_comment(line, nil, body, true)
735
+ end
736
+ end
737
+ end
738
+
659
739
  # insert all remaining comments
660
740
  @comments.each do |line, _comment|
661
741
  add_comment(line, nil, root, true)
@@ -667,6 +747,11 @@ module YARD
667
747
  def add_comment(line, node = nil, before_node = nil, into = false)
668
748
  comment = @comments[line]
669
749
  source_range = @comments_range[line]
750
+ if comment && source_range
751
+ source = @source[source_range]
752
+ last_line = source.lines.to_a.last
753
+ return if last_line && last_line =~ /^\s*\#-\s*$/
754
+ end
670
755
  line_range = ((line - comment.count("\n"))..line)
671
756
  if node.nil?
672
757
  node = CommentNode.new(:comment, [comment], :line => line_range, :char => source_range)
@@ -67,7 +67,7 @@ module YARD
67
67
 
68
68
  # The default glob of files to be parsed.
69
69
  # @since 0.9.0
70
- DEFAULT_PATH_GLOB = ["{lib,app}/**/*.rb", "ext/**/*.{c,cc,cxx,cpp,rb}"]
70
+ DEFAULT_PATH_GLOB = ["{lib,app}/**/*.{rb,rbs}", "sig/**/*.rbs", "ext/**/*.{c,cc,cxx,cpp,rb}"]
71
71
 
72
72
  # Byte order marks for various encodings
73
73
  # @since 0.7.0
@@ -105,7 +105,7 @@ module YARD
105
105
  end
106
106
  end
107
107
  files = [paths].flatten.
108
- map {|p| File.directory?(p) ? "#{p}/**/*.{rb,c,cc,cxx,cpp}" : p }.
108
+ map {|p| File.directory?(p) ? "#{p}/**/*.{rb,rbs,c,cc,cxx,cpp}" : p }.
109
109
  map {|p| p.include?("*") ? Dir[p].sort_by {|d| [d.length, d] } : p }.flatten.
110
110
  reject {|p| !File.file?(p) || excluded.any? {|re| p =~ re } }.
111
111
  map {|p| p.encoding == Encoding.default_external ? p : p.dup.force_encoding(Encoding.default_external) }
@@ -379,6 +379,7 @@ module YARD
379
379
  register_parser_type :ruby, Ruby::RubyParser
380
380
  register_parser_type :ruby18, Ruby::Legacy::RubyParser
381
381
  register_parser_type :c, C::CParser, ['c', 'cc', 'cxx', 'cpp']
382
+ register_parser_type :rbs, RBS::RbsParser, ['rbs']
382
383
 
383
384
  self.parser_type = :ruby
384
385
 
@@ -75,6 +75,13 @@ module YARD
75
75
  lexical_lookup = 0
76
76
  while namespace && !resolved
77
77
  resolved = lookup_path_direct(namespace, path, type)
78
+ # Prevent a bare name from resolving back to the namespace we started
79
+ # from when searching through a parent namespace. For example,
80
+ # `include Enumerable` inside `A::Enumerable` would walk up to namespace
81
+ # `A` and match `A::Enumerable`, creating a false self-referential mixin.
82
+ # Only skip when we have already moved to a parent (namespace != orignamespace).
83
+ # See https://github.com/lsegal/yard/issues/1116
84
+ resolved = nil if resolved.equal?(orignamespace) && !namespace.equal?(orignamespace)
78
85
  resolved ||= lookup_path_inherited(namespace, path, type) if inheritance
79
86
  break if resolved
80
87
  namespace = namespace.parent
@@ -11,7 +11,7 @@ class Gem::Specification
11
11
  @has_rdoc == 'yard'
12
12
  end
13
13
 
14
- undef has_rdoc?
14
+ undef has_rdoc? if method_defined?(:has_rdoc?)
15
15
  def has_rdoc?
16
16
  (@has_rdoc ||= true) && @has_rdoc != 'yard'
17
17
  end
@@ -71,7 +71,7 @@ module YARD
71
71
  # def load_yardoc_from_http
72
72
  # Thread.new do
73
73
  # # zip/unzip method implementations are not shown
74
- # download_zip_file("http://mysite.com/yardocs/#{self}.zip")
74
+ # download_zip_file("https://mysite.com/yardocs/#{self}.zip")
75
75
  # unzip_file_to("/path/to/yardocs/#{self}")
76
76
  # end
77
77
  #
@@ -1,12 +1,208 @@
1
- /*
2
- * jQuery Autocomplete plugin 1.1
3
- *
4
- * Copyright (c) 2009 Jörn Zaefferer
5
- *
6
- * Dual licensed under the MIT and GPL licenses:
7
- * http://www.opensource.org/licenses/mit-license.php
8
- * http://www.gnu.org/licenses/gpl.html
9
- *
10
- * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $
11
- */
12
- eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}(';(3($){$.2e.1u({19:3(b,d){5 c=W b=="1B";d=$.1u({},$.M.1T,{Y:c?b:P,y:c?P:b,1J:c?$.M.1T.1J:10,X:d&&!d.1D?10:48},d);d.1y=d.1y||3(a){6 a};d.1v=d.1v||d.1R;6 A.I(3(){1M $.M(A,d)})},L:3(a){6 A.11("L",a)},1k:3(a){6 A.14("1k",[a])},2b:3(){6 A.14("2b")},28:3(a){6 A.14("28",[a])},24:3(){6 A.14("24")}});$.M=3(o,r){5 t={2Y:38,2S:40,2N:46,2I:9,2E:13,2B:27,2x:3I,2v:33,2p:34,2n:8};5 u=$(o).3r("19","3o").Q(r.2Q);5 p;5 m="";5 n=$.M.3c(r);5 s=0;5 k;5 h={1F:C};5 l=$.M.32(r,o,1Z,h);5 j;$.1Y.2X&&$(o.2U).11("45.19",3(){4(j){j=C;6 C}});u.11(($.1Y.2X?"43":"42")+".19",3(a){s=1;k=a.2M;3V(a.2M){O t.2Y:a.1d();4(l.N()){l.30()}w{12(0,D)}R;O t.2S:a.1d();4(l.N()){l.2D()}w{12(0,D)}R;O t.2v:a.1d();4(l.N()){l.2C()}w{12(0,D)}R;O t.2p:a.1d();4(l.N()){l.2A()}w{12(0,D)}R;O r.17&&$.1c(r.S)==","&&t.2x:O t.2I:O t.2E:4(1Z()){a.1d();j=D;6 C}R;O t.2B:l.Z();R;3J:1P(p);p=1O(12,r.1J);R}}).2t(3(){s++}).3E(3(){s=0;4(!h.1F){2r()}}).2q(3(){4(s++>1&&!l.N()){12(0,D)}}).11("1k",3(){5 c=(1r.7>1)?1r[1]:P;3 1N(q,a){5 b;4(a&&a.7){16(5 i=0;i<a.7;i++){4(a[i].L.J()==q.J()){b=a[i];R}}}4(W c=="3")c(b);w u.14("L",b&&[b.y,b.F])}$.I(15(u.K()),3(i,a){21(a,1N,1N)})}).11("2b",3(){n.1o()}).11("28",3(){$.1u(r,1r[1]);4("y"2h 1r[1])n.1e()}).11("24",3(){l.1p();u.1p();$(o.2U).1p(".19")});3 1Z(){5 e=l.2g();4(!e)6 C;5 v=e.L;m=v;4(r.17){5 b=15(u.K());4(b.7>1){5 f=r.S.7;5 c=$(o).18().1I;5 d,1H=0;$.I(b,3(i,a){1H+=a.7;4(c<=1H){d=i;6 C}1H+=f});b[d]=v;v=b.3f(r.S)}v+=r.S}u.K(v);1l();u.14("L",[e.y,e.F]);6 D}3 12(b,c){4(k==t.2N){l.Z();6}5 a=u.K();4(!c&&a==m)6;m=a;a=1m(a);4(a.7>=r.29){u.Q(r.26);4(!r.1s)a=a.J();21(a,3a,1l)}w{1q();l.Z()}};3 15(b){4(!b)6[""];4(!r.17)6[$.1c(b)];6 $.4h(b.23(r.S),3(a){6 $.1c(b).7?$.1c(a):P})}3 1m(a){4(!r.17)6 a;5 c=15(a);4(c.7==1)6 c[0];5 b=$(o).18().1I;4(b==a.7){c=15(a)}w{c=15(a.22(a.37(b),""))}6 c[c.7-1]}3 1G(q,a){4(r.1G&&(1m(u.K()).J()==q.J())&&k!=t.2n){u.K(u.K()+a.37(1m(m).7));$(o).18(m.7,m.7+a.7)}};3 2r(){1P(p);p=1O(1l,4g)};3 1l(){5 c=l.N();l.Z();1P(p);1q();4(r.36){u.1k(3(a){4(!a){4(r.17){5 b=15(u.K()).1n(0,-1);u.K(b.3f(r.S)+(b.7?r.S:""))}w{u.K("");u.14("L",P)}}})}};3 3a(q,a){4(a&&a.7&&s){1q();l.35(a,q);1G(q,a[0].F);l.20()}w{1l()}};3 21(f,d,g){4(!r.1s)f=f.J();5 e=n.31(f);4(e&&e.7){d(f,e)}w 4((W r.Y=="1B")&&(r.Y.7>0)){5 c={4f:+1M 4e()};$.I(r.2Z,3(a,b){c[a]=W b=="3"?b():b});$.4d({4c:"4b",4a:"19"+o.49,2V:r.2V,Y:r.Y,y:$.1u({q:1m(f),47:r.X},c),44:3(a){5 b=r.1A&&r.1A(a)||1A(a);n.1i(f,b);d(f,b)}})}w{l.2T();g(f)}};3 1A(c){5 d=[];5 b=c.23("\\n");16(5 i=0;i<b.7;i++){5 a=$.1c(b[i]);4(a){a=a.23("|");d[d.7]={y:a,F:a[0],L:r.1z&&r.1z(a,a[0])||a[0]}}}6 d};3 1q(){u.1h(r.26)}};$.M.1T={2Q:"41",2P:"3Z",26:"3Y",29:1,1J:3W,1s:C,1f:D,1w:C,1g:10,X:3U,36:C,2Z:{},1X:D,1R:3(a){6 a[0]},1v:P,1G:C,E:0,17:C,S:", ",1y:3(b,a){6 b.22(1M 3T("(?![^&;]+;)(?!<[^<>]*)("+a.22(/([\\^\\$\\(\\)\\[\\]\\{\\}\\*\\.\\+\\?\\|\\\\])/2K,"\\\\$1")+")(?![^<>]*>)(?![^&;]+;)","2K"),"<2J>$1</2J>")},1D:D,1E:3S};$.M.3c=3(g){5 h={};5 j=0;3 1f(s,a){4(!g.1s)s=s.J();5 i=s.2H(a);4(g.1w=="3R"){i=s.J().1k("\\\\b"+a.J())}4(i==-1)6 C;6 i==0||g.1w};3 1i(q,a){4(j>g.1g){1o()}4(!h[q]){j++}h[q]=a}3 1e(){4(!g.y)6 C;5 f={},2G=0;4(!g.Y)g.1g=1;f[""]=[];16(5 i=0,2F=g.y.7;i<2F;i++){5 c=g.y[i];c=(W c=="1B")?[c]:c;5 d=g.1v(c,i+1,g.y.7);4(d===C)1V;5 e=d.3Q(0).J();4(!f[e])f[e]=[];5 b={F:d,y:c,L:g.1z&&g.1z(c)||d};f[e].1U(b);4(2G++<g.X){f[""].1U(b)}};$.I(f,3(i,a){g.1g++;1i(i,a)})}1O(1e,25);3 1o(){h={};j=0}6{1o:1o,1i:1i,1e:1e,31:3(q){4(!g.1g||!j)6 P;4(!g.Y&&g.1w){5 a=[];16(5 k 2h h){4(k.7>0){5 c=h[k];$.I(c,3(i,x){4(1f(x.F,q)){a.1U(x)}})}}6 a}w 4(h[q]){6 h[q]}w 4(g.1f){16(5 i=q.7-1;i>=g.29;i--){5 c=h[q.3O(0,i)];4(c){5 a=[];$.I(c,3(i,x){4(1f(x.F,q)){a[a.7]=x}});6 a}}}6 P}}};$.M.32=3(e,g,f,k){5 h={H:"3N"};5 j,z=-1,y,1t="",1S=D,G,B;3 2y(){4(!1S)6;G=$("<3M/>").Z().Q(e.2P).T("3L","3K").1Q(1K.2w);B=$("<3H/>").1Q(G).3G(3(a){4(U(a).2u&&U(a).2u.3F()==\'2s\'){z=$("1L",B).1h(h.H).3D(U(a));$(U(a)).Q(h.H)}}).2q(3(a){$(U(a)).Q(h.H);f();g.2t();6 C}).3C(3(){k.1F=D}).3B(3(){k.1F=C});4(e.E>0)G.T("E",e.E);1S=C}3 U(a){5 b=a.U;3A(b&&b.3z!="2s")b=b.3y;4(!b)6[];6 b}3 V(b){j.1n(z,z+1).1h(h.H);2o(b);5 a=j.1n(z,z+1).Q(h.H);4(e.1D){5 c=0;j.1n(0,z).I(3(){c+=A.1a});4((c+a[0].1a-B.1b())>B[0].3x){B.1b(c+a[0].1a-B.3w())}w 4(c<B.1b()){B.1b(c)}}};3 2o(a){z+=a;4(z<0){z=j.1j()-1}w 4(z>=j.1j()){z=0}}3 2m(a){6 e.X&&e.X<a?e.X:a}3 2l(){B.2z();5 b=2m(y.7);16(5 i=0;i<b;i++){4(!y[i])1V;5 a=e.1R(y[i].y,i+1,b,y[i].F,1t);4(a===C)1V;5 c=$("<1L/>").3v(e.1y(a,1t)).Q(i%2==0?"3u":"3P").1Q(B)[0];$.y(c,"2k",y[i])}j=B.3t("1L");4(e.1X){j.1n(0,1).Q(h.H);z=0}4($.2e.2W)B.2W()}6{35:3(d,q){2y();y=d;1t=q;2l()},2D:3(){V(1)},30:3(){V(-1)},2C:3(){4(z!=0&&z-8<0){V(-z)}w{V(-8)}},2A:3(){4(z!=j.1j()-1&&z+8>j.1j()){V(j.1j()-1-z)}w{V(8)}},Z:3(){G&&G.Z();j&&j.1h(h.H);z=-1},N:3(){6 G&&G.3s(":N")},3q:3(){6 A.N()&&(j.2j("."+h.H)[0]||e.1X&&j[0])},20:3(){5 a=$(g).3p();G.T({E:W e.E=="1B"||e.E>0?e.E:$(g).E(),2i:a.2i+g.1a,1W:a.1W}).20();4(e.1D){B.1b(0);B.T({2L:e.1E,3n:\'3X\'});4($.1Y.3m&&W 1K.2w.3l.2L==="1x"){5 c=0;j.I(3(){c+=A.1a});5 b=c>e.1E;B.T(\'3k\',b?e.1E:c);4(!b){j.E(B.E()-2R(j.T("2O-1W"))-2R(j.T("2O-3j")))}}}},2g:3(){5 a=j&&j.2j("."+h.H).1h(h.H);6 a&&a.7&&$.y(a[0],"2k")},2T:3(){B&&B.2z()},1p:3(){G&&G.3i()}}};$.2e.18=3(b,f){4(b!==1x){6 A.I(3(){4(A.2d){5 a=A.2d();4(f===1x||b==f){a.4n("2c",b);a.3h()}w{a.4m(D);a.4l("2c",b);a.4k("2c",f);a.3h()}}w 4(A.3g){A.3g(b,f)}w 4(A.1C){A.1C=b;A.3e=f}})}5 c=A[0];4(c.2d){5 e=1K.18.4j(),3d=c.F,2a="<->",2f=e.3b.7;e.3b=2a;5 d=c.F.2H(2a);c.F=3d;A.18(d,d+2f);6{1I:d,39:d+2f}}w 4(c.1C!==1x){6{1I:c.1C,39:c.3e}}}})(4i);',62,272,'|||function|if|var|return|length|||||||||||||||||||||||||else||data|active|this|list|false|true|width|value|element|ACTIVE|each|toLowerCase|val|result|Autocompleter|visible|case|null|addClass|break|multipleSeparator|css|target|moveSelect|typeof|max|url|hide||bind|onChange||trigger|trimWords|for|multiple|selection|autocomplete|offsetHeight|scrollTop|trim|preventDefault|populate|matchSubset|cacheLength|removeClass|add|size|search|hideResultsNow|lastWord|slice|flush|unbind|stopLoading|arguments|matchCase|term|extend|formatMatch|matchContains|undefined|highlight|formatResult|parse|string|selectionStart|scroll|scrollHeight|mouseDownOnSelect|autoFill|progress|start|delay|document|li|new|findValueCallback|setTimeout|clearTimeout|appendTo|formatItem|needsInit|defaults|push|continue|left|selectFirst|browser|selectCurrent|show|request|replace|split|unautocomplete||loadingClass||setOptions|minChars|teststring|flushCache|character|createTextRange|fn|textLength|selected|in|top|filter|ac_data|fillList|limitNumberOfItems|BACKSPACE|movePosition|PAGEDOWN|click|hideResults|LI|focus|nodeName|PAGEUP|body|COMMA|init|empty|pageDown|ESC|pageUp|next|RETURN|ol|nullData|indexOf|TAB|strong|gi|maxHeight|keyCode|DEL|padding|resultsClass|inputClass|parseInt|DOWN|emptyList|form|dataType|bgiframe|opera|UP|extraParams|prev|load|Select|||display|mustMatch|substring||end|receiveData|text|Cache|orig|selectionEnd|join|setSelectionRange|select|remove|right|height|style|msie|overflow|off|offset|current|attr|is|find|ac_even|html|innerHeight|clientHeight|parentNode|tagName|while|mouseup|mousedown|index|blur|toUpperCase|mouseover|ul|188|default|absolute|position|div|ac_over|substr|ac_odd|charAt|word|180|RegExp|100|switch|400|auto|ac_loading|ac_results||ac_input|keydown|keypress|success|submit||limit|150|name|port|abort|mode|ajax|Date|timestamp|200|map|jQuery|createRange|moveEnd|moveStart|collapse|move'.split('|'),0,{}))
1
+ (function() {
2
+ function query(selector, root) {
3
+ return (root || document).querySelector(selector);
4
+ }
5
+
6
+ function ready(callback) {
7
+ if (document.readyState === "loading") {
8
+ document.addEventListener("DOMContentLoaded", callback, { once: true });
9
+ } else {
10
+ callback();
11
+ }
12
+ }
13
+
14
+ function createAutocomplete(input) {
15
+ var form = input.form;
16
+ var results = document.createElement("div");
17
+ var list = document.createElement("ul");
18
+ var requestTimer = null;
19
+ var controller = null;
20
+ var items = [];
21
+ var activeIndex = -1;
22
+ var blurTimer = null;
23
+
24
+ if (!form) return;
25
+
26
+ results.className = "ac_results";
27
+ results.hidden = true;
28
+ results.setAttribute("role", "listbox");
29
+ results.id = input.id + "_results";
30
+ list.setAttribute("role", "presentation");
31
+ results.appendChild(list);
32
+ input.setAttribute("autocomplete", "off");
33
+ input.setAttribute("aria-autocomplete", "list");
34
+ input.setAttribute("aria-controls", results.id);
35
+ input.setAttribute("aria-expanded", "false");
36
+ form.appendChild(results);
37
+
38
+ function syncResultsWidth() {
39
+ results.style.width = input.offsetWidth + "px";
40
+ }
41
+
42
+ function hideResults() {
43
+ results.hidden = true;
44
+ input.setAttribute("aria-expanded", "false");
45
+ input.removeAttribute("aria-activedescendant");
46
+ activeIndex = -1;
47
+ items = [];
48
+ list.innerHTML = "";
49
+ }
50
+
51
+ function setActive(index) {
52
+ if (!items.length) return;
53
+ activeIndex = (index + items.length) % items.length;
54
+ items.forEach(function(item, itemIndex) {
55
+ item.element.classList.toggle("ac_over", itemIndex === activeIndex);
56
+ });
57
+ input.setAttribute("aria-activedescendant", items[activeIndex].element.id);
58
+ }
59
+
60
+ function selectItem(item) {
61
+ input.value = item.values[1];
62
+ window.location.href = item.values[3];
63
+ }
64
+
65
+ function renderItems(lines) {
66
+ syncResultsWidth();
67
+ list.innerHTML = "";
68
+ items = lines.map(function(line, index) {
69
+ var values = line.split(",");
70
+ var element = document.createElement("li");
71
+ var label = document.createElement("span");
72
+ var namespace = document.createElement("small");
73
+
74
+ element.id = results.id + "_item_" + index;
75
+ element.setAttribute("role", "option");
76
+ element.className = index % 2 === 0 ? "ac_even" : "ac_odd";
77
+ label.textContent = values[0];
78
+ element.appendChild(label);
79
+
80
+ if (values[1] !== "") {
81
+ namespace.textContent = "(" + values[1] + ")";
82
+ element.appendChild(document.createTextNode(" "));
83
+ element.appendChild(namespace);
84
+ }
85
+
86
+ element.addEventListener("mouseenter", function() {
87
+ setActive(index);
88
+ });
89
+ element.addEventListener("mousedown", function(event) {
90
+ event.preventDefault();
91
+ selectItem(items[index]);
92
+ });
93
+
94
+ list.appendChild(element);
95
+
96
+ return { element: element, values: values };
97
+ });
98
+
99
+ if (items.length) {
100
+ results.hidden = false;
101
+ input.setAttribute("aria-expanded", "true");
102
+ setActive(0);
103
+ } else {
104
+ hideResults();
105
+ }
106
+ }
107
+
108
+ function fetchResults(term) {
109
+ if (controller) controller.abort();
110
+ controller = new AbortController();
111
+ input.classList.add("ac_loading");
112
+
113
+ fetch(
114
+ form.action +
115
+ "?q=" +
116
+ encodeURIComponent(term) +
117
+ "&_=" +
118
+ new Date().getTime(),
119
+ {
120
+ headers: {
121
+ "X-Requested-With": "XMLHttpRequest"
122
+ },
123
+ signal: controller.signal
124
+ }
125
+ )
126
+ .then(function(response) {
127
+ return response.text();
128
+ })
129
+ .then(function(text) {
130
+ var lines = text
131
+ .split("\n")
132
+ .map(function(line) {
133
+ return line.trim();
134
+ })
135
+ .filter(Boolean);
136
+
137
+ renderItems(lines);
138
+ })
139
+ .catch(function(error) {
140
+ if (error.name !== "AbortError") hideResults();
141
+ })
142
+ .finally(function() {
143
+ input.classList.remove("ac_loading");
144
+ });
145
+ }
146
+
147
+ input.addEventListener("input", function() {
148
+ clearTimeout(requestTimer);
149
+ if (blurTimer) clearTimeout(blurTimer);
150
+
151
+ if (!input.value.trim()) {
152
+ hideResults();
153
+ return;
154
+ }
155
+
156
+ requestTimer = setTimeout(function() {
157
+ fetchResults(input.value.trim());
158
+ }, 200);
159
+ });
160
+
161
+ input.addEventListener("keydown", function(event) {
162
+ if (results.hidden && (event.key === "ArrowDown" || event.key === "ArrowUp")) {
163
+ if (!input.value.trim()) return;
164
+ fetchResults(input.value.trim());
165
+ return;
166
+ }
167
+
168
+ if (event.key === "ArrowDown") {
169
+ event.preventDefault();
170
+ setActive(activeIndex + 1);
171
+ } else if (event.key === "ArrowUp") {
172
+ event.preventDefault();
173
+ setActive(activeIndex - 1);
174
+ } else if (event.key === "Enter") {
175
+ if (activeIndex >= 0 && items[activeIndex]) {
176
+ event.preventDefault();
177
+ selectItem(items[activeIndex]);
178
+ }
179
+ } else if (event.key === "Escape") {
180
+ hideResults();
181
+ }
182
+ });
183
+
184
+ input.addEventListener("blur", function() {
185
+ blurTimer = setTimeout(hideResults, 150);
186
+ });
187
+
188
+ input.addEventListener("focus", function() {
189
+ syncResultsWidth();
190
+ if (items.length) {
191
+ results.hidden = false;
192
+ input.setAttribute("aria-expanded", "true");
193
+ }
194
+ });
195
+
196
+ document.addEventListener("click", function(event) {
197
+ if (!form.contains(event.target)) hideResults();
198
+ });
199
+
200
+ window.addEventListener("resize", syncResultsWidth);
201
+ syncResultsWidth();
202
+ }
203
+
204
+ ready(function() {
205
+ var input = query("#search_box");
206
+ if (input) createAutocomplete(input);
207
+ });
208
+ })();
@@ -1,22 +1,6 @@
1
1
  <form class="search" method="get" action="<%= abs_url base_path(router.search_prefix) %>">
2
- <input name="q" type="search" placeholder="Search" id="search_box" size="30" value="<%= h @query %>" />
2
+ <input name="q" type="search" placeholder="Search" id="search_box" size="30" value="<%= h @query %>">
3
3
  </form>
4
- <script type="text/javascript" charset="utf-8">
5
- $(function() {
6
- $('#search_box').autocomplete($('#search_box').parent().attr('action'), {
7
- width: 200,
8
- formatItem: function(item) {
9
- var values = item[0].split(",");
10
- return values[0] + (values[1] == '' ? "" : " <small>(" + values[1] + ")</small>");
11
- }
12
- }).result(function(event, item) {
13
- var values = item[0].split(",")
14
- $('#search_box').val(values[1]);
15
- location.href = values[3];
16
- return false;
17
- });
18
- });
19
- </script>
20
4
 
21
5
  <div id="menu">
22
6
  <% unless @single_library %>
@@ -1,4 +1,6 @@
1
1
  <script>
2
- $(document.getElementById("<%= anchor_for(object) %>")).prepend(
3
- '<a class="permalink" href="<%= abs_url base_path(router.docs_prefix) %>/<%= urlencode serializer.serialized_path(object) %>">permalink</a>');
2
+ document.getElementById("<%= anchor_for(object) %>").insertAdjacentHTML(
3
+ "afterbegin",
4
+ '<a class="permalink" href="<%= abs_url base_path(router.docs_prefix) %>/<%= urlencode serializer.serialized_path(object) %>">permalink</a>'
5
+ );
4
6
  </script>
@@ -1,7 +1,7 @@
1
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
1
+ <meta charset="UTF-8">
2
2
  <title>YARD Documentation Server <%= YARD::VERSION %> - Library Listing</title>
3
- <link rel="stylesheet" href="<%= abs_url('css', 'style.css') %>?<%= mtime('css/style.css') %>" type="text/css" media="screen" charset="utf-8" />
4
- <link rel="stylesheet" href="<%= abs_url('css', 'custom.css') %>?<%= mtime('css/custom.css') %>" type="text/css" media="screen" charset="utf-8" />
3
+ <link rel="stylesheet" href="<%= abs_url('css', 'style.css') %>?<%= mtime('css/style.css') %>" type="text/css" media="screen" charset="utf-8">
4
+ <link rel="stylesheet" href="<%= abs_url('css', 'custom.css') %>?<%= mtime('css/custom.css') %>" type="text/css" media="screen" charset="utf-8">
5
5
  <style type="text/css" media="screen">
6
6
  ul { list-style: circle inside none; padding: 0; }
7
7
  li { font-size: 1.2em; line-height: 1.4em; padding: 3px 5px; }
@@ -1,6 +1,5 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
1
+ <!DOCTYPE html>
2
+ <html lang="en">
4
3
  <head>
5
4
  <%= erb(:headers) %>
6
5
  </head>