rdoc 8.0.0 → 8.1.0

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 (114) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +1 -3
  3. data/RI.md +75 -75
  4. data/exe/rdoc +2 -2
  5. data/lib/rdoc/code_object/alias.rb +71 -69
  6. data/lib/rdoc/code_object/any_method.rb +305 -303
  7. data/lib/rdoc/code_object/attr.rb +150 -148
  8. data/lib/rdoc/code_object/class_module.rb +798 -792
  9. data/lib/rdoc/code_object/constant.rb +175 -173
  10. data/lib/rdoc/code_object/context/section.rb +142 -138
  11. data/lib/rdoc/code_object/context.rb +926 -958
  12. data/lib/rdoc/code_object/extend.rb +7 -5
  13. data/lib/rdoc/code_object/include.rb +7 -5
  14. data/lib/rdoc/code_object/method_attr.rb +326 -319
  15. data/lib/rdoc/code_object/mixin.rb +97 -95
  16. data/lib/rdoc/code_object/normal_class.rb +77 -78
  17. data/lib/rdoc/code_object/normal_module.rb +61 -59
  18. data/lib/rdoc/code_object/require.rb +23 -39
  19. data/lib/rdoc/code_object/single_class.rb +21 -19
  20. data/lib/rdoc/code_object/top_level.rb +212 -219
  21. data/lib/rdoc/code_object.rb +305 -303
  22. data/lib/rdoc/comment.rb +275 -273
  23. data/lib/rdoc/cross_reference.rb +192 -190
  24. data/lib/rdoc/encoding.rb +105 -103
  25. data/lib/rdoc/erb_partial.rb +13 -11
  26. data/lib/rdoc/erbio.rb +29 -27
  27. data/lib/rdoc/generator/aliki.rb +161 -153
  28. data/lib/rdoc/generator/darkfish.rb +645 -635
  29. data/lib/rdoc/generator/json_index.rb +233 -229
  30. data/lib/rdoc/generator/markup.rb +164 -146
  31. data/lib/rdoc/generator/pot/message_extractor.rb +57 -51
  32. data/lib/rdoc/generator/pot/po.rb +52 -51
  33. data/lib/rdoc/generator/pot/po_entry.rb +138 -132
  34. data/lib/rdoc/generator/pot.rb +85 -81
  35. data/lib/rdoc/generator/ri.rb +23 -19
  36. data/lib/rdoc/generator/template/aliki/DESIGN.md +6 -4
  37. data/lib/rdoc/generator/template/aliki/_footer.rhtml +1 -1
  38. data/lib/rdoc/generator/template/aliki/_head.rhtml +10 -10
  39. data/lib/rdoc/generator/template/aliki/_header.rhtml +29 -44
  40. data/lib/rdoc/generator/template/aliki/_sidebar_search.rhtml +4 -4
  41. data/lib/rdoc/generator/template/aliki/css/rdoc.css +207 -178
  42. data/lib/rdoc/generator/template/aliki/js/aliki.js +60 -84
  43. data/lib/rdoc/generator/template/darkfish/_footer.rhtml +1 -1
  44. data/lib/rdoc/generator.rb +48 -46
  45. data/lib/rdoc/i18n/locale.rb +99 -95
  46. data/lib/rdoc/i18n/text.rb +109 -105
  47. data/lib/rdoc/i18n.rb +7 -5
  48. data/lib/rdoc/markdown/byte_runtime.rb +80 -0
  49. data/lib/rdoc/markdown.kpeg +15 -11
  50. data/lib/rdoc/markdown.rb +40 -47
  51. data/lib/rdoc/markup/block_quote.rb +12 -8
  52. data/lib/rdoc/markup/document.rb +127 -123
  53. data/lib/rdoc/markup/formatter.rb +219 -215
  54. data/lib/rdoc/markup/include.rb +33 -29
  55. data/lib/rdoc/markup/indented_paragraph.rb +37 -33
  56. data/lib/rdoc/markup/inline_parser.rb +281 -277
  57. data/lib/rdoc/markup/list.rb +80 -88
  58. data/lib/rdoc/markup/list_item.rb +73 -85
  59. data/lib/rdoc/markup/paragraph.rb +23 -19
  60. data/lib/rdoc/markup/parser.rb +501 -497
  61. data/lib/rdoc/markup/pre_process.rb +283 -279
  62. data/lib/rdoc/markup/raw.rb +2 -2
  63. data/lib/rdoc/markup/rule.rb +16 -12
  64. data/lib/rdoc/markup/to_ansi.rb +143 -139
  65. data/lib/rdoc/markup/to_bs.rb +72 -68
  66. data/lib/rdoc/markup/to_html.rb +594 -565
  67. data/lib/rdoc/markup/to_html_crossref.rb +234 -230
  68. data/lib/rdoc/markup/to_html_snippet.rb +232 -227
  69. data/lib/rdoc/markup/to_joined_paragraph.rb +36 -32
  70. data/lib/rdoc/markup/to_label.rb +63 -59
  71. data/lib/rdoc/markup/to_markdown.rb +212 -208
  72. data/lib/rdoc/markup/to_rdoc.rb +336 -332
  73. data/lib/rdoc/markup/to_table_of_contents.rb +66 -62
  74. data/lib/rdoc/markup/to_test.rb +60 -56
  75. data/lib/rdoc/markup/to_tt_only.rb +84 -80
  76. data/lib/rdoc/markup/verbatim.rb +62 -58
  77. data/lib/rdoc/markup.rb +198 -196
  78. data/lib/rdoc/options.rb +1063 -1061
  79. data/lib/rdoc/parser/c.rb +1039 -1037
  80. data/lib/rdoc/parser/changelog.rb +319 -315
  81. data/lib/rdoc/parser/markdown.rb +17 -13
  82. data/lib/rdoc/parser/rbs.rb +239 -235
  83. data/lib/rdoc/parser/rd.rb +17 -13
  84. data/lib/rdoc/parser/ruby.rb +1245 -1124
  85. data/lib/rdoc/parser/ruby_colorizer.rb +263 -213
  86. data/lib/rdoc/parser/simple.rb +31 -27
  87. data/lib/rdoc/parser/text.rb +12 -8
  88. data/lib/rdoc/parser.rb +228 -220
  89. data/lib/rdoc/rbs_helper.rb +1 -1
  90. data/lib/rdoc/rd/inline.rb +57 -53
  91. data/lib/rdoc/rd.rb +90 -88
  92. data/lib/rdoc/rdoc.rb +500 -491
  93. data/lib/rdoc/ri/driver.rb +1140 -1135
  94. data/lib/rdoc/ri/formatter.rb +7 -3
  95. data/lib/rdoc/ri/paths.rb +140 -136
  96. data/lib/rdoc/ri/servlet.rb +354 -350
  97. data/lib/rdoc/ri/store.rb +4 -2
  98. data/lib/rdoc/ri/task.rb +55 -51
  99. data/lib/rdoc/ri.rb +14 -12
  100. data/lib/rdoc/rubygems_hook.rb +183 -181
  101. data/lib/rdoc/server.rb +349 -347
  102. data/lib/rdoc/stats/normal.rb +46 -42
  103. data/lib/rdoc/stats/quiet.rb +39 -35
  104. data/lib/rdoc/stats/verbose.rb +35 -31
  105. data/lib/rdoc/stats.rb +365 -363
  106. data/lib/rdoc/store.rb +888 -902
  107. data/lib/rdoc/task.rb +260 -256
  108. data/lib/rdoc/text.rb +135 -133
  109. data/lib/rdoc/token_stream.rb +101 -93
  110. data/lib/rdoc/tom_doc.rb +203 -201
  111. data/lib/rdoc/version.rb +1 -1
  112. metadata +4 -5
  113. data/lib/rdoc/markdown/literals.kpeg +0 -21
  114. data/lib/rdoc/markdown/literals.rb +0 -454
@@ -47,6 +47,8 @@ function createSearchInstance(input, result) {
47
47
  html += `<span class="search-type search-type-${this.escapeHTML(typeClass)}">${typeLabel}</span>`;
48
48
  }
49
49
 
50
+ html += '</p>';
51
+
50
52
  if (result.snippet)
51
53
  html += `<div class="search-snippet">${result.snippet}</div>`;
52
54
 
@@ -75,10 +77,15 @@ function createSearchInstance(input, result) {
75
77
 
76
78
  function hookSearch() {
77
79
  const input = document.querySelector('#search-field');
78
- const result = document.querySelector('#search-results-desktop');
80
+ const result = document.querySelector('#search-results');
79
81
 
80
82
  if (!input || !result) return; // Exit if search elements not found
81
83
 
84
+ const container = input.closest('[data-search-container]');
85
+ const searchToggle = document.querySelector('#search-toggle');
86
+ const searchEmpty = container && container.querySelector('.search-empty');
87
+ let focusBeforeOpen = null;
88
+
82
89
  const search_section = document.querySelector('#search-section');
83
90
  if (search_section) {
84
91
  search_section.classList.remove("initially-hidden");
@@ -87,23 +94,65 @@ function hookSearch() {
87
94
  const search = createSearchInstance(input, result);
88
95
  if (!search) return;
89
96
 
97
+ if (searchEmpty) {
98
+ const originalRenderItem = search.renderItem;
99
+ search.renderItem = function(result) {
100
+ searchEmpty.style.display = 'none';
101
+ return originalRenderItem.call(this, result);
102
+ };
103
+ }
104
+
105
+ const showSearchSurface = () => {
106
+ if (container) container.classList.add('is-open');
107
+ if (searchToggle) searchToggle.setAttribute('aria-expanded', 'true');
108
+ };
109
+
110
+ const openSearch = () => {
111
+ focusBeforeOpen = document.activeElement;
112
+ showSearchSurface();
113
+ input.focus({ preventScroll: true });
114
+ };
115
+
116
+ const closeSearch = (restoreFocus = true) => {
117
+ if (container) container.classList.remove('is-open');
118
+ if (searchToggle) searchToggle.setAttribute('aria-expanded', 'false');
119
+ search.hide();
120
+ input.blur();
121
+
122
+ if (restoreFocus && focusBeforeOpen && typeof focusBeforeOpen.focus === 'function') {
123
+ focusBeforeOpen.focus({ preventScroll: true });
124
+ }
125
+ focusBeforeOpen = null;
126
+ };
127
+
128
+ if (searchToggle) searchToggle.addEventListener('click', openSearch);
129
+ if (container) {
130
+ container.querySelectorAll('[data-search-close]').forEach((control) => {
131
+ control.addEventListener('click', () => closeSearch());
132
+ });
133
+ }
134
+
135
+ hookFocus(openSearch);
136
+
90
137
  // Hide search results when clicking outside the search area
91
138
  document.addEventListener('click', (e) => {
92
- if (!e.target.closest('.navbar-search-desktop')) {
93
- search.hide();
94
- }
139
+ if (container && container.contains(e.target)) return;
140
+
141
+ search.hide();
142
+ if (container && container.classList.contains('is-open')) closeSearch(false);
95
143
  });
96
144
 
97
- // Hide search results on Escape key on desktop too
145
+ // Close the search surface on Escape
98
146
  document.addEventListener('keydown', (e) => {
99
- if (e.key === 'Escape' && input.matches(":focus")) {
100
- search.hide();
101
- input.blur();
147
+ const isOpen = container && container.classList.contains('is-open');
148
+ if (e.key === 'Escape' && (isOpen || input.matches(":focus"))) {
149
+ closeSearch();
102
150
  }
103
151
  });
104
152
 
105
153
  // Show search results when focusing on input (if there's a query)
106
154
  input.addEventListener('focus', () => {
155
+ showSearchSurface();
107
156
  if (input.value.trim()) {
108
157
  search.show();
109
158
  }
@@ -114,6 +163,7 @@ function hookSearch() {
114
163
  const urlParams = new URLSearchParams(window.location.search);
115
164
  const queryParam = urlParams.get('q');
116
165
  if (queryParam) {
166
+ openSearch();
117
167
  input.value = queryParam;
118
168
  search.search(queryParam, false);
119
169
  }
@@ -122,14 +172,14 @@ function hookSearch() {
122
172
 
123
173
  /* ===== Keyboard Shortcuts ===== */
124
174
 
125
- function hookFocus() {
175
+ function hookFocus(openSearch) {
126
176
  document.addEventListener("keydown", (event) => {
127
177
  if (document.activeElement.tagName === 'INPUT') {
128
178
  return;
129
179
  }
130
180
  if (event.key === "/") {
131
181
  event.preventDefault();
132
- document.querySelector('#search-field').focus();
182
+ openSearch();
133
183
  }
134
184
  });
135
185
  }
@@ -328,78 +378,6 @@ function setHeadingSelfLinkScrollHandlers() {
328
378
  })
329
379
  }
330
380
 
331
- /* ===== Mobile Search Modal ===== */
332
-
333
- function hookSearchModal() {
334
- const searchToggle = document.querySelector('#search-toggle');
335
- const searchModal = document.querySelector('#search-modal');
336
- const searchModalClose = document.querySelector('#search-modal-close');
337
- const searchModalBackdrop = document.querySelector('.search-modal-backdrop');
338
- const searchInput = document.querySelector('#search-field-mobile');
339
- const searchResults = document.querySelector('#search-results-mobile');
340
- const searchEmpty = document.querySelector('.search-modal-empty');
341
-
342
- if (!searchToggle || !searchModal) return;
343
-
344
- // Initialize search for mobile modal
345
- const mobileSearch = createSearchInstance(searchInput, searchResults);
346
- if (!mobileSearch) return;
347
-
348
- // Hide empty state when there are results
349
- const originalRenderItem = mobileSearch.renderItem;
350
- mobileSearch.renderItem = function(result) {
351
- if (searchEmpty) searchEmpty.style.display = 'none';
352
- return originalRenderItem.call(this, result);
353
- };
354
-
355
- const openSearchModal = () => {
356
- searchModal.hidden = false;
357
- document.body.style.overflow = 'hidden';
358
- // Focus input after animation
359
- setTimeout(() => {
360
- if (searchInput) searchInput.focus();
361
- }, 100);
362
- };
363
-
364
- const closeSearchModal = () => {
365
- searchModal.hidden = true;
366
- document.body.style.overflow = '';
367
- };
368
-
369
- // Open on button click
370
- searchToggle.addEventListener('click', openSearchModal);
371
-
372
- // Close on close button click
373
- if (searchModalClose) {
374
- searchModalClose.addEventListener('click', closeSearchModal);
375
- }
376
-
377
- // Close on backdrop click
378
- if (searchModalBackdrop) {
379
- searchModalBackdrop.addEventListener('click', closeSearchModal);
380
- }
381
-
382
- // Close on Escape key
383
- document.addEventListener('keydown', (e) => {
384
- if (e.key === 'Escape' && !searchModal.hidden) {
385
- closeSearchModal();
386
- }
387
- });
388
-
389
- // Check for ?q= URL parameter on mobile and open modal
390
- if (typeof URLSearchParams !== 'undefined') {
391
- const urlParams = new URLSearchParams(window.location.search);
392
- const queryParam = urlParams.get('q');
393
- const isSmallViewport = window.matchMedia("(max-width: 1023px)").matches;
394
-
395
- if (queryParam && isSmallViewport) {
396
- openSearchModal();
397
- searchInput.value = queryParam;
398
- mobileSearch.search(queryParam, false);
399
- }
400
- }
401
- }
402
-
403
381
  /* ===== Code Block Copy Functionality ===== */
404
382
 
405
383
  function createCopyButton() {
@@ -503,11 +481,9 @@ function showCopySuccess(button) {
503
481
  document.addEventListener('DOMContentLoaded', () => {
504
482
  hookSourceViews();
505
483
  hookSearch();
506
- hookFocus();
507
484
  hookSidebar();
508
485
  generateToc();
509
486
  setHeadingSelfLinkScrollHandlers();
510
487
  hookTocActiveHighlighting();
511
- hookSearchModal();
512
488
  wrapCodeBlocksWithCopyButton();
513
489
  });
@@ -1,5 +1,5 @@
1
1
  <footer id="validator-badges" role="contentinfo">
2
2
  <p><a href="https://validator.w3.org/check/referer">Validate</a></p>
3
- <p>Generated by <a href="https://ruby.github.io/rdoc/">RDoc</a> <%= RDoc::VERSION %>.</p>
3
+ <p>Generated by <a href="https://ruby.github.io/rdoc/">RDoc</a> <%= VERSION %>.</p>
4
4
  <p>Based on <a href="http://deveiate.org/projects/Darkfish-RDoc/">Darkfish</a> by <a href="http://deveiate.org">Michael Granger</a>.</p>
5
5
  </footer>
@@ -1,52 +1,54 @@
1
1
  # frozen_string_literal: true
2
- ##
3
- # RDoc uses generators to turn parsed source code in the form of an
4
- # RDoc::CodeObject tree into some form of output. RDoc comes with the HTML
5
- # generator RDoc::Generator::Darkfish and an ri data generator
6
- # RDoc::Generator::RI.
7
- #
8
- # == Registering a Generator
9
- #
10
- # Generators are registered by calling RDoc::RDoc.add_generator with the class
11
- # of the generator:
12
- #
13
- # class My::Awesome::Generator
14
- # RDoc::RDoc.add_generator self
15
- # end
16
- #
17
- # == Adding Options to +rdoc+
18
- #
19
- # Before option processing in +rdoc+, RDoc::Options will call ::setup_options
20
- # on the generator class with an RDoc::Options instance. The generator can
21
- # use RDoc::Options#option_parser to add command-line options to the +rdoc+
22
- # tool. See RDoc::Options@Custom+Options for an example and see OptionParser
23
- # for details on how to add options.
24
- #
25
- # You can extend the RDoc::Options instance with additional accessors for your
26
- # generator.
27
- #
28
- # == Generator Instantiation
29
- #
30
- # After parsing, RDoc::RDoc will instantiate a generator by calling
31
- # #initialize with an RDoc::Store instance and an RDoc::Options instance.
32
- #
33
- # The RDoc::Store instance holds documentation for parsed source code. In
34
- # RDoc 3 and earlier the RDoc::TopLevel class held this data. When upgrading
35
- # a generator from RDoc 3 and earlier you should only need to replace
36
- # RDoc::TopLevel with the store instance.
37
- #
38
- # RDoc will then call #generate on the generator instance. You can use the
39
- # various methods on RDoc::Store and in the RDoc::CodeObject tree to create
40
- # your desired output format.
2
+ module RDoc
3
+ ##
4
+ # RDoc uses generators to turn parsed source code in the form of an
5
+ # RDoc::CodeObject tree into some form of output. RDoc comes with the HTML
6
+ # generator RDoc::Generator::Darkfish and an ri data generator
7
+ # RDoc::Generator::RI.
8
+ #
9
+ # == Registering a Generator
10
+ #
11
+ # Generators are registered by calling RDoc::RDoc.add_generator with the class
12
+ # of the generator:
13
+ #
14
+ # class My::Awesome::Generator
15
+ # RDoc::RDoc.add_generator self
16
+ # end
17
+ #
18
+ # == Adding Options to +rdoc+
19
+ #
20
+ # Before option processing in +rdoc+, RDoc::Options will call ::setup_options
21
+ # on the generator class with an RDoc::Options instance. The generator can
22
+ # use RDoc::Options#option_parser to add command-line options to the +rdoc+
23
+ # tool. See RDoc::Options@Custom+Options for an example and see OptionParser
24
+ # for details on how to add options.
25
+ #
26
+ # You can extend the RDoc::Options instance with additional accessors for your
27
+ # generator.
28
+ #
29
+ # == Generator Instantiation
30
+ #
31
+ # After parsing, RDoc::RDoc will instantiate a generator by calling
32
+ # #initialize with an RDoc::Store instance and an RDoc::Options instance.
33
+ #
34
+ # The RDoc::Store instance holds documentation for parsed source code. In
35
+ # RDoc 3 and earlier the RDoc::TopLevel class held this data. When upgrading
36
+ # a generator from RDoc 3 and earlier you should only need to replace
37
+ # RDoc::TopLevel with the store instance.
38
+ #
39
+ # RDoc will then call #generate on the generator instance. You can use the
40
+ # various methods on RDoc::Store and in the RDoc::CodeObject tree to create
41
+ # your desired output format.
41
42
 
42
- module RDoc::Generator
43
+ module Generator
43
44
 
44
- autoload :Markup, "#{__dir__}/generator/markup"
45
+ autoload :Markup, "#{__dir__}/generator/markup"
45
46
 
46
- autoload :Aliki, "#{__dir__}/generator/aliki"
47
- autoload :Darkfish, "#{__dir__}/generator/darkfish"
48
- autoload :JsonIndex, "#{__dir__}/generator/json_index"
49
- autoload :RI, "#{__dir__}/generator/ri"
50
- autoload :POT, "#{__dir__}/generator/pot"
47
+ autoload :Aliki, "#{__dir__}/generator/aliki"
48
+ autoload :Darkfish, "#{__dir__}/generator/darkfish"
49
+ autoload :JsonIndex, "#{__dir__}/generator/json_index"
50
+ autoload :RI, "#{__dir__}/generator/ri"
51
+ autoload :POT, "#{__dir__}/generator/pot"
51
52
 
53
+ end
52
54
  end
@@ -1,102 +1,106 @@
1
1
  # frozen_string_literal: true
2
- ##
3
- # A message container for a locale.
4
- #
5
- # This object provides the following two features:
6
- #
7
- # * Loads translated messages from .po file.
8
- # * Translates a message into the locale.
9
-
10
- class RDoc::I18n::Locale
11
-
12
- @@locales = {} # :nodoc:
13
-
14
- class << self
15
-
2
+ module RDoc
3
+ module I18n
16
4
  ##
17
- # Returns the locale object for +locale_name+.
18
-
19
- def [](locale_name)
20
- @@locales[locale_name] ||= new(locale_name)
21
- end
22
-
23
- ##
24
- # Sets the locale object for +locale_name+.
5
+ # A message container for a locale.
25
6
  #
26
- # Normally, this method is not used. This method is useful for
27
- # testing.
28
-
29
- def []=(locale_name, locale)
30
- @@locales[locale_name] = locale
31
- end
32
-
33
- end
34
-
35
- ##
36
- # The name of the locale. It uses IETF language tag format
37
- # +[language[_territory][.codeset][@modifier]]+.
38
- #
39
- # See also {BCP 47 - Tags for Identifying
40
- # Languages}[http://tools.ietf.org/rfc/bcp/bcp47.txt].
41
-
42
- attr_reader :name
43
-
44
- ##
45
- # Creates a new locale object for +name+ locale. +name+ must
46
- # follow IETF language tag format.
47
-
48
- def initialize(name)
49
- @name = name
50
- @messages = {}
51
- end
7
+ # This object provides the following two features:
8
+ #
9
+ # * Loads translated messages from .po file.
10
+ # * Translates a message into the locale.
11
+
12
+ class Locale
13
+
14
+ @@locales = {} # :nodoc:
15
+
16
+ class << self
17
+
18
+ ##
19
+ # Returns the locale object for +locale_name+.
20
+
21
+ def [](locale_name)
22
+ @@locales[locale_name] ||= new(locale_name)
23
+ end
24
+
25
+ ##
26
+ # Sets the locale object for +locale_name+.
27
+ #
28
+ # Normally, this method is not used. This method is useful for
29
+ # testing.
30
+
31
+ def []=(locale_name, locale)
32
+ @@locales[locale_name] = locale
33
+ end
34
+
35
+ end
36
+
37
+ ##
38
+ # The name of the locale. It uses IETF language tag format
39
+ # +[language[_territory][.codeset][@modifier]]+.
40
+ #
41
+ # See also {BCP 47 - Tags for Identifying
42
+ # Languages}[http://tools.ietf.org/rfc/bcp/bcp47.txt].
43
+
44
+ attr_reader :name
45
+
46
+ ##
47
+ # Creates a new locale object for +name+ locale. +name+ must
48
+ # follow IETF language tag format.
49
+
50
+ def initialize(name)
51
+ @name = name
52
+ @messages = {}
53
+ end
54
+
55
+ ##
56
+ # Loads translation messages from +locale_directory+/+@name+/rdoc.po
57
+ # or +locale_directory+/+@name+.po. The former has high priority.
58
+ #
59
+ # This method requires gettext gem for parsing .po file. If you
60
+ # don't have gettext gem, this method doesn't load .po file. This
61
+ # method warns and returns +false+.
62
+ #
63
+ # Returns +true+ if succeeded, +false+ otherwise.
64
+
65
+ def load(locale_directory)
66
+ return false if @name.nil?
67
+
68
+ po_file_candidates = [
69
+ File.join(locale_directory, @name, 'rdoc.po'),
70
+ File.join(locale_directory, "#{@name}.po"),
71
+ ]
72
+ po_file = po_file_candidates.find do |po_file_candidate|
73
+ File.exist?(po_file_candidate)
74
+ end
75
+ return false unless po_file
76
+
77
+ begin
78
+ require 'gettext/po_parser'
79
+ require 'gettext/mo'
80
+ rescue LoadError
81
+ warn('Need gettext gem for i18n feature:')
82
+ warn(' gem install gettext')
83
+ return false
84
+ end
85
+
86
+ po_parser = GetText::POParser.new
87
+ messages = GetText::MO.new
88
+ po_parser.report_warning = false
89
+ po_parser.parse_file(po_file, messages)
90
+
91
+ @messages.merge!(messages)
92
+
93
+ true
94
+ end
95
+
96
+ ##
97
+ # Translates the +message+ into locale. If there is no translation
98
+ # messages for +message+ in locale, +message+ itself is returned.
99
+
100
+ def translate(message)
101
+ @messages[message] || message
102
+ end
52
103
 
53
- ##
54
- # Loads translation messages from +locale_directory+/+@name+/rdoc.po
55
- # or +locale_directory+/+@name+.po. The former has high priority.
56
- #
57
- # This method requires gettext gem for parsing .po file. If you
58
- # don't have gettext gem, this method doesn't load .po file. This
59
- # method warns and returns +false+.
60
- #
61
- # Returns +true+ if succeeded, +false+ otherwise.
62
-
63
- def load(locale_directory)
64
- return false if @name.nil?
65
-
66
- po_file_candidates = [
67
- File.join(locale_directory, @name, 'rdoc.po'),
68
- File.join(locale_directory, "#{@name}.po"),
69
- ]
70
- po_file = po_file_candidates.find do |po_file_candidate|
71
- File.exist?(po_file_candidate)
72
- end
73
- return false unless po_file
74
-
75
- begin
76
- require 'gettext/po_parser'
77
- require 'gettext/mo'
78
- rescue LoadError
79
- warn('Need gettext gem for i18n feature:')
80
- warn(' gem install gettext')
81
- return false
82
104
  end
83
-
84
- po_parser = GetText::POParser.new
85
- messages = GetText::MO.new
86
- po_parser.report_warning = false
87
- po_parser.parse_file(po_file, messages)
88
-
89
- @messages.merge!(messages)
90
-
91
- true
92
- end
93
-
94
- ##
95
- # Translates the +message+ into locale. If there is no translation
96
- # messages for +message+ in locale, +message+ itself is returned.
97
-
98
- def translate(message)
99
- @messages[message] || message
100
105
  end
101
-
102
106
  end