docurium 0.4.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/main.yml +42 -0
- data/Gemfile +4 -4
- data/README.md +0 -15
- data/bin/cm +19 -2
- data/docurium.gemspec +7 -6
- data/lib/docurium/cli.rb +6 -1
- data/lib/docurium/debug.rb +41 -0
- data/lib/docurium/docparser.rb +96 -27
- data/lib/docurium/layout.rb +0 -3
- data/lib/docurium/version.rb +1 -1
- data/lib/docurium.rb +276 -92
- data/lib/libdetect.rb +1 -1
- data/site/css/style.css +17 -11
- data/site/index.html +133 -122
- data/site/js/backbone.js +1 -1
- data/site/js/docurium.js +178 -162
- data/site/js/underscore.js +5 -5
- data/test/docurium_test.rb +235 -0
- data/test/fixtures/git2/cherrypick.h +19 -0
- data/test/fixtures/git2/common.h +1 -0
- data/test/fixtures/git2/repository.h +39 -0
- data/test/fixtures/git2/types.h +2 -0
- data/test/gen_test.rb +2 -2
- data/test/parser_test.rb +18 -14
- metadata +38 -23
- data/.travis.yml +0 -13
- data/test/repo_test.rb +0 -136
data/lib/docurium.rb
CHANGED
@@ -4,12 +4,14 @@ require 'version_sorter'
|
|
4
4
|
require 'rocco'
|
5
5
|
require 'docurium/version'
|
6
6
|
require 'docurium/layout'
|
7
|
+
require 'docurium/debug'
|
7
8
|
require 'libdetect'
|
8
9
|
require 'docurium/docparser'
|
9
10
|
require 'pp'
|
10
11
|
require 'rugged'
|
11
12
|
require 'redcarpet'
|
12
13
|
require 'redcarpet/compat'
|
14
|
+
require 'parallel'
|
13
15
|
require 'thread'
|
14
16
|
|
15
17
|
# Markdown expects the old redcarpet compat API, so let's tell it what
|
@@ -17,13 +19,15 @@ require 'thread'
|
|
17
19
|
Rocco::Markdown = RedcarpetCompat
|
18
20
|
|
19
21
|
class Docurium
|
20
|
-
attr_accessor :branch, :output_dir, :data
|
22
|
+
attr_accessor :branch, :output_dir, :data, :head_data
|
21
23
|
|
22
|
-
def initialize(config_file, repo = nil)
|
24
|
+
def initialize(config_file, cli_options = {}, repo = nil)
|
23
25
|
raise "You need to specify a config file" if !config_file
|
24
26
|
raise "You need to specify a valid config file" if !valid_config(config_file)
|
25
27
|
@sigs = {}
|
26
|
-
@
|
28
|
+
@head_data = nil
|
29
|
+
@repo = repo || Rugged::Repository.discover(config_file)
|
30
|
+
@cli_options = cli_options
|
27
31
|
end
|
28
32
|
|
29
33
|
def init_data(version = 'HEAD')
|
@@ -115,8 +119,31 @@ class Docurium
|
|
115
119
|
def generate_doc_for(version)
|
116
120
|
index = Rugged::Index.new
|
117
121
|
read_subtree(index, version, option_version(version, 'input', ''))
|
122
|
+
|
118
123
|
data = parse_headers(index, version)
|
119
|
-
data
|
124
|
+
examples = format_examples!(data, version)
|
125
|
+
[data, examples]
|
126
|
+
end
|
127
|
+
|
128
|
+
def process_project(versions)
|
129
|
+
nversions = versions.count
|
130
|
+
Parallel.each_with_index(versions, finish: -> (version, index, result) do
|
131
|
+
data, examples = result
|
132
|
+
# There's still some work we need to do serially
|
133
|
+
tally_sigs!(version, data)
|
134
|
+
force_utf8(data)
|
135
|
+
|
136
|
+
puts "Adding documentation for #{version} [#{index}/#{nversions}]"
|
137
|
+
|
138
|
+
# Store it so we can show it at the end
|
139
|
+
@head_data = data if version == 'HEAD'
|
140
|
+
|
141
|
+
yield index, version, result if block_given?
|
142
|
+
|
143
|
+
end) do |version, index|
|
144
|
+
puts "Generating documentation for #{version} [#{index}/#{nversions}]"
|
145
|
+
generate_doc_for(version)
|
146
|
+
end
|
120
147
|
end
|
121
148
|
|
122
149
|
def generate_docs
|
@@ -125,68 +152,46 @@ class Docurium
|
|
125
152
|
@tf = File.expand_path(File.join(File.dirname(__FILE__), 'docurium', 'layout.mustache'))
|
126
153
|
versions = get_versions
|
127
154
|
versions << 'HEAD'
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
read, write = IO.pipe
|
135
|
-
pid = Process.fork do
|
136
|
-
read.close
|
137
|
-
|
138
|
-
data = generate_doc_for(version)
|
139
|
-
examples = format_examples!(data, version)
|
140
|
-
|
141
|
-
Marshal.dump([version, data, examples], write)
|
142
|
-
write.close
|
155
|
+
# If the user specified versions, validate them and overwrite
|
156
|
+
if !(vers = (@cli_options[:for] || [])).empty?
|
157
|
+
vers.each do |v|
|
158
|
+
next if versions.include?(v)
|
159
|
+
puts "Unknown version #{v}"
|
160
|
+
exit(false)
|
143
161
|
end
|
144
|
-
|
145
|
-
pipes[pid] = read
|
146
|
-
write.close
|
162
|
+
versions = vers
|
147
163
|
end
|
148
164
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
# This may seem odd, but we need to keep reading from the pipe or
|
153
|
-
# the buffer will fill and they'll block and never exit. Therefore
|
154
|
-
# we can't rely on Process.wait to tell us when the work is
|
155
|
-
# done. Instead read from all the pipes concurrently and send the
|
156
|
-
# ruby objects through the queue.
|
157
|
-
Thread.abort_on_exception = true
|
158
|
-
pipes.each do |pid, read|
|
159
|
-
Thread.new do
|
160
|
-
result = read.read
|
161
|
-
output << Marshal.load(result)
|
162
|
-
end
|
165
|
+
if (@repo.config['user.name'].nil? || @repo.config['user.email'].nil?)
|
166
|
+
puts "ERROR: 'user.name' or 'user.email' is not configured. Docurium will not be able to commit the documentation"
|
167
|
+
exit(false)
|
163
168
|
end
|
164
169
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
# There's still some work we need to do serially
|
169
|
-
tally_sigs!(version, data)
|
170
|
+
process_project(versions) do |i, version, result|
|
171
|
+
data, examples = result
|
170
172
|
sha = @repo.write(data.to_json, :blob)
|
171
173
|
|
172
|
-
print "Generating documentation [#{i}/#{
|
174
|
+
print "Generating documentation [#{i}/#{versions.count}]\r"
|
173
175
|
|
174
|
-
|
175
|
-
|
176
|
-
|
176
|
+
unless dry_run?
|
177
|
+
output_index.add(:path => "#{version}.json", :oid => sha, :mode => 0100644)
|
178
|
+
examples.each do |path, id|
|
179
|
+
output_index.add(:path => path, :oid => id, :mode => 0100644)
|
180
|
+
end
|
177
181
|
end
|
182
|
+
end
|
178
183
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
184
|
+
if head_data
|
185
|
+
puts ''
|
186
|
+
show_warnings(head_data)
|
187
|
+
end
|
183
188
|
|
184
|
-
|
185
|
-
puts ''
|
186
|
-
show_warnings(data)
|
187
|
-
end
|
189
|
+
return if dry_run?
|
188
190
|
|
189
|
-
|
191
|
+
# We tally the signatures in the order they finished, which is
|
192
|
+
# arbitrary due to the concurrency, so we need to sort them once
|
193
|
+
# they've finished.
|
194
|
+
sort_sigs!
|
190
195
|
|
191
196
|
project = {
|
192
197
|
:versions => versions.reverse,
|
@@ -220,34 +225,145 @@ class Docurium
|
|
220
225
|
puts "\tupdated #{br}"
|
221
226
|
end
|
222
227
|
|
223
|
-
def
|
224
|
-
|
228
|
+
def force_utf8(data)
|
229
|
+
# Walk the data to force strings encoding to UTF-8.
|
230
|
+
if data.instance_of? Hash
|
231
|
+
data.each do |key, value|
|
232
|
+
if [:comment, :comments, :description].include?(key)
|
233
|
+
data[key] = value.force_encoding('UTF-8') unless value.nil?
|
234
|
+
else
|
235
|
+
force_utf8(value)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
elsif data.respond_to?(:each)
|
239
|
+
data.each { |x| force_utf8(x) }
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
class Warning
|
244
|
+
class UnmatchedParameter < Warning
|
245
|
+
def initialize(function, opts = {})
|
246
|
+
super :unmatched_param, :function, function, opts
|
247
|
+
end
|
248
|
+
|
249
|
+
def _message; "unmatched param"; end
|
250
|
+
end
|
251
|
+
|
252
|
+
class SignatureChanged < Warning
|
253
|
+
def initialize(function, opts = {})
|
254
|
+
super :signature_changed, :function, function, opts
|
255
|
+
end
|
256
|
+
|
257
|
+
def _message; "signature changed"; end
|
258
|
+
end
|
259
|
+
|
260
|
+
class MissingDocumentation < Warning
|
261
|
+
def initialize(type, identifier, opts = {})
|
262
|
+
super :missing_documentation, type, identifier, opts
|
263
|
+
end
|
264
|
+
|
265
|
+
def _message
|
266
|
+
["%s %s is missing documentation", :type, :identifier]
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
WARNINGS = [
|
271
|
+
:unmatched_param,
|
272
|
+
:signature_changed,
|
273
|
+
:missing_documentation,
|
274
|
+
]
|
275
|
+
|
276
|
+
attr_reader :warning, :type, :identifier, :file, :line, :column
|
277
|
+
|
278
|
+
def initialize(warning, type, identifier, opts = {})
|
279
|
+
raise ArgumentError.new("invalid warning class") unless WARNINGS.include?(warning)
|
280
|
+
@warning = warning
|
281
|
+
@type = type
|
282
|
+
@identifier = identifier
|
283
|
+
if type = opts.delete(:type)
|
284
|
+
@file = type[:file]
|
285
|
+
if input_dir = opts.delete(:input_dir)
|
286
|
+
File.expand_path(File.join(input_dir, @file))
|
287
|
+
end
|
288
|
+
@file ||= "<missing>"
|
289
|
+
@line = type[:line] || 1
|
290
|
+
@column = type[:column] || 1
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
def message
|
295
|
+
msg = self._message
|
296
|
+
msg.kind_of?(Array) ? msg.shift % msg.map {|a| self.send(a).to_s } : msg
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def collect_warnings(data)
|
301
|
+
warnings = []
|
302
|
+
input_dir = File.join(@project_dir, option_version("HEAD", 'input'))
|
225
303
|
|
226
304
|
# check for unmatched paramaters
|
227
|
-
unmatched = []
|
228
305
|
data[:functions].each do |f, fdata|
|
229
|
-
|
230
|
-
end
|
231
|
-
if unmatched.size > 0
|
232
|
-
out ' - unmatched params in'
|
233
|
-
unmatched.sort.each { |p| out ("\t" + p) }
|
306
|
+
warnings << Warning::UnmatchedParameter.new(f, type: fdata, input_dir: input_dir) if fdata[:comments] =~ /@param/
|
234
307
|
end
|
235
308
|
|
236
309
|
# check for changed signatures
|
237
310
|
sigchanges = []
|
238
|
-
@sigs.each do |fun,
|
239
|
-
if
|
240
|
-
|
311
|
+
@sigs.each do |fun, sig_data|
|
312
|
+
warnings << Warning::SignatureChanged.new(fun) if sig_data[:changes]['HEAD']
|
313
|
+
end
|
314
|
+
|
315
|
+
# check for undocumented things
|
316
|
+
types = [:functions, :callbacks, :globals, :types]
|
317
|
+
types.each do |type_id|
|
318
|
+
under_type = type_id.tap {|t| break t.to_s[0..-2].to_sym }
|
319
|
+
data[type_id].each do |ident, type|
|
320
|
+
under_type = type[:type] if type_id == :types
|
321
|
+
|
322
|
+
warnings << Warning::MissingDocumentation.new(under_type, ident, type: type, input_dir: input_dir) if type[:description].empty?
|
323
|
+
|
324
|
+
case type[:type]
|
325
|
+
when :struct
|
326
|
+
if type[:fields]
|
327
|
+
type[:fields].each do |field|
|
328
|
+
warnings << Warning::MissingDocumentation.new(:field, "#{ident}.#{field[:name]}", type: type, input_dir: input_dir) if field[:comments].empty?
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
241
332
|
end
|
242
333
|
end
|
243
|
-
|
244
|
-
|
245
|
-
|
334
|
+
warnings
|
335
|
+
end
|
336
|
+
|
337
|
+
def check_warnings(options)
|
338
|
+
versions = []
|
339
|
+
versions << get_versions.pop
|
340
|
+
versions << 'HEAD'
|
341
|
+
|
342
|
+
process_project(versions)
|
343
|
+
|
344
|
+
collect_warnings(head_data).each do |warning|
|
345
|
+
puts "#{warning.file}:#{warning.line}:#{warning.column}: #{warning.message}"
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
def show_warnings(data)
|
350
|
+
out '* checking your api'
|
351
|
+
|
352
|
+
collect_warnings(data).group_by {|w| w.warning }.each do |klass, klass_warnings|
|
353
|
+
klass_warnings.group_by {|w| w.type }.each do |type, type_warnings|
|
354
|
+
out " - " + type_warnings[0].message
|
355
|
+
type_warnings.sort_by {|w| w.identifier }.each do |warning|
|
356
|
+
out "\t" + warning.identifier
|
357
|
+
end
|
358
|
+
end
|
246
359
|
end
|
247
360
|
end
|
248
361
|
|
249
362
|
def get_versions
|
250
|
-
|
363
|
+
releases = @repo.tags
|
364
|
+
.map { |tag| tag.name.gsub(%r(^refs/tags/), '') }
|
365
|
+
.delete_if { |tagname| tagname.match(%r(-rc\d*$)) }
|
366
|
+
VersionSorter.sort(releases)
|
251
367
|
end
|
252
368
|
|
253
369
|
def parse_headers(index, version)
|
@@ -258,10 +374,11 @@ class Docurium
|
|
258
374
|
end
|
259
375
|
|
260
376
|
data = init_data(version)
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
377
|
+
DocParser.with_files(files, :prefix => version) do |parser|
|
378
|
+
headers.each do |header|
|
379
|
+
records = parser.parse_file(header, debug: interesting?(:file, header))
|
380
|
+
update_globals!(data, records)
|
381
|
+
end
|
265
382
|
end
|
266
383
|
|
267
384
|
data[:groups] = group_functions!(data)
|
@@ -288,6 +405,14 @@ class Docurium
|
|
288
405
|
end
|
289
406
|
end
|
290
407
|
|
408
|
+
def sort_sigs!
|
409
|
+
@sigs.keys.each do |fn|
|
410
|
+
VersionSorter.sort!(@sigs[fn][:exists])
|
411
|
+
# Put HEAD at the back
|
412
|
+
@sigs[fn][:exists] << @sigs[fn][:exists].shift
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
291
416
|
def find_subtree(version, path)
|
292
417
|
tree = nil
|
293
418
|
if version == 'HEAD'
|
@@ -326,40 +451,57 @@ class Docurium
|
|
326
451
|
def group_functions!(data)
|
327
452
|
func = {}
|
328
453
|
data[:functions].each_pair do |key, value|
|
454
|
+
debug_set interesting?(:function, key)
|
455
|
+
debug "grouping #{key}: #{value}"
|
329
456
|
if @options['prefix']
|
330
457
|
k = key.gsub(@options['prefix'], '')
|
331
458
|
else
|
332
459
|
k = key
|
333
460
|
end
|
334
461
|
group, rest = k.split('_', 2)
|
335
|
-
|
336
|
-
if
|
337
|
-
group
|
462
|
+
debug "grouped: k: #{k}, group: #{group}, rest: #{rest}"
|
463
|
+
if group.empty?
|
464
|
+
puts "empty group for function #{key}"
|
465
|
+
next
|
338
466
|
end
|
467
|
+
debug "grouped: k: #{k}, group: #{group}, rest: #{rest}"
|
339
468
|
data[:functions][key][:group] = group
|
340
469
|
func[group] ||= []
|
341
470
|
func[group] << key
|
342
471
|
func[group].sort!
|
343
472
|
end
|
344
|
-
misc = []
|
345
473
|
func.to_a.sort
|
346
474
|
end
|
347
475
|
|
348
476
|
def find_type_usage!(data)
|
349
|
-
# go through all
|
477
|
+
# go through all functions, callbacks, and structs
|
478
|
+
# see which other types are used and returned
|
350
479
|
# store them in the types data
|
351
|
-
|
480
|
+
h = {}
|
481
|
+
h.merge!(data[:functions])
|
482
|
+
h.merge!(data[:callbacks])
|
483
|
+
|
484
|
+
structs = data[:types].find_all {|t, tdata| (tdata[:type] == :struct and tdata[:fields] and not tdata[:fields].empty?) }
|
485
|
+
structs = Hash[structs.map {|t, tdata| [t, tdata] }]
|
486
|
+
h.merge!(structs)
|
487
|
+
|
488
|
+
h.each do |use, use_data|
|
352
489
|
data[:types].each_with_index do |tdata, i|
|
353
490
|
type, typeData = tdata
|
354
|
-
|
355
|
-
|
356
|
-
|
491
|
+
|
492
|
+
data[:types][i][1][:used] ||= {:returns => [], :needs => [], :fields => []}
|
493
|
+
if use_data[:return] && use_data[:return][:type].index(/#{type}[ ;\)\*]?/)
|
494
|
+
data[:types][i][1][:used][:returns] << use
|
357
495
|
data[:types][i][1][:used][:returns].sort!
|
358
496
|
end
|
359
|
-
if
|
360
|
-
data[:types][i][1][:used][:needs] <<
|
497
|
+
if use_data[:argline] && use_data[:argline].index(/#{type}[ ;\)\*]?/)
|
498
|
+
data[:types][i][1][:used][:needs] << use
|
361
499
|
data[:types][i][1][:used][:needs].sort!
|
362
500
|
end
|
501
|
+
if use_data[:fields] and use_data[:fields].find {|f| f[:type] == type }
|
502
|
+
data[:types][i][1][:used][:fields] << use
|
503
|
+
data[:types][i][1][:used][:fields].sort!
|
504
|
+
end
|
363
505
|
end
|
364
506
|
end
|
365
507
|
end
|
@@ -376,9 +518,28 @@ class Docurium
|
|
376
518
|
|
377
519
|
file_map = {}
|
378
520
|
|
379
|
-
md = Redcarpet::Markdown.new
|
521
|
+
md = Redcarpet::Markdown.new(Redcarpet::Render::HTML.new({}), :no_intra_emphasis => true)
|
380
522
|
recs.each do |r|
|
381
523
|
|
524
|
+
types = %w(function file type).map(&:to_sym)
|
525
|
+
dbg = false
|
526
|
+
types.each do |t|
|
527
|
+
dbg ||= if r[:type] == t and interesting?(t, r[:name])
|
528
|
+
true
|
529
|
+
elsif t == :file and interesting?(:file, r[:file])
|
530
|
+
true
|
531
|
+
elsif [:struct, :enum].include?(r[:type]) and interesting?(:type, r[:name])
|
532
|
+
true
|
533
|
+
else
|
534
|
+
false
|
535
|
+
end
|
536
|
+
end
|
537
|
+
|
538
|
+
debug_set dbg
|
539
|
+
|
540
|
+
debug "processing record: #{r}"
|
541
|
+
debug
|
542
|
+
|
382
543
|
# initialize filemap for this file
|
383
544
|
file_map[r[:file]] ||= {
|
384
545
|
:file => r[:file], :functions => [], :meta => {}, :lines => 0
|
@@ -390,7 +551,7 @@ class Docurium
|
|
390
551
|
# process this type of record
|
391
552
|
case r[:type]
|
392
553
|
when :function, :callback
|
393
|
-
|
554
|
+
t = r[:type] == :function ? :functions : :callbacks
|
394
555
|
data[t][r[:name]] ||= {}
|
395
556
|
wanted[:functions].each do |k|
|
396
557
|
next unless r.has_key? k
|
@@ -458,13 +619,24 @@ class Docurium
|
|
458
619
|
|
459
620
|
when :struct, :fnptr
|
460
621
|
data[:types][r[:name]] ||= {}
|
622
|
+
known = data[:types][r[:name]]
|
461
623
|
r[:value] ||= r[:name]
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
624
|
+
# we don't want to override "opaque" structs with typedefs or
|
625
|
+
# "public" documentation
|
626
|
+
unless r[:tdef].nil? and known[:fields] and known[:comments] and known[:description]
|
627
|
+
wanted[:types].each do |k|
|
628
|
+
next unless r.has_key? k
|
629
|
+
if k == :comments
|
630
|
+
data[:types][r[:name]][k] = md.render r[k]
|
631
|
+
else
|
632
|
+
data[:types][r[:name]][k] = r[k]
|
633
|
+
end
|
634
|
+
end
|
635
|
+
else
|
636
|
+
# We're about to skip that type. Just make sure we preserve the
|
637
|
+
# :fields comment
|
638
|
+
if r[:fields] and known[:fields].empty?
|
639
|
+
data[:types][r[:name]][:fields] = r[:fields]
|
468
640
|
end
|
469
641
|
end
|
470
642
|
if r[:type] == :fnptr
|
@@ -475,6 +647,10 @@ class Docurium
|
|
475
647
|
# Anything else we want to record?
|
476
648
|
end
|
477
649
|
|
650
|
+
debug "processed record: #{r}"
|
651
|
+
debug
|
652
|
+
|
653
|
+
debug_restore
|
478
654
|
end
|
479
655
|
|
480
656
|
data[:files] << file_map.values[0]
|
@@ -505,4 +681,12 @@ class Docurium
|
|
505
681
|
def out(text)
|
506
682
|
puts text
|
507
683
|
end
|
684
|
+
|
685
|
+
def dry_run?
|
686
|
+
@cli_options[:dry_run]
|
687
|
+
end
|
688
|
+
|
689
|
+
def interesting?(type, what)
|
690
|
+
@cli_options['debug'] || (@cli_options["debug-#{type}"] || []).include?(what)
|
691
|
+
end
|
508
692
|
end
|
data/lib/libdetect.rb
CHANGED
data/site/css/style.css
CHANGED
@@ -95,12 +95,12 @@ input.search {
|
|
95
95
|
background: url(../images/search_icon.png) 5px 50% no-repeat white;
|
96
96
|
}
|
97
97
|
|
98
|
-
a small {
|
98
|
+
a small {
|
99
99
|
font-size: 0.8em;
|
100
100
|
color: #aaa;
|
101
101
|
}
|
102
102
|
|
103
|
-
h2 small {
|
103
|
+
h2 small {
|
104
104
|
font-size: 0.8em;
|
105
105
|
font-weight: normal;
|
106
106
|
color: #666;
|
@@ -117,18 +117,25 @@ table.methods tr td.methodName a {
|
|
117
117
|
font-weight: bold;
|
118
118
|
}
|
119
119
|
|
120
|
-
table.funcTable tr td
|
120
|
+
table.funcTable tr td,
|
121
|
+
table.structTable tr td {
|
121
122
|
padding: 5px 10px;
|
122
123
|
border-bottom: 1px solid #eee;
|
123
124
|
}
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
125
|
+
|
126
|
+
.enumTable .var,
|
127
|
+
.funcTable .var,
|
128
|
+
.structTable .var {
|
128
129
|
font-weight: bold;
|
129
130
|
color: #833;
|
130
131
|
}
|
131
132
|
|
133
|
+
.enumTable .type,
|
134
|
+
.funcTable .type,
|
135
|
+
.structTable .type {
|
136
|
+
text-align: right;
|
137
|
+
}
|
138
|
+
|
132
139
|
code.params {
|
133
140
|
white-space: pre-wrap; /* css-3 */
|
134
141
|
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
@@ -152,7 +159,9 @@ code.params {
|
|
152
159
|
|
153
160
|
.returns { margin-bottom: 15px; }
|
154
161
|
|
155
|
-
h1.funcTitle
|
162
|
+
h1.funcTitle,
|
163
|
+
h1.enumTitle,
|
164
|
+
h1.structTitle {
|
156
165
|
font-size: 1.6em;
|
157
166
|
}
|
158
167
|
h3.funcDesc {
|
@@ -255,6 +264,3 @@ p.functionList a.introd {
|
|
255
264
|
color: #933;
|
256
265
|
}
|
257
266
|
|
258
|
-
.type-comment {
|
259
|
-
padding-left: 3em;
|
260
|
-
}
|