yard 0.9.35 → 0.9.37

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5ff0ce7fb0e2d8ecc443968bc650be669b354e264b468ed73110367f8e18a8f
4
- data.tar.gz: 57f2052210346c9492bb9d80bd15200cc3410e358f4d169e09a148cd258fc65c
3
+ metadata.gz: 0774d1772b133075737690acbc502767f6fef28d3765a14929074259248f3981
4
+ data.tar.gz: '068103b3caf24a6c6071a6c9b0f52bd58641fd0c03e22220fb2d1b09a104385c'
5
5
  SHA512:
6
- metadata.gz: 01c9c77f83fc7c2e8ccfe5cd21c16c51506ececa875a9e24793eb2d0d29376c69d8686f2ab8d0a11caefd77f5bf70424b40ea9e4c83d4afebd070b2c7c4d6132
7
- data.tar.gz: d3e49a80ac5be583a158011351cbca068d4f78179ce02f88e43a3d02cac1a10ce7a02bd4b20fa9a44ce6dd519e02e2ede8acca8b5ed62a21341149de71c0a825
6
+ metadata.gz: 64a799b2f45d7ad6aad8684c805344f242c8e2f8ef1c60a43094bc237bccd449ee1c93c60c0f54a36f05a79e5b652636d7170dce85941b1f74a4bcc173c92c21
7
+ data.tar.gz: b19ba690f1a244b0c7df5c1524f77355323fa9164e9496c609f258b3d0691c0a3d807cd985f20f335884ba1d8e97193149d4a7b9e1eebd9ed3a43431492a1ce3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # main
2
2
 
3
+ # [0.9.37] - September 4th, 2024
4
+
5
+ [0.9.37]: https://github.com/lsegal/yard/compare/v0.9.36...v0.9.37
6
+
7
+ - Fix JavaScript errors in `--one-file` template (#1426)
8
+ - Fix heredoc parsing and add support for squiggly heredocs (#1315, #1495)
9
+ - Accessibility improvements to the default template (#1501)
10
+ - Improved YARD documentation (#1410, #1512, #1516, #1544)
11
+ - Fix error when parsing `@option` tags (#1515)
12
+ - Fix issue parsing UTF-8 filenames (#1517)
13
+ - Replace OpenStruct with optimized YARD::OpenStruct to avoid ostruct performance warnings (#1545)
14
+ - Add support for `private attr_*` syntax (#1541)
15
+ - Remove logger dependency (#1546)
16
+
17
+ # [0.9.36] - February 29th, 2024
18
+
19
+ [0.9.36]: https://github.com/lsegal/yard/compare/v0.9.35...v0.9.36
20
+
21
+ - Further XSS fixes for generated frameset pages (#1538)
22
+ - Improve tests for Ruby 3.3 compatibility (#1519, #1531)
23
+ - Documentation improvements (#1524)
24
+
3
25
  # [0.9.35] - February 28th, 2024
4
26
 
5
27
  [0.9.35]: https://github.com/lsegal/yard/compare/v0.9.34...v0.9.35
data/README.md CHANGED
@@ -122,6 +122,13 @@ HTML. If running `which rdoc` turns up empty, install RDoc by issuing:
122
122
  $ sudo apt-get install rdoc
123
123
  ```
124
124
 
125
+ ### Markdown parser
126
+
127
+ When rendering markdown, yard will use one of several possible markdown providers,
128
+ [in order of priority](https://github.com/lsegal/yard/blob/e833aac7a01510245dd4ae1d1d18b046c8293c2d/lib/yard/templates/helpers/markup_helper.rb#L26-L33).
129
+ If you are experiencing rendering bugs (example [1](https://github.com/lsegal/yard/issues/1410) [2](https://github.com/lsegal/yard/issues/1543)), try adding one of the
130
+ gems further up in the list to your Gemfile.
131
+
125
132
  ## Usage
126
133
 
127
134
  There are a couple of ways to use YARD. The first is via command-line, and the
@@ -185,7 +192,7 @@ Note that the README file can be specified with its own `--readme` switch.
185
192
  You can also add a `.yardopts` file to your project directory which lists the
186
193
  switches separated by whitespace (newlines or space) to pass to yardoc whenever
187
194
  it is run. A full overview of the `.yardopts` file can be found in
188
- {YARD::CLI::Yardoc}.
195
+ [YARD::CLI::Yardoc](https://rubydoc.info/gems/yard/YARD/CLI/Yardoc#label-Options+File+-28.yardopts-29).
189
196
 
190
197
  ### Queries
191
198
 
data/docs/Tags.md CHANGED
@@ -206,7 +206,7 @@ also be a list of types separated by commas.
206
206
  An order dependent list is a set of types surrounded by "()" and separated by
207
207
  commas. This list must contain exactly those types in exactly the order specified.
208
208
  For instance, an Array containing a String, Fixnum and Hash in that order (and
209
- having exactly those 3 elements) would be listed as: `Array<(String, Fixnum, Hash)>`.
209
+ having exactly those 3 elements) would be listed as: `Array(String, Fixnum, Hash)`.
210
210
 
211
211
  #### Literals
212
212
 
data/lib/yard/autoload.rb CHANGED
@@ -298,6 +298,7 @@ module YARD
298
298
  autoload :DocstringParser, __p('docstring_parser')
299
299
  autoload :GemIndex, __p('gem_index')
300
300
  autoload :Logger, __p('logging')
301
+ autoload :OpenStruct, __p('open_struct')
301
302
  autoload :Options, __p('options')
302
303
  autoload :Registry, __p('registry')
303
304
  autoload :RegistryResolver, __p('registry_resolver')
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'ostruct'
3
2
 
4
3
  module YARD
5
4
  module CodeObjects
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'ostruct'
3
2
 
4
3
  module YARD
5
4
  # Parses text and creates a {Docstring} object to represent documentation
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'ostruct'
3
2
 
4
3
  module YARD
5
4
  module Handlers
@@ -13,10 +13,22 @@ class YARD::Handlers::Ruby::VisibilityHandler < YARD::Handlers::Ruby::Base
13
13
  case statement.type
14
14
  when :var_ref, :vcall
15
15
  self.visibility = ident.first.to_sym
16
- when :fcall, :command
16
+ when :command
17
+ if RUBY_VERSION >= '3.' && is_attribute_method?(statement.parameters.first)
18
+ parse_block(statement.parameters.first, visibility: ident.first.to_sym)
19
+ return
20
+ end
21
+ process_decorator do |method|
22
+ method.visibility = ident.first if method.respond_to? :visibility=
23
+ end
24
+ when :fcall
17
25
  process_decorator do |method|
18
26
  method.visibility = ident.first if method.respond_to? :visibility=
19
27
  end
20
28
  end
21
29
  end
30
+
31
+ def is_attribute_method?(node)
32
+ node.type == :command && node.jump(:ident).first.to_s =~ /^attr_(accessor|writer|reader)$/
33
+ end
22
34
  end
data/lib/yard/logging.rb CHANGED
@@ -1,12 +1,44 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- require 'logger'
4
3
  require 'thread'
5
4
 
6
5
  module YARD
7
6
  # Handles console logging for info, warnings and errors.
8
7
  # Uses the stdlib Logger class in Ruby for all the backend logic.
9
- class Logger < ::Logger
8
+ class Logger
9
+ # Log severity levels
10
+ module Severity
11
+ # Debugging log level
12
+ DEBUG = 0
13
+
14
+ # Information log level
15
+ INFO = 1
16
+
17
+ # Warning log level
18
+ WARN = 2
19
+
20
+ # Error log level
21
+ ERROR = 3
22
+
23
+ # Fatal log level
24
+ FATAL = 4
25
+
26
+ # Unknown log level
27
+ UNKNOWN = 5
28
+
29
+ # @private
30
+ SEVERITIES = {
31
+ DEBUG => :debug,
32
+ INFO => :info,
33
+ WARN => :warn,
34
+ ERROR => :error,
35
+ FATAL => :fatal,
36
+ UNKNOWN => :unknown
37
+ }
38
+ end
39
+
40
+ include Severity
41
+
10
42
  # The list of characters displayed beside the progress bar to indicate
11
43
  # "movement".
12
44
  # @since 0.8.2
@@ -14,25 +46,31 @@ module YARD
14
46
 
15
47
  # @return [IO] the IO object being logged to
16
48
  # @since 0.8.2
17
- def io; @logdev end
18
- def io=(pipe) @logdev = pipe end
49
+ attr_accessor :io
19
50
 
20
51
  # @return [Boolean] whether backtraces should be shown (by default
21
52
  # this is on).
22
53
  def show_backtraces; @show_backtraces || level == DEBUG end
23
54
  attr_writer :show_backtraces
24
55
 
56
+ # @return [DEBUG, INFO, WARN, ERROR, FATAL, UNKNOWN] the logging level
57
+ attr_accessor :level
58
+
59
+ # @return [Boolean] whether a warn message has been emitted. Used for status tracking.
60
+ attr_accessor :warned
61
+
25
62
  # @return [Boolean] whether progress indicators should be shown when
26
63
  # logging CLIs (by default this is off).
27
64
  def show_progress
28
65
  return false if YARD.ruby18? # threading is too ineffective for progress support
29
- return false if YARD.windows? # windows has poor ANSI support
30
66
  return false unless io.tty? # no TTY support on IO
31
67
  return false unless level > INFO # no progress in verbose/debug modes
32
68
  @show_progress
33
69
  end
34
70
  attr_writer :show_progress
35
71
 
72
+ # @!group Constructor Methods
73
+
36
74
  # The logger instance
37
75
  # @return [Logger] the logger instance
38
76
  def self.instance(pipe = STDOUT)
@@ -40,13 +78,12 @@ module YARD
40
78
  end
41
79
 
42
80
  # Creates a new logger
81
+ # @private
43
82
  def initialize(pipe, *args)
44
- super(pipe, *args)
45
83
  self.io = pipe
46
84
  self.show_backtraces = true
47
85
  self.show_progress = false
48
86
  self.level = WARN
49
- self.formatter = method(:format_log)
50
87
  self.warned = false
51
88
  @progress_indicator = 0
52
89
  @mutex = Mutex.new
@@ -54,36 +91,64 @@ module YARD
54
91
  @progress_last_update = Time.now
55
92
  end
56
93
 
57
- # Changes the debug level to DEBUG if $DEBUG is set
58
- # and writes a debugging message.
59
- def debug(*args)
60
- self.level = DEBUG if $DEBUG
61
- super
94
+ # @!macro [attach] logger.create_log_method
95
+ # @method $1(message)
96
+ # Logs a message with the $1 severity level.
97
+ # @param message [String] the message to log
98
+ # @see #log
99
+ # @return [void]
100
+ # @private
101
+ def self.create_log_method(name)
102
+ severity = Severity.const_get(name.to_s.upcase)
103
+ define_method(name) { |message| log(severity, message) }
62
104
  end
63
105
 
106
+ # @!group Logging Methods
107
+
108
+ create_log_method :info
109
+ create_log_method :error
110
+ create_log_method :fatal
111
+ create_log_method :unknown
112
+
113
+ # Changes the debug level to DEBUG if $DEBUG is set and writes a debugging message.
114
+ create_log_method :debug
115
+
64
116
  # Remembers when a warning occurs and writes a warning message.
65
- def warn(*args)
66
- self.warned = true
67
- super
117
+ create_log_method :warn
118
+
119
+ # Logs a message with a given severity
120
+ # @param severity [DEBUG, INFO, WARN, ERROR, FATAL, UNKNOWN] the severity level
121
+ # @param message [String] the message to log
122
+ def log(severity, message)
123
+ self.level = DEBUG if $DEBUG
124
+ return unless severity >= level
125
+
126
+ self.warned = true if severity == WARN
127
+ clear_line
128
+ puts "[#{SEVERITIES[severity].to_s.downcase}]: #{message}"
68
129
  end
69
- attr_accessor :warned
70
130
 
71
- # Captures the duration of a block of code for benchmark analysis. Also
72
- # calls {#progress} on the message to display it to the user.
131
+ # @!group Level Control Methods
132
+
133
+ # Sets the logger level for the duration of the block
73
134
  #
74
- # @todo Implement capture storage for reporting of benchmarks
75
- # @param [String] msg the message to display
76
- # @param [Symbol, nil] nontty_log the level to log as if the output
77
- # stream is not a TTY. Use +nil+ for no alternate logging.
78
- # @yield a block of arbitrary code to benchmark
79
- # @return [void]
80
- def capture(msg, nontty_log = :debug)
81
- progress(msg, nontty_log)
135
+ # @example
136
+ # log.enter_level(Logger::ERROR) do
137
+ # YARD.parse_string "def x; end"
138
+ # end
139
+ # @param [Fixnum] new_level the logger level for the duration of the block.
140
+ # values can be found in Ruby's Logger class.
141
+ # @yield the block with the logger temporarily set to +new_level+
142
+ def enter_level(new_level = level)
143
+ old_level = level
144
+ self.level = new_level
82
145
  yield
83
146
  ensure
84
- clear_progress
147
+ self.level = old_level
85
148
  end
86
149
 
150
+ # @!group Utility Printing Methods
151
+
87
152
  # Displays a progress indicator for a given message. This progress report
88
153
  # is only displayed on TTY displays, otherwise the message is passed to
89
154
  # the +nontty_log+ level.
@@ -120,7 +185,7 @@ module YARD
120
185
  # @since 0.8.2
121
186
  def clear_progress
122
187
  return unless show_progress
123
- print_no_newline("\e[?25h\e[2K")
188
+ io.write("\e[?25h\e[2K")
124
189
  @progress_msg = nil
125
190
  end
126
191
 
@@ -133,16 +198,13 @@ module YARD
133
198
  print("#{msg}\n")
134
199
  end
135
200
 
136
- alias print_no_newline <<
137
- private :print_no_newline
138
-
139
201
  # Displays an unformatted line to the logger output stream.
140
202
  # @param [String] msg the message to display
141
203
  # @return [void]
142
204
  # @since 0.8.2
143
205
  def print(msg = '')
144
206
  clear_line
145
- print_no_newline(msg)
207
+ io.write(msg)
146
208
  end
147
209
  alias << print
148
210
 
@@ -158,48 +220,41 @@ module YARD
158
220
  exc.backtrace[0..5].map {|x| "\n\t#{x}" }.join + "\n")
159
221
  end
160
222
 
223
+ # @!group Benchmarking Methods
224
+
225
+ # Captures the duration of a block of code for benchmark analysis. Also
226
+ # calls {#progress} on the message to display it to the user.
227
+ #
228
+ # @todo Implement capture storage for reporting of benchmarks
229
+ # @param [String] msg the message to display
230
+ # @param [Symbol, nil] nontty_log the level to log as if the output
231
+ # stream is not a TTY. Use +nil+ for no alternate logging.
232
+ # @yield a block of arbitrary code to benchmark
233
+ # @return [void]
234
+ def capture(msg, nontty_log = :debug)
235
+ progress(msg, nontty_log)
236
+ yield
237
+ ensure
238
+ clear_progress
239
+ end
240
+
241
+ # @!endgroup
242
+
161
243
  # Warns that the Ruby environment does not support continuations. Applies
162
244
  # to JRuby, Rubinius and MacRuby. This warning will only display once
163
245
  # per Ruby process.
164
246
  #
165
247
  # @deprecated Continuations are no longer needed by YARD 0.8.0+.
166
248
  # @return [void]
249
+ # @private
167
250
  def warn_no_continuations
168
251
  end
169
252
 
170
- # Sets the logger level for the duration of the block
171
- #
172
- # @example
173
- # log.enter_level(Logger::ERROR) do
174
- # YARD.parse_string "def x; end"
175
- # end
176
- # @param [Fixnum] new_level the logger level for the duration of the block.
177
- # values can be found in Ruby's Logger class.
178
- # @yield the block with the logger temporarily set to +new_level+
179
- def enter_level(new_level = level)
180
- old_level = level
181
- self.level = new_level
182
- yield
183
- ensure
184
- self.level = old_level
185
- end
186
-
187
253
  private
188
254
 
189
- # Override this internal Logger method to clear line
190
- def add(*args)
191
- clear_line
192
- super(*args)
193
- end
194
-
195
255
  def clear_line
196
256
  return unless @progress_msg
197
- print_no_newline("\e[2K\r")
198
- end
199
-
200
- # Log format (from Logger implementation). Used by Logger internally
201
- def format_log(sev, _time, _prog, msg)
202
- "[#{sev.downcase}]: #{msg}\n"
257
+ io.write("\e[2K\r")
203
258
  end
204
259
  end
205
260
  end
@@ -0,0 +1,67 @@
1
+ module YARD
2
+ # An OpenStruct compatible struct class that allows for basic access of attributes
3
+ # via +struct.attr_name+ and +struct.attr_name = value+.
4
+ class OpenStruct
5
+ def initialize(hash = {})
6
+ @table = hash.each_pair { |k, v| [k.to_sym, v] }
7
+ end
8
+
9
+ # @private
10
+ def method_missing(name, *args)
11
+ if name.to_s.end_with?('=')
12
+ varname = name.to_s[0..-2].to_sym
13
+ __cache_lookup__(varname)
14
+ send(name, args.first)
15
+ else
16
+ __cache_lookup__(name)
17
+ send(name)
18
+ end
19
+ end
20
+
21
+ def to_h
22
+ @table.dup
23
+ end
24
+
25
+ def ==(other)
26
+ other.is_a?(self.class) && to_h == other.to_h
27
+ end
28
+
29
+ def hash
30
+ @table.hash
31
+ end
32
+
33
+ def dig(*keys)
34
+ @table.dig(*keys)
35
+ end
36
+
37
+ def []=(key, value)
38
+ @table[key.to_sym] = value
39
+ end
40
+
41
+ def [](key)
42
+ @table[key.to_sym]
43
+ end
44
+
45
+ def each_pair(&block)
46
+ @table.each_pair(&block)
47
+ end
48
+
49
+ def marshal_dump
50
+ @table
51
+ end
52
+
53
+ def marshal_load(data)
54
+ @table = data
55
+ end
56
+
57
+ private
58
+
59
+ def __cache_lookup__(name)
60
+ key = name.to_sym.inspect
61
+ instance_eval <<-RUBY, __FILE__, __LINE__ + 1
62
+ def #{name}; @table[#{key}]; end
63
+ def #{name.to_s.sub('?','_')}=(v); @table[#{key}] = v; end unless #{key}.to_s.include?('?')
64
+ RUBY
65
+ end
66
+ end
67
+ end
@@ -656,7 +656,7 @@ module YARD
656
656
  if @lex_state != EXPR_END && @lex_state != EXPR_CLASS &&
657
657
  (@lex_state != EXPR_ARG || @space_seen)
658
658
  c = peek(0)
659
- tk = identify_here_document if /[-\w\"\'\`]/ =~ c
659
+ tk = identify_here_document if /[-~\w\"\'\`]/ =~ c
660
660
  end
661
661
  if !tk
662
662
  @lex_state = EXPR_BEG
@@ -1063,6 +1063,8 @@ module YARD
1063
1063
  ch = getc
1064
1064
  if ch == "-"
1065
1065
  ch = getc
1066
+ elsif ch == "~"
1067
+ ch = getc
1066
1068
  indent = true
1067
1069
  end
1068
1070
  if /['"`]/ =~ ch # '
@@ -1096,9 +1098,12 @@ module YARD
1096
1098
  str = String.new
1097
1099
  while (l = gets)
1098
1100
  l.chomp!
1099
- l.strip! if indent
1100
- break if l == quoted
1101
- str << l.chomp << "\n"
1101
+ if l == quoted
1102
+ str = dedent(str) if indent
1103
+ break
1104
+ else
1105
+ str << l.chomp << "\n"
1106
+ end
1102
1107
  end
1103
1108
 
1104
1109
  @reader.divert_read_from(reserve)
@@ -1108,6 +1113,16 @@ module YARD
1108
1113
  Token(Ltype2Token[lt], str).set_text(str.dump)
1109
1114
  end
1110
1115
 
1116
+ def dedent(str)
1117
+ lines = str.split("\n", -1)
1118
+ dedent_amt = lines.map do |line|
1119
+ line =~ /\S/ ? line.match(/^ */).offset(0)[1] : nil
1120
+ end.compact.min || 0
1121
+ return str if dedent_amt.zero?
1122
+
1123
+ lines.map { |line| line =~ /\S/ ? line.gsub(/^ {#{dedent_amt}}/, "") : line }.join("\n")
1124
+ end
1125
+
1111
1126
  def identify_quotation(initial_char)
1112
1127
  ch = getc
1113
1128
  if lt = PERCENT_LTYPE[ch]
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  require 'stringio'
3
- require 'ostruct'
4
3
 
5
4
  module YARD
6
5
  module Parser
@@ -108,7 +107,8 @@ module YARD
108
107
  files = [paths].flatten.
109
108
  map {|p| File.directory?(p) ? "#{p}/**/*.{rb,c,cc,cxx,cpp}" : p }.
110
109
  map {|p| p.include?("*") ? Dir[p].sort_by {|d| [d.length, d] } : p }.flatten.
111
- reject {|p| !File.file?(p) || excluded.any? {|re| p =~ re } }
110
+ reject {|p| !File.file?(p) || excluded.any? {|re| p =~ re } }.
111
+ map {|p| p.encoding == Encoding.default_external ? p : p.dup.force_encoding(Encoding.default_external) }
112
112
 
113
113
  log.enter_level(level) do
114
114
  parse_in_order(*files.uniq)
@@ -143,6 +143,7 @@ module YARD
143
143
  seen_space = false
144
144
  i = 0
145
145
  last_seen = ''
146
+ text ||= ''
146
147
  while i < text.length
147
148
  c = text[i, 1]
148
149
 
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'ostruct'
3
2
 
4
3
  module YARD
5
4
  module Tags
data/lib/yard/tags/tag.rb CHANGED
@@ -23,6 +23,7 @@ module YARD
23
23
  attr_accessor :types
24
24
 
25
25
  # @return [String] a name associated with the tag
26
+ # @return [nil] if no tag name is supplied
26
27
  attr_accessor :name
27
28
 
28
29
  # @return [CodeObjects::Base] the associated object
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'ostruct'
3
2
 
4
3
  module YARD
5
4
  module Templates
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'ostruct'
3
2
 
4
3
  module YARD
5
4
  module Templates
data/lib/yard/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module YARD
5
- VERSION = '0.9.35'
5
+ VERSION = '0.9.37'
6
6
  end
@@ -20,8 +20,8 @@ h1 { padding: 12px 10px; padding-bottom: 0; margin: 0; font-size: 1.4em; }
20
20
  #content.insearch #noresults { margin-left: 7px; }
21
21
  li.collapsed ul { display: none; }
22
22
  li a.toggle { cursor: default; position: relative; left: -5px; top: 4px; text-indent: -999px; width: 10px; height: 9px; margin-left: -10px; display: block; float: left; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK8AAACvABQqw0mAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTM5jWRgMAAAAVdEVYdENyZWF0aW9uIFRpbWUAMy8xNC8wOeNZPpQAAAE2SURBVDiNrZTBccIwEEXfelIAHUA6CZ24BGaWO+FuzZAK4k6gg5QAdGAq+Bxs2Yqx7BzyL7Llp/VfzZeQhCTc/ezuGzKKnKSzpCxXJM8fwNXda3df5RZETlIt6YUzSQDs93sl8w3wBZxCCE10GM1OcWbWjB2mWgEH4Mfdyxm3PSepBHibgQE2wLe7r4HjEidpnXMYdQPKEMJcsZ4zs2POYQOcaPfwMVOo58zsAdMt18BuoVDPxUJRacELbXv3hUIX2vYmOUvi8C8ydz/ThjXrqKqqLbDIAdsCKBd+Wo7GWa7o9qzOQHVVVXeAbs+yHHCH4aTsaCOQqunmUy1yBUAXkdMIfMlgF5EXLo2OpV/c/Up7jG4hhHcYLgWzAZXUc2b2ixsfvc/RmNNfOXD3Q/oeL9axJE1yT9IOoUu6MGUkAAAAAElFTkSuQmCC) no-repeat bottom left; }
23
- li.collapsed a.toggle { opacity: 0.5; cursor: default; background-position: top left; }
24
- li { color: #888; cursor: pointer; }
23
+ li.collapsed a.toggle { cursor: default; background-position: top left; }
24
+ li { color: #666; cursor: pointer; }
25
25
  li.deprecated { text-decoration: line-through; font-style: italic; }
26
26
  li.odd { background: #f0f0f0; }
27
27
  li.even { background: #fafafa; }
@@ -47,7 +47,7 @@ li small { display: block; font-size: 0.8em; }
47
47
  li small:before { content: ""; }
48
48
  li small:after { content: ""; }
49
49
  li small.search_info { display: none; }
50
- #search { width: 170px; position: static; margin: 3px; margin-left: 10px; font-size: 0.9em; color: #888; padding-left: 0; padding-right: 24px; }
50
+ #search { width: 170px; position: static; margin: 3px; margin-left: 10px; font-size: 0.9em; color: #666; padding-left: 0; padding-right: 24px; }
51
51
  #content.insearch #search { background-position: center right; }
52
52
  #search input { width: 110px; }
53
53
 
@@ -82,6 +82,11 @@ body {
82
82
  #search { display: none; }
83
83
  }
84
84
 
85
+ @media (max-width: 320px) {
86
+ body { height: 100%; overflow: hidden; overflow-wrap: break-word; }
87
+ #main { height: 100%; overflow: auto; }
88
+ }
89
+
85
90
  #main img { max-width: 100%; }
86
91
  h1 { font-size: 25px; margin: 1em 0 0.5em; padding-top: 4px; border-top: 1px dotted #d5d5d5; }
87
92
  h1.noborder { border-top: 0px; margin-top: 0; padding-top: 4px; }
@@ -106,6 +111,7 @@ h2 small a {
106
111
  position: relative;
107
112
  padding: 2px 7px;
108
113
  }
114
+ a { font-weight: 550; }
109
115
  .clear { clear: both; }
110
116
  .inline { display: inline; }
111
117
  .inline p:first-child { display: inline; }
@@ -5,10 +5,15 @@
5
5
  <title><%= options.title %></title>
6
6
  </head>
7
7
  <script type="text/javascript">
8
- var match = decodeURIComponent(window.location.hash).match(/^#!(.+)/);
9
- var name = match ? match[1] : '<%= url_for_main %>';
10
- name = name.replace(/^((\w*):)?[\/\\]*/gm, '').trim();
11
- window.top.location.replace(name)
8
+ var mainUrl = '<%= url_for_main %>';
9
+ try {
10
+ var match = decodeURIComponent(window.location.hash).match(/^#!(.+)/);
11
+ var name = match ? match[1] : mainUrl;
12
+ var url = new URL(name, location.href);
13
+ window.top.location.replace(url.origin === location.origin ? name : mainUrl);
14
+ } catch (e) {
15
+ window.top.location.replace(mainUrl);
16
+ }
12
17
  </script>
13
18
  <noscript>
14
19
  <h1>Oops!</h1>
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html <%= "lang=\"#{html_lang}\"" unless html_lang.nil? %>>
3
3
  <head>
4
4
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
5
5
  <meta charset="<%= charset %>" />
@@ -26,7 +26,10 @@
26
26
  <% end %>
27
27
  </div>
28
28
 
29
- <div id="search">Search: <input type="text" /></div>
29
+ <div id="search">
30
+ <label for="search-class">Search:</label>
31
+ <input id="search-class" type="text" />
32
+ </div>
30
33
  </div>
31
34
 
32
35
  <ul id="full_list" class="<%= @list_class || @list_type %>">