packnga 0.9.4 → 0.9.5
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.
- data/Gemfile +1 -10
- data/README.textile +5 -2
- data/Rakefile +9 -44
- data/doc/text/news.textile +28 -1
- data/doc/text/release.textile +53 -33
- data/doc/text/tutorial.textile +92 -15
- data/lib/packnga.rb +1 -2
- data/lib/packnga/document-task.rb +49 -15
- data/lib/packnga/reference-task.rb +539 -54
- data/lib/packnga/release-task.rb +7 -7
- data/lib/packnga/version.rb +2 -2
- data/lib/packnga/yard-task.rb +18 -27
- metadata +166 -132
data/lib/packnga.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
#
|
3
|
-
# Copyright (C) 2011
|
3
|
+
# Copyright (C) 2011 Haruka Yoshihara <yoshihara@clear-code.com>
|
4
4
|
#
|
5
5
|
# This library is free software; you can redistribute it and/or
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -19,5 +19,4 @@ require "rake"
|
|
19
19
|
|
20
20
|
require "packnga/version"
|
21
21
|
require "packnga/document-task"
|
22
|
-
require "packnga/reference-task"
|
23
22
|
require "packnga/release-task"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
#
|
3
|
-
# Copyright (C) 2011
|
3
|
+
# Copyright (C) 2011 Haruka Yoshihara <yoshihara@clear-code.com>
|
4
4
|
# Copyright (C) 2011 Kouhei Sutou <kou@clear-code.com>
|
5
5
|
#
|
6
6
|
# This library is free software; you can redistribute it and/or
|
@@ -21,34 +21,26 @@ require "packnga/yard-task"
|
|
21
21
|
require "packnga/reference-task"
|
22
22
|
|
23
23
|
module Packnga
|
24
|
-
# This class creates
|
25
|
-
# They generate YARD
|
24
|
+
# This class creates tasks for document.
|
25
|
+
# They generate YARD document or references.
|
26
26
|
#
|
27
27
|
# @since 0.9.0
|
28
28
|
class DocumentTask
|
29
29
|
include Rake::DSL
|
30
30
|
# Defines tasks to generate YARD documentation
|
31
31
|
# and to translate references.
|
32
|
-
# @param [
|
32
|
+
# @param [Gem::Specification] spec specification for your package
|
33
33
|
def initialize(spec)
|
34
34
|
@spec = spec
|
35
35
|
@yard_task = YARDTask.new(@spec)
|
36
36
|
@reference_task = ReferenceTask.new(@spec)
|
37
37
|
self.base_dir = "doc"
|
38
|
-
if block_given?
|
39
|
-
|
40
|
-
define
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# @private
|
45
|
-
def define
|
46
|
-
set_default_values
|
47
|
-
define_tasks
|
38
|
+
yield(self) if block_given?
|
39
|
+
define
|
48
40
|
end
|
49
41
|
|
50
42
|
# Sets base directory for documents. Default value is "doc".
|
51
|
-
# @param [String] base direcory path
|
43
|
+
# @param [String] dir base direcory path
|
52
44
|
def base_dir=(dir)
|
53
45
|
dir = Pathname.new(dir)
|
54
46
|
@yard_task.base_dir = dir
|
@@ -70,7 +62,49 @@ module Packnga
|
|
70
62
|
end
|
71
63
|
|
72
64
|
private
|
65
|
+
def define
|
66
|
+
set_default_values
|
67
|
+
define_tasks
|
68
|
+
end
|
69
|
+
|
73
70
|
def set_default_values
|
71
|
+
set_default_readme
|
72
|
+
set_default_source_files
|
73
|
+
set_default_text_files
|
74
|
+
end
|
75
|
+
|
76
|
+
def set_default_readme
|
77
|
+
readme = @spec.files.find do |file|
|
78
|
+
file.include?("README")
|
79
|
+
end
|
80
|
+
@yard_task.readme = readme
|
81
|
+
@reference_task.readme = readme
|
82
|
+
end
|
83
|
+
|
84
|
+
def set_default_source_files
|
85
|
+
source_files = @spec.files.find_all do |file|
|
86
|
+
ruby_source_file?(file) or
|
87
|
+
c_source_file?(file)
|
88
|
+
end
|
89
|
+
@yard_task.source_files = source_files
|
90
|
+
@reference_task.source_files = source_files
|
91
|
+
end
|
92
|
+
|
93
|
+
def ruby_source_file?(file)
|
94
|
+
file.start_with?("lib/") and file.end_with?(".rb")
|
95
|
+
end
|
96
|
+
|
97
|
+
def c_source_file?(file)
|
98
|
+
file.start_with?("ext/") and file.end_with?(".c")
|
99
|
+
end
|
100
|
+
|
101
|
+
def set_default_text_files
|
102
|
+
text_dir = @yard_task.base_dir + "text"
|
103
|
+
text_files = @spec.files.find_all do |file|
|
104
|
+
file.start_with?(text_dir.to_s)
|
105
|
+
end
|
106
|
+
@yard_task.text_files = text_files
|
107
|
+
@reference_task.text_files = text_files
|
74
108
|
end
|
75
109
|
|
76
110
|
def define_tasks
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
#
|
3
|
-
# Copyright (C) 2011
|
3
|
+
# Copyright (C) 2011 Haruka Yoshihara <yoshihara@clear-code.com>
|
4
4
|
#
|
5
5
|
# This library is free software; you can redistribute it and/or
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -16,6 +16,10 @@
|
|
16
16
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
17
|
|
18
18
|
require "erb"
|
19
|
+
require "gettext/tools"
|
20
|
+
require "tempfile"
|
21
|
+
require "tmpdir"
|
22
|
+
require "rake/clean"
|
19
23
|
|
20
24
|
module Packnga
|
21
25
|
# This class creates reference tasks.
|
@@ -26,27 +30,36 @@ module Packnga
|
|
26
30
|
include Rake::DSL
|
27
31
|
include ERB::Util
|
28
32
|
|
33
|
+
# This attribute is used to set path of base directory of document.
|
29
34
|
# @return [String] path of base directory of document
|
30
|
-
|
35
|
+
attr_accessor :base_dir
|
31
36
|
|
32
|
-
#
|
33
|
-
|
37
|
+
# This attribute is used to set README file.
|
38
|
+
# @return [String] path of readme file
|
39
|
+
attr_accessor :readme
|
40
|
+
|
41
|
+
# This attribute is used to set source files for document.
|
42
|
+
# @return [Array<String>] target source files
|
43
|
+
attr_accessor :source_files
|
44
|
+
|
45
|
+
# This attribute is used to set text files for document.
|
46
|
+
# @return [Array<String>] target text files
|
47
|
+
attr_accessor :text_files
|
34
48
|
|
35
49
|
# @private
|
36
50
|
def initialize(spec)
|
37
51
|
@spec = spec
|
38
52
|
@base_dir = nil
|
39
|
-
@mode = nil
|
40
53
|
@translate_languages = nil
|
41
54
|
@supported_languages = nil
|
55
|
+
@source_files = nil
|
56
|
+
@text_files = nil
|
57
|
+
@readme = nil
|
58
|
+
@extra_files = nil
|
59
|
+
@files = nil
|
42
60
|
@html_files = nil
|
43
|
-
@htaccess = nil
|
44
61
|
@po_dir = nil
|
45
62
|
@pot_file = nil
|
46
|
-
if block_given?
|
47
|
-
yield(self)
|
48
|
-
define
|
49
|
-
end
|
50
63
|
end
|
51
64
|
|
52
65
|
# @private
|
@@ -63,12 +76,14 @@ module Packnga
|
|
63
76
|
private
|
64
77
|
def set_default_values
|
65
78
|
@base_dir ||= Pathname.new("doc")
|
66
|
-
@mode ||= "docbook"
|
67
79
|
@translate_languages ||= [:ja]
|
68
80
|
@supported_languages = [:en, *@translate_languages]
|
69
81
|
@html_files = FileList[(doc_en_dir + "**/*.html").to_s].to_a
|
70
|
-
@po_dir = "
|
82
|
+
@po_dir = "#{@base_dir}/po"
|
71
83
|
@pot_file = "#{@po_dir}/#{@spec.name}.pot"
|
84
|
+
@extra_files = @text_files
|
85
|
+
@extra_files += [@readme] if @readme
|
86
|
+
@files = @source_files + @extra_files
|
72
87
|
end
|
73
88
|
|
74
89
|
def reference_base_dir
|
@@ -100,14 +115,9 @@ module Packnga
|
|
100
115
|
def define_pot_tasks
|
101
116
|
namespace :pot do
|
102
117
|
directory @po_dir
|
103
|
-
file @pot_file => [@po_dir, *@
|
104
|
-
|
105
|
-
"--keep-entities",
|
106
|
-
"--mode", @mode,
|
107
|
-
"--output", t.name,
|
108
|
-
*@html_files)
|
118
|
+
file @pot_file => [@po_dir, *@files] do |t|
|
119
|
+
create_pot_file(@pot_file)
|
109
120
|
end
|
110
|
-
|
111
121
|
desc "Generates pot file."
|
112
122
|
task :generate => @pot_file do |t|
|
113
123
|
end
|
@@ -117,23 +127,22 @@ module Packnga
|
|
117
127
|
def define_po_tasks
|
118
128
|
namespace :po do
|
119
129
|
namespace :update do
|
120
|
-
|
130
|
+
@translate_languages.each do |language|
|
121
131
|
po_file = "#{@po_dir}/#{language}.po"
|
122
132
|
|
123
133
|
if File.exist?(po_file)
|
124
|
-
file po_file => @
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
134
|
+
file po_file => @files do |t|
|
135
|
+
current_pot_file = "tmp.pot"
|
136
|
+
create_pot_file(current_pot_file)
|
137
|
+
GetText.msgmerge(po_file, current_pot_file,
|
138
|
+
"#{@spec.name} #{Packnga::VERSION}")
|
139
|
+
FileUtils.rm_f(current_pot_file)
|
130
140
|
end
|
131
141
|
else
|
132
142
|
file po_file => @pot_file do |t|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
"--locale=#{language}")
|
143
|
+
GetText::Tools::MsgInit.run("--input", @pot_file,
|
144
|
+
"--output", t.name,
|
145
|
+
"--locale", language.to_s)
|
137
146
|
end
|
138
147
|
end
|
139
148
|
|
@@ -144,41 +153,35 @@ module Packnga
|
|
144
153
|
|
145
154
|
desc "Updates po files."
|
146
155
|
task :update do
|
147
|
-
|
148
|
-
ruby($0, "yard")
|
156
|
+
Rake::Task["clobber"].invoke
|
149
157
|
@translate_languages.each do |language|
|
150
|
-
|
158
|
+
Rake::Task["reference:po:update:#{language}"].invoke
|
151
159
|
end
|
152
160
|
end
|
153
161
|
end
|
154
162
|
end
|
155
163
|
|
164
|
+
def create_pot_file(pot_file_path)
|
165
|
+
options = ["-o", pot_file_path]
|
166
|
+
options += @source_files
|
167
|
+
options += ["-"]
|
168
|
+
options += @extra_files
|
169
|
+
YARD::CLI::I18n.run(*options)
|
170
|
+
end
|
171
|
+
|
156
172
|
def define_translate_task
|
173
|
+
directory reference_base_dir.to_s
|
157
174
|
namespace :translate do
|
158
175
|
@translate_languages.each do |language|
|
159
176
|
po_file = "#{@po_dir}/#{language}.po"
|
160
|
-
translate_doc_dir = "#{reference_base_dir}/#{language}"
|
161
177
|
desc "Translates documents to #{language}."
|
162
|
-
task language => [po_file, reference_base_dir, *@
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
end
|
170
|
-
case path.extname
|
171
|
-
when ".html"
|
172
|
-
sh("xml2po",
|
173
|
-
"--keep-entities",
|
174
|
-
"--mode", @mode,
|
175
|
-
"--po-file", po_file.to_s,
|
176
|
-
"--language", language.to_s,
|
177
|
-
"--output", translated_path.to_s,
|
178
|
-
path.to_s)
|
179
|
-
else
|
180
|
-
cp(path.to_s, translated_path, :preserve => true)
|
181
|
-
end
|
178
|
+
task language => [po_file, reference_base_dir, *@files] do
|
179
|
+
locale = YARD::I18n::Locale.new(language)
|
180
|
+
locale.load(@po_dir)
|
181
|
+
Dir.mktmpdir do |temp_dir|
|
182
|
+
create_translated_sources(temp_dir, locale)
|
183
|
+
copy_extra_files(temp_dir)
|
184
|
+
create_translated_documents(temp_dir, locale)
|
182
185
|
end
|
183
186
|
end
|
184
187
|
end
|
@@ -283,5 +286,487 @@ module Packnga
|
|
283
286
|
erb.filename = file
|
284
287
|
erb
|
285
288
|
end
|
289
|
+
|
290
|
+
def create_translated_documents(output_dir, locale)
|
291
|
+
language = locale.name.to_s
|
292
|
+
translate_doc_dir = "#{reference_base_dir}/#{language}"
|
293
|
+
po_dir = File.expand_path(@po_dir)
|
294
|
+
mkdir_p(translate_doc_dir)
|
295
|
+
|
296
|
+
Dir.chdir(output_dir) do
|
297
|
+
YARD::Registry.clear
|
298
|
+
YARD.parse(@source_files)
|
299
|
+
|
300
|
+
options = [
|
301
|
+
"--title", @spec.name,
|
302
|
+
"-o", translate_doc_dir,
|
303
|
+
"--po-dir", po_dir,
|
304
|
+
"--locale", language,
|
305
|
+
"--charset", "utf-8",
|
306
|
+
"--no-private"
|
307
|
+
]
|
308
|
+
options += ["--readme", @readme] if @readme
|
309
|
+
options += @source_files
|
310
|
+
options += ["-"]
|
311
|
+
options += @text_files
|
312
|
+
|
313
|
+
YARD::CLI::Yardoc.run(*options)
|
314
|
+
end
|
315
|
+
translated_files = File.join(output_dir, translate_doc_dir, "**")
|
316
|
+
FileUtils.cp_r(Dir.glob(translated_files), translate_doc_dir)
|
317
|
+
end
|
318
|
+
|
319
|
+
def create_translated_sources(output_dir, locale)
|
320
|
+
YARD.parse(@source_files)
|
321
|
+
create_translated_files(@source_files, output_dir) do |content|
|
322
|
+
code_objects = YARD::Registry.all
|
323
|
+
code_objects.each do |code_object|
|
324
|
+
original_docstring = code_object.docstring
|
325
|
+
content = translate_content_part(content,
|
326
|
+
original_docstring,
|
327
|
+
locale)
|
328
|
+
|
329
|
+
original_docstring.tags.each do |tag|
|
330
|
+
original_tag_text = tag.text
|
331
|
+
next if original_tag_text.nil?
|
332
|
+
content = translate_content_part(content,
|
333
|
+
original_tag_text,
|
334
|
+
locale)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
content
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
def copy_extra_files(output_dir)
|
342
|
+
@extra_files.each do |file|
|
343
|
+
target_extra_file = File.join(output_dir, file)
|
344
|
+
FileUtils.mkdir_p(File.dirname(target_extra_file))
|
345
|
+
FileUtils.cp_r(file, target_extra_file)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
def create_translated_files(original_files, output_dir)
|
350
|
+
original_files.each do |file|
|
351
|
+
translated_file = File.join(output_dir, file)
|
352
|
+
FileUtils.mkdir_p(File.dirname(translated_file))
|
353
|
+
content = File.read(file)
|
354
|
+
|
355
|
+
translated_text = yield(content)
|
356
|
+
|
357
|
+
File.open(translated_file, "w") do |file|
|
358
|
+
file.puts(translated_text)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
def translate_content_part(content, original_text, locale)
|
364
|
+
translated_content = ""
|
365
|
+
text = YARD::I18n::Text.new(original_text)
|
366
|
+
translate_text = text.translate(locale)
|
367
|
+
original_text = original_text.each_line.collect do |line|
|
368
|
+
"(.+)#{Regexp.escape(line)}"
|
369
|
+
end
|
370
|
+
translate_text = translate_text.each_line.collect do |line|
|
371
|
+
"\\1#{line}"
|
372
|
+
end
|
373
|
+
content.sub(/#{original_text.join}/, translate_text.join)
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
# XXX: This module is the patch to translate documents.
|
379
|
+
# This module should be deleted after
|
380
|
+
# https://github.com/lsegal/yard/pull/594 is merged and released.
|
381
|
+
# @private
|
382
|
+
module YARD
|
383
|
+
# @private
|
384
|
+
module I18n
|
385
|
+
# @private
|
386
|
+
class Locale
|
387
|
+
def translate(message)
|
388
|
+
return message if @messages[message].nil?
|
389
|
+
return message if @messages[message].empty?
|
390
|
+
@messages[message]
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
# XXX: This module is the re-definition of YARD module.
|
397
|
+
# this module should be deleted in the next release of YARD.
|
398
|
+
# @private
|
399
|
+
module YARD
|
400
|
+
module CLI
|
401
|
+
# @private
|
402
|
+
class Yardoc
|
403
|
+
def parse_arguments(*args)
|
404
|
+
parse_yardopts_options(*args)
|
405
|
+
|
406
|
+
# Parse files and then command line arguments
|
407
|
+
optparse(*support_rdoc_document_file!) if use_document_file
|
408
|
+
optparse(*yardopts) if use_yardopts_file
|
409
|
+
optparse(*args)
|
410
|
+
|
411
|
+
# Last minute modifications
|
412
|
+
self.files = ['{lib,app}/**/*.rb', 'ext/**/*.c'] if self.files.empty?
|
413
|
+
self.files.delete_if {|x| x =~ /\A\s*\Z/ } # remove empty ones
|
414
|
+
readme = Dir.glob('README*').first
|
415
|
+
readme ||= Dir.glob(files.first).first if options.onefile
|
416
|
+
options.readme ||= CodeObjects::ExtraFileObject.new(readme) if readme
|
417
|
+
options.files.unshift(options.readme).uniq! if options.readme
|
418
|
+
|
419
|
+
Tags::Library.visible_tags -= hidden_tags
|
420
|
+
add_visibility_verifier
|
421
|
+
add_api_verifier
|
422
|
+
|
423
|
+
apply_locale
|
424
|
+
|
425
|
+
# US-ASCII is invalid encoding for onefile
|
426
|
+
if defined?(::Encoding) && options.onefile
|
427
|
+
if ::Encoding.default_internal == ::Encoding::US_ASCII
|
428
|
+
log.warn "--one-file is not compatible with US-ASCII encoding, using ASCII-8BIT"
|
429
|
+
::Encoding.default_external, ::Encoding.default_internal = ['ascii-8bit'] * 2
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
if generate && !verify_markup_options
|
434
|
+
false
|
435
|
+
else
|
436
|
+
true
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
def apply_locale
|
441
|
+
options.files.each do |file|
|
442
|
+
file.locale = options.locale
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
def output_options(opts)
|
447
|
+
opts.separator ""
|
448
|
+
opts.separator "Output options:"
|
449
|
+
|
450
|
+
opts.on('--one-file', 'Generates output as a single file') do
|
451
|
+
options.onefile = true
|
452
|
+
end
|
453
|
+
|
454
|
+
opts.on('--list', 'List objects to standard out (implies -n)') do |format|
|
455
|
+
self.generate = false
|
456
|
+
self.list = true
|
457
|
+
end
|
458
|
+
|
459
|
+
opts.on('--no-public', "Don't show public methods. (default shows public)") do
|
460
|
+
visibilities.delete(:public)
|
461
|
+
end
|
462
|
+
|
463
|
+
opts.on('--protected', "Show protected methods. (default hides protected)") do
|
464
|
+
visibilities.push(:protected)
|
465
|
+
end
|
466
|
+
|
467
|
+
opts.on('--private', "Show private methods. (default hides private)") do
|
468
|
+
visibilities.push(:private)
|
469
|
+
end
|
470
|
+
|
471
|
+
opts.on('--no-private', "Hide objects with @private tag") do
|
472
|
+
options.verifier.add_expressions '!object.tag(:private) &&
|
473
|
+
(object.namespace.is_a?(CodeObjects::Proxy) || !object.namespace.tag(:private))'
|
474
|
+
end
|
475
|
+
|
476
|
+
opts.on('--[no-]api API', 'Generates documentation for a given API',
|
477
|
+
'(objects which define the correct @api tag).',
|
478
|
+
'If --no-api is given, displays objects with',
|
479
|
+
'no @api tag.') do |api|
|
480
|
+
api = '' if api == false
|
481
|
+
apis.push(api)
|
482
|
+
end
|
483
|
+
|
484
|
+
opts.on('--embed-mixins', "Embeds mixin methods into class documentation") do
|
485
|
+
options.embed_mixins << '*'
|
486
|
+
end
|
487
|
+
|
488
|
+
opts.on('--embed-mixin [MODULE]', "Embeds mixin methods from a particular",
|
489
|
+
" module into class documentation") do |mod|
|
490
|
+
options.embed_mixins << mod
|
491
|
+
end
|
492
|
+
|
493
|
+
opts.on('--no-highlight', "Don't highlight code blocks in output.") do
|
494
|
+
options.highlight = false
|
495
|
+
end
|
496
|
+
|
497
|
+
opts.on('--default-return TYPE', "Shown if method has no return type. ",
|
498
|
+
" (defaults to 'Object')") do |type|
|
499
|
+
options.default_return = type
|
500
|
+
end
|
501
|
+
|
502
|
+
opts.on('--hide-void-return', "Hides return types specified as 'void'. ",
|
503
|
+
" (default is shown)") do
|
504
|
+
options.hide_void_return = true
|
505
|
+
end
|
506
|
+
|
507
|
+
opts.on('--query QUERY', "Only show objects that match a specific query") do |query|
|
508
|
+
next if YARD::Config.options[:safe_mode]
|
509
|
+
options.verifier.add_expressions(query.taint)
|
510
|
+
end
|
511
|
+
|
512
|
+
opts.on('--title TITLE', 'Add a specific title to HTML documents') do |title|
|
513
|
+
options.title = title
|
514
|
+
end
|
515
|
+
|
516
|
+
opts.on('-r', '--readme FILE', '--main FILE', 'The readme file used as the title page',
|
517
|
+
' of documentation.') do |readme|
|
518
|
+
if File.file?(readme)
|
519
|
+
options.readme = CodeObjects::ExtraFileObject.new(readme)
|
520
|
+
else
|
521
|
+
log.warn "Could not find readme file: #{readme}"
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
opts.on('--files FILE1,FILE2,...', 'Any extra comma separated static files to be ',
|
526
|
+
' included (eg. FAQ)') do |files|
|
527
|
+
add_extra_files(*files.split(","))
|
528
|
+
end
|
529
|
+
|
530
|
+
opts.on('--asset FROM[:TO]', 'A file or directory to copy over to output ',
|
531
|
+
' directory after generating') do |asset|
|
532
|
+
re = /^(?:\.\.\/|\/)/
|
533
|
+
from, to = *asset.split(':').map {|f| File.cleanpath(f) }
|
534
|
+
to ||= from
|
535
|
+
if from =~ re || to =~ re
|
536
|
+
log.warn "Invalid file '#{asset}'"
|
537
|
+
else
|
538
|
+
assets[from] = to
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
opts.on('-o', '--output-dir PATH',
|
543
|
+
'The output directory. (defaults to ./doc)') do |dir|
|
544
|
+
options.serializer.basepath = dir
|
545
|
+
end
|
546
|
+
|
547
|
+
opts.on('-m', '--markup MARKUP',
|
548
|
+
'Markup style used in documentation, like textile, ',
|
549
|
+
' markdown or rdoc. (defaults to rdoc)') do |markup|
|
550
|
+
self.has_markup = true
|
551
|
+
options.markup = markup.to_sym
|
552
|
+
end
|
553
|
+
|
554
|
+
opts.on('-M', '--markup-provider MARKUP_PROVIDER',
|
555
|
+
'Overrides the library used to process markup ',
|
556
|
+
' formatting (specify the gem name)') do |markup_provider|
|
557
|
+
options.markup_provider = markup_provider.to_sym
|
558
|
+
end
|
559
|
+
|
560
|
+
opts.on('--charset ENC', 'Character set to use when parsing files ',
|
561
|
+
' (default is system locale)') do |encoding|
|
562
|
+
begin
|
563
|
+
if defined?(Encoding) && Encoding.respond_to?(:default_external=)
|
564
|
+
Encoding.default_external, Encoding.default_internal = encoding, encoding
|
565
|
+
end
|
566
|
+
rescue ArgumentError => e
|
567
|
+
raise OptionParser::InvalidOption, e
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
571
|
+
opts.on('-t', '--template TEMPLATE',
|
572
|
+
'The template to use. (defaults to "default")') do |template|
|
573
|
+
options.template = template.to_sym
|
574
|
+
end
|
575
|
+
|
576
|
+
opts.on('-p', '--template-path PATH',
|
577
|
+
'The template path to look for templates in.',
|
578
|
+
' (used with -t).') do |path|
|
579
|
+
next if YARD::Config.options[:safe_mode]
|
580
|
+
YARD::Templates::Engine.register_template_path(File.expand_path(path))
|
581
|
+
end
|
582
|
+
|
583
|
+
opts.on('-f', '--format FORMAT',
|
584
|
+
'The output format for the template.',
|
585
|
+
' (defaults to html)') do |format|
|
586
|
+
options.format = format.to_sym
|
587
|
+
end
|
588
|
+
|
589
|
+
opts.on('--no-stats', 'Don\'t print statistics') do
|
590
|
+
self.statistics = false
|
591
|
+
end
|
592
|
+
|
593
|
+
opts.on('--locale LOCALE',
|
594
|
+
'The locale for generated documentation.',
|
595
|
+
' (defaults to en)') do |locale|
|
596
|
+
options.locale = locale
|
597
|
+
end
|
598
|
+
|
599
|
+
opts.on('--po-dir DIR',
|
600
|
+
'The directory that has .po files.',
|
601
|
+
' (defaults to #{YARD::Registry.po_dir})') do |dir|
|
602
|
+
YARD::Registry.po_dir = dir
|
603
|
+
end
|
604
|
+
end
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
module CodeObjects
|
609
|
+
# @private
|
610
|
+
class ExtraFileObject
|
611
|
+
attr_writer :attributes
|
612
|
+
attr_reader :locale
|
613
|
+
|
614
|
+
def initialize(filename, contents = nil)
|
615
|
+
self.filename = filename
|
616
|
+
self.name = File.basename(filename).gsub(/\.[^.]+$/, '')
|
617
|
+
self.attributes = SymbolHash.new(false)
|
618
|
+
@original_contents = contents
|
619
|
+
@parsed = false
|
620
|
+
@locale = nil
|
621
|
+
ensure_parsed
|
622
|
+
end
|
623
|
+
|
624
|
+
def attributes
|
625
|
+
ensure_parsed
|
626
|
+
@attributes
|
627
|
+
end
|
628
|
+
|
629
|
+
def contents
|
630
|
+
ensure_parsed
|
631
|
+
@contents
|
632
|
+
end
|
633
|
+
|
634
|
+
def contents=(contents)
|
635
|
+
@original_contents = contents
|
636
|
+
@parsed = false
|
637
|
+
end
|
638
|
+
|
639
|
+
def locale=(locale)
|
640
|
+
@locale = locale
|
641
|
+
@parsed = false
|
642
|
+
end
|
643
|
+
|
644
|
+
private
|
645
|
+
def ensure_parsed
|
646
|
+
return if @parsed
|
647
|
+
@parsed = true
|
648
|
+
@contents = parse_contents(@original_contents || File.read(@filename))
|
649
|
+
end
|
650
|
+
|
651
|
+
def parse_contents(data)
|
652
|
+
retried = false
|
653
|
+
cut_index = 0
|
654
|
+
data = translate(data)
|
655
|
+
data = data.split("\n")
|
656
|
+
data.each_with_index do |line, index|
|
657
|
+
case line
|
658
|
+
when /^#!(\S+)\s*$/
|
659
|
+
if index == 0
|
660
|
+
attributes[:markup] = $1
|
661
|
+
else
|
662
|
+
cut_index = index
|
663
|
+
break
|
664
|
+
end
|
665
|
+
when /^\s*#\s*@(\S+)\s*(.+?)\s*$/
|
666
|
+
attributes[$1] = $2
|
667
|
+
else
|
668
|
+
cut_index = index
|
669
|
+
break
|
670
|
+
end
|
671
|
+
end
|
672
|
+
data = data[cut_index..-1] if cut_index > 0
|
673
|
+
contents = data.join("\n")
|
674
|
+
|
675
|
+
if contents.respond_to?(:force_encoding) && attributes[:encoding]
|
676
|
+
begin
|
677
|
+
contents.force_encoding(attributes[:encoding])
|
678
|
+
rescue ArgumentError
|
679
|
+
log.warn "Invalid encoding `#{attributes[:encoding]}' in #{filename}"
|
680
|
+
end
|
681
|
+
end
|
682
|
+
contents
|
683
|
+
rescue ArgumentError => e
|
684
|
+
if retried && e.message =~ /invalid byte sequence/
|
685
|
+
# This should never happen.
|
686
|
+
log.warn "Could not read #{filename}, #{e.message}. You probably want to set `--charset`."
|
687
|
+
return ''
|
688
|
+
end
|
689
|
+
data.force_encoding('binary') if data.respond_to?(:force_encoding)
|
690
|
+
retried = true
|
691
|
+
retry
|
692
|
+
end
|
693
|
+
|
694
|
+
def translate(data)
|
695
|
+
text = YARD::I18n::Text.new(data, :have_header => true)
|
696
|
+
text.translate(YARD::Registry.locale(locale))
|
697
|
+
end
|
698
|
+
end
|
699
|
+
end
|
700
|
+
|
701
|
+
module I18n
|
702
|
+
# @private
|
703
|
+
class Locale
|
704
|
+
def load(locale_directory)
|
705
|
+
return false if @name.nil?
|
706
|
+
|
707
|
+
po_file = File.join(locale_directory, "#{@name}.po")
|
708
|
+
return false unless File.exist?(po_file)
|
709
|
+
|
710
|
+
begin
|
711
|
+
require "gettext/tools/poparser"
|
712
|
+
require "gettext/runtime/mofile"
|
713
|
+
rescue LoadError
|
714
|
+
log.warn "Need gettext gem for i18n feature:"
|
715
|
+
log.warn " gem install gettext"
|
716
|
+
return false
|
717
|
+
end
|
718
|
+
|
719
|
+
parser = GetText::PoParser.new
|
720
|
+
parser.report_warning = false
|
721
|
+
data = GetText::MoFile.new
|
722
|
+
parser.parse_file(po_file, data)
|
723
|
+
@messages.merge!(data)
|
724
|
+
true
|
725
|
+
end
|
726
|
+
end
|
727
|
+
end
|
728
|
+
|
729
|
+
# @private
|
730
|
+
module Registry
|
731
|
+
DEFAULT_PO_DIR = "po"
|
732
|
+
class << self
|
733
|
+
def locale(name)
|
734
|
+
thread_local_store.locale(name)
|
735
|
+
end
|
736
|
+
|
737
|
+
attr_accessor :po_dir
|
738
|
+
undef po_dir, po_dir=
|
739
|
+
def po_dir=(dir) Thread.current[:__yard_po_dir__] = dir end
|
740
|
+
def po_dir
|
741
|
+
Thread.current[:__yard_po_dir__] ||= DEFAULT_PO_DIR
|
742
|
+
end
|
743
|
+
end
|
744
|
+
end
|
745
|
+
|
746
|
+
# @private
|
747
|
+
class RegistryStore
|
748
|
+
def initialize
|
749
|
+
@file = nil
|
750
|
+
@checksums = {}
|
751
|
+
@store = {}
|
752
|
+
@proxy_types = {}
|
753
|
+
@object_types = {:root => [:root]}
|
754
|
+
@notfound = {}
|
755
|
+
@loaded_objects = 0
|
756
|
+
@available_objects = 0
|
757
|
+
@locales = {}
|
758
|
+
@store[:root] = CodeObjects::RootObject.allocate
|
759
|
+
@store[:root].send(:initialize, nil, :root)
|
760
|
+
end
|
761
|
+
|
762
|
+
def locale(name)
|
763
|
+
@locales[name] ||= load_locale(name)
|
764
|
+
end
|
765
|
+
|
766
|
+
def load_locale(name)
|
767
|
+
locale = I18n::Locale.new(name)
|
768
|
+
locale.load(Registry.po_dir)
|
769
|
+
locale
|
770
|
+
end
|
286
771
|
end
|
287
772
|
end
|