jsduck 3.7.0 → 3.8.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.
- data/README.md +3 -1
- data/Rakefile +1 -1
- data/jsduck.gemspec +2 -2
- data/lib/jsduck/app.rb +2 -1
- data/lib/jsduck/app_data.rb +1 -1
- data/lib/jsduck/class.rb +13 -2
- data/lib/jsduck/doc_formatter.rb +30 -43
- data/lib/jsduck/doc_parser.rb +26 -5
- data/lib/jsduck/guides.rb +2 -1
- data/lib/jsduck/index_html.rb +2 -1
- data/lib/jsduck/inline_img.rb +53 -0
- data/lib/jsduck/inline_video.rb +58 -0
- data/lib/jsduck/io.rb +30 -0
- data/lib/jsduck/json_duck.rb +2 -1
- data/lib/jsduck/options.rb +6 -8
- data/lib/jsduck/search_data.rb +61 -25
- data/lib/jsduck/tag/aside.rb +0 -3
- data/lib/jsduck/type_parser.rb +305 -30
- data/lib/jsduck/welcome.rb +2 -1
- data/opt/comments-server-side/app.js +60 -45
- data/opt/comments-server-side/package.json +1 -1
- data/opt/comments-server-side/util.js +129 -54
- metadata +398 -404
data/README.md
CHANGED
@@ -120,7 +120,9 @@ Thanks to [Ondřej Jirman](https://github.com/megous),
|
|
120
120
|
[ligaard](https://github.com/ligaard),
|
121
121
|
[Bill Hubbard](http://www.sencha.com/forum/member.php?272458-BillHubbard),
|
122
122
|
[Ed Spencer](https://github.com/edspencer),
|
123
|
-
[atian25](https://github.com/atian25)
|
123
|
+
[atian25](https://github.com/atian25),
|
124
|
+
Katherine Chu,
|
125
|
+
[Rob Dougan](https://github.com/rdougan) and many-many others who
|
124
126
|
reported bugs, submitted patches, and provided a lot of useful input.
|
125
127
|
|
126
128
|
|
data/Rakefile
CHANGED
data/jsduck.gemspec
CHANGED
@@ -2,8 +2,8 @@ Gem::Specification.new do |s|
|
|
2
2
|
s.required_rubygems_version = ">= 1.3.5"
|
3
3
|
|
4
4
|
s.name = 'jsduck'
|
5
|
-
s.version = '3.
|
6
|
-
s.date = '2012-
|
5
|
+
s.version = '3.8.0'
|
6
|
+
s.date = '2012-03-15'
|
7
7
|
s.summary = "Simple JavaScript Duckumentation generator"
|
8
8
|
s.description = "Documentation generator for Sencha JS frameworks"
|
9
9
|
s.homepage = "https://github.com/senchalabs/jsduck"
|
data/lib/jsduck/app.rb
CHANGED
@@ -10,6 +10,7 @@ require 'jsduck/parallel_wrap'
|
|
10
10
|
require 'jsduck/logger'
|
11
11
|
require 'jsduck/assets'
|
12
12
|
require 'jsduck/json_duck'
|
13
|
+
require 'jsduck/io'
|
13
14
|
require 'jsduck/lint'
|
14
15
|
require 'jsduck/template_dir'
|
15
16
|
require 'jsduck/class_writer'
|
@@ -81,7 +82,7 @@ module JsDuck
|
|
81
82
|
def parallel_parse(filenames)
|
82
83
|
@parallel.map(filenames) do |fname|
|
83
84
|
Logger.instance.log("Parsing", fname)
|
84
|
-
SourceFile.new(IO.read(fname), fname, @opts)
|
85
|
+
SourceFile.new(JsDuck::IO.read(fname), fname, @opts)
|
85
86
|
end
|
86
87
|
end
|
87
88
|
|
data/lib/jsduck/app_data.rb
CHANGED
@@ -22,7 +22,7 @@ module JsDuck
|
|
22
22
|
:guides => @assets.guides.to_array,
|
23
23
|
:videos => @assets.videos.to_array,
|
24
24
|
:examples => @assets.examples.to_array,
|
25
|
-
:search => SearchData.new.create(@relations.classes),
|
25
|
+
:search => SearchData.new.create(@relations.classes, @assets),
|
26
26
|
:stats => @opts.stats ? Stats.new.create(@relations.classes) : [],
|
27
27
|
:signatures => MetaTagRegistry.instance.signatures,
|
28
28
|
:localStorageDb => @opts.local_storage_db,
|
data/lib/jsduck/class.rb
CHANGED
@@ -178,7 +178,7 @@ module JsDuck
|
|
178
178
|
end
|
179
179
|
|
180
180
|
# merges second members hash into first one
|
181
|
-
def merge!(hash1, hash2)
|
181
|
+
def merge!(hash1, hash2, skip_overrides=false)
|
182
182
|
hash2.each_pair do |name, m|
|
183
183
|
if m[:meta] && m[:meta][:hide]
|
184
184
|
if hash1[name]
|
@@ -210,7 +210,18 @@ module JsDuck
|
|
210
210
|
# this, ignore overriding itself.
|
211
211
|
if new[:owner] != old[:owner]
|
212
212
|
new[:overrides] = [] unless new[:overrides]
|
213
|
-
|
213
|
+
unless new[:overrides].any? {|m| m[:owner] == old[:owner] }
|
214
|
+
# Make a copy of the important properties for us. We can't
|
215
|
+
# just push the actual `old` member itself, because there
|
216
|
+
# can be circular overrides (notably with Ext.Base), which
|
217
|
+
# will result in infinite loop when we try to convert our
|
218
|
+
# class into JSON.
|
219
|
+
new[:overrides] << {
|
220
|
+
:name => old[:name],
|
221
|
+
:owner => old[:owner],
|
222
|
+
:id => old[:id],
|
223
|
+
}
|
224
|
+
end
|
214
225
|
end
|
215
226
|
end
|
216
227
|
|
data/lib/jsduck/doc_formatter.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
1
2
|
require 'rubygems'
|
2
3
|
require 'rdiscount'
|
3
4
|
require 'strscan'
|
4
5
|
require 'cgi'
|
5
6
|
require 'jsduck/logger'
|
7
|
+
require 'jsduck/inline_img'
|
8
|
+
require 'jsduck/inline_video'
|
6
9
|
|
7
10
|
module JsDuck
|
8
11
|
|
@@ -20,22 +23,6 @@ module JsDuck
|
|
20
23
|
# Default value: '<a href="%c%M">%a</a>'
|
21
24
|
attr_accessor :link_tpl
|
22
25
|
|
23
|
-
# Template HTML that replaces {@img URL alt text}
|
24
|
-
# Can contain placeholders:
|
25
|
-
#
|
26
|
-
# %u - URL from @img tag (e.g. "some/path.png")
|
27
|
-
# %a - alt text for image
|
28
|
-
#
|
29
|
-
# Default value: '<img src="%u" alt="%a"/>'
|
30
|
-
attr_accessor :img_tpl
|
31
|
-
|
32
|
-
# This will hold list of all image paths gathered from {@img} tags.
|
33
|
-
attr_accessor :images
|
34
|
-
|
35
|
-
# Base path to prefix images from {@img} tags.
|
36
|
-
# Defaults to no prefix.
|
37
|
-
attr_accessor :img_path
|
38
|
-
|
39
26
|
# Sets up instance to work in context of particular class, so
|
40
27
|
# that when {@link #blah} is encountered it knows that
|
41
28
|
# Context#blah is meant.
|
@@ -61,13 +48,26 @@ module JsDuck
|
|
61
48
|
@max_length = 120
|
62
49
|
@relations = relations
|
63
50
|
@images = []
|
51
|
+
|
52
|
+
@inline_img = InlineImg.new(opts)
|
53
|
+
@inline_video = InlineVideo.new(opts)
|
54
|
+
|
64
55
|
@link_tpl = opts[:link_tpl] || '<a href="%c%#%m">%a</a>'
|
65
|
-
@img_tpl = opts[:img_tpl] || '<img src="%u" alt="%a"/>'
|
66
56
|
@link_re = /\{@link\s+(\S*?)(?:\s+(.+?))?\}/m
|
67
|
-
|
57
|
+
|
68
58
|
@example_annotation_re = /<pre><code>\s*@example( +[^\n]*)?\s+/m
|
69
59
|
end
|
70
60
|
|
61
|
+
# Sets base path to prefix images from {@img} tags.
|
62
|
+
def img_path=(path)
|
63
|
+
@inline_img.base_path = path
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns list of all image paths gathered from {@img} tags.
|
67
|
+
def images
|
68
|
+
@inline_img.images
|
69
|
+
end
|
70
|
+
|
71
71
|
# Replaces {@link} and {@img} tags, auto-generates links for
|
72
72
|
# recognized classnames.
|
73
73
|
#
|
@@ -93,8 +93,10 @@ module JsDuck
|
|
93
93
|
while !s.eos? do
|
94
94
|
if s.check(@link_re)
|
95
95
|
out += replace_link_tag(s.scan(@link_re))
|
96
|
-
elsif
|
97
|
-
out +=
|
96
|
+
elsif substitute = @inline_img.replace(s)
|
97
|
+
out += substitute
|
98
|
+
elsif substitute = @inline_video.replace(s)
|
99
|
+
out += substitute
|
98
100
|
elsif s.check(/[{]/)
|
99
101
|
# There might still be "{" that doesn't begin {@link} or {@img} - ignore it
|
100
102
|
out += s.scan(/[{]/)
|
@@ -185,10 +187,6 @@ module JsDuck
|
|
185
187
|
end
|
186
188
|
end
|
187
189
|
|
188
|
-
def replace_img_tag(input)
|
189
|
-
input.sub(@img_re) { img($1, $2) }
|
190
|
-
end
|
191
|
-
|
192
190
|
# Looks input text for patterns like:
|
193
191
|
#
|
194
192
|
# My.ClassName
|
@@ -258,21 +256,6 @@ module JsDuck
|
|
258
256
|
Logger.instance.warn(:link_auto, msg, @doc_context[:filename], @doc_context[:linenr])
|
259
257
|
end
|
260
258
|
|
261
|
-
# applies the image template
|
262
|
-
def img(url, alt_text)
|
263
|
-
@images << url
|
264
|
-
@img_tpl.gsub(/(%\w)/) do
|
265
|
-
case $1
|
266
|
-
when '%u'
|
267
|
-
@img_path ? (@img_path + "/" + url) : url
|
268
|
-
when '%a'
|
269
|
-
CGI.escapeHTML(alt_text||"")
|
270
|
-
else
|
271
|
-
$1
|
272
|
-
end
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
259
|
# applies the link template
|
277
260
|
def link(cls, member, anchor_text, type=nil, static=false)
|
278
261
|
# Use the canonical class name for link (not some alternateClassName)
|
@@ -345,21 +328,25 @@ module JsDuck
|
|
345
328
|
#
|
346
329
|
def shorten(input)
|
347
330
|
sent = first_sentence(strip_tags(input))
|
348
|
-
|
349
|
-
|
331
|
+
# Use u-modifier to correctly count multi-byte characters
|
332
|
+
chars = sent.scan(/./mu)
|
333
|
+
if chars.length > @max_length
|
334
|
+
chars[0..(@max_length-4)].join + "..."
|
350
335
|
else
|
351
336
|
sent + " ..."
|
352
337
|
end
|
353
338
|
end
|
354
339
|
|
355
340
|
def first_sentence(str)
|
356
|
-
str.sub(/\A(
|
341
|
+
str.sub(/\A(.+?(\.|。))\s.*\Z/mu, "\\1")
|
357
342
|
end
|
358
343
|
|
359
344
|
# Returns true when input should get shortened.
|
360
345
|
def too_long?(input)
|
361
346
|
stripped = strip_tags(input)
|
362
|
-
|
347
|
+
# for sentence v/s full - compare byte length
|
348
|
+
# for full v/s max - compare char length
|
349
|
+
first_sentence(stripped).length < stripped.length || stripped.scan(/./mu).length > @max_length
|
363
350
|
end
|
364
351
|
|
365
352
|
def strip_tags(str)
|
data/lib/jsduck/doc_parser.rb
CHANGED
@@ -286,7 +286,9 @@ module JsDuck
|
|
286
286
|
add_tag(:type)
|
287
287
|
skip_horiz_white
|
288
288
|
if look(/\{/)
|
289
|
-
|
289
|
+
tdf = typedef
|
290
|
+
@current_tag[:type] = tdf[:type]
|
291
|
+
@current_tag[:optional] = true if tdf[:optional]
|
290
292
|
elsif look(/\S/)
|
291
293
|
@current_tag[:type] = @input.scan(/\S+/)
|
292
294
|
end
|
@@ -354,10 +356,13 @@ module JsDuck
|
|
354
356
|
end
|
355
357
|
|
356
358
|
# matches {type} if possible and sets it on @current_tag
|
359
|
+
# Also checks for {optionality=} in type definition.
|
357
360
|
def maybe_type
|
358
361
|
skip_horiz_white
|
359
362
|
if look(/\{/)
|
360
|
-
|
363
|
+
tdf = typedef
|
364
|
+
@current_tag[:type] = tdf[:type]
|
365
|
+
@current_tag[:optional] = true if tdf[:optional]
|
361
366
|
end
|
362
367
|
end
|
363
368
|
|
@@ -431,12 +436,28 @@ module JsDuck
|
|
431
436
|
end
|
432
437
|
end
|
433
438
|
|
434
|
-
# matches {
|
439
|
+
# matches {...=} and returns text inside brackets
|
435
440
|
def typedef
|
436
441
|
match(/\{/)
|
437
|
-
name = @input.scan(/[^}]
|
442
|
+
name = @input.scan(/[^{}]*/)
|
443
|
+
|
444
|
+
# Type definition can contain nested braces: {{foo:Number}}
|
445
|
+
# In such case we parse the definition so that the braces are balanced.
|
446
|
+
while @input.check(/[{]/)
|
447
|
+
name += "{" + typedef[:type] +"}"
|
448
|
+
name += @input.scan(/[^{}]*/)
|
449
|
+
end
|
450
|
+
|
451
|
+
if name =~ /=$/
|
452
|
+
name = name.chop
|
453
|
+
optional = true
|
454
|
+
else
|
455
|
+
optional = nil
|
456
|
+
end
|
457
|
+
|
438
458
|
match(/\}/)
|
439
|
-
|
459
|
+
|
460
|
+
return {:type => name, :optional => optional}
|
440
461
|
end
|
441
462
|
|
442
463
|
# matches <ident_chain> <ident_chain> ... until line end
|
data/lib/jsduck/guides.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'jsduck/logger'
|
2
2
|
require 'jsduck/json_duck'
|
3
|
+
require 'jsduck/io'
|
3
4
|
require 'jsduck/null_object'
|
4
5
|
require 'jsduck/logger'
|
5
6
|
require 'jsduck/grouped_asset'
|
@@ -51,7 +52,7 @@ module JsDuck
|
|
51
52
|
@formatter.doc_context = {:filename => guide_file, :linenr => 0}
|
52
53
|
name = File.basename(in_dir)
|
53
54
|
@formatter.img_path = "guides/#{name}"
|
54
|
-
html = add_toc(guide, @formatter.format(IO.read(guide_file)))
|
55
|
+
html = add_toc(guide, @formatter.format(JsDuck::IO.read(guide_file)))
|
55
56
|
|
56
57
|
JsonDuck.write_jsonp(out_dir+"/README.js", name, {:guide => html, :title => guide["title"]})
|
57
58
|
end
|
data/lib/jsduck/index_html.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'jsduck/logger'
|
2
|
+
require 'jsduck/io'
|
2
3
|
require 'fileutils'
|
3
4
|
|
4
5
|
module JsDuck
|
@@ -49,7 +50,7 @@ module JsDuck
|
|
49
50
|
# Opens in_file, replaces {keys} inside it, writes to out_file
|
50
51
|
def write_template(in_file, out_file, replacements)
|
51
52
|
Logger.instance.log("Writing", out_file)
|
52
|
-
html = IO.read(in_file)
|
53
|
+
html = JsDuck::IO.read(in_file)
|
53
54
|
html.gsub!(/\{\w+\}/) do |key|
|
54
55
|
replacements[key] ? replacements[key] : key
|
55
56
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'jsduck/logger'
|
3
|
+
|
4
|
+
module JsDuck
|
5
|
+
|
6
|
+
# Implementation of inline tag {@img}
|
7
|
+
class InlineImg
|
8
|
+
# Base path to prefix images from {@img} tags.
|
9
|
+
# Defaults to no prefix.
|
10
|
+
attr_accessor :base_path
|
11
|
+
|
12
|
+
# This will hold list of all image paths gathered from {@img} tags.
|
13
|
+
attr_accessor :images
|
14
|
+
|
15
|
+
def initialize(opts={})
|
16
|
+
@tpl = opts[:img_tpl] || '<img src="%u" alt="%a"/>'
|
17
|
+
|
18
|
+
@re = /\{@img\s+(\S*?)(?:\s+(.+?))?\}/m
|
19
|
+
|
20
|
+
@base_path = nil
|
21
|
+
@images = []
|
22
|
+
end
|
23
|
+
|
24
|
+
# Takes StringScanner instance.
|
25
|
+
#
|
26
|
+
# Looks for inline tag at the current scan pointer position, when
|
27
|
+
# found, moves scan pointer forward and performs the apporpriate
|
28
|
+
# replacement.
|
29
|
+
def replace(input)
|
30
|
+
if input.check(@re)
|
31
|
+
input.scan(@re).sub(@re) { apply_tpl($1, $2) }
|
32
|
+
else
|
33
|
+
false
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# applies the image template
|
38
|
+
def apply_tpl(url, alt_text)
|
39
|
+
@images << url
|
40
|
+
@tpl.gsub(/(%\w)/) do
|
41
|
+
case $1
|
42
|
+
when '%u'
|
43
|
+
@base_path ? (@base_path + "/" + url) : url
|
44
|
+
when '%a'
|
45
|
+
CGI.escapeHTML(alt_text||"")
|
46
|
+
else
|
47
|
+
$1
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'jsduck/logger'
|
3
|
+
|
4
|
+
module JsDuck
|
5
|
+
|
6
|
+
# Implementation of inline tag {@video}
|
7
|
+
class InlineVideo
|
8
|
+
def initialize(opts={})
|
9
|
+
@templates = {
|
10
|
+
"html5" => '<video src="%u">%a</video>',
|
11
|
+
"vimeo" => [
|
12
|
+
'<p><object width="640" height="360">',
|
13
|
+
'<param name="allowfullscreen" value="true" />',
|
14
|
+
'<param name="allowscriptaccess" value="always" />',
|
15
|
+
'<param name="flashvars" value="api=1" />',
|
16
|
+
'<param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=%u&server=vimeo.com&color=4CC208&fullscreen=1" />',
|
17
|
+
'<embed src="http://vimeo.com/moogaloop.swf?clip_id=%u&server=vimeo.com&color=4CC208&fullscreen=1" ',
|
18
|
+
'type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="640" height="360"></embed>',
|
19
|
+
'</object></p>',
|
20
|
+
].join
|
21
|
+
}
|
22
|
+
|
23
|
+
@re = /\{@video\s+(\w+)\s+(\S*?)(?:\s+(.+?))?\}/m
|
24
|
+
end
|
25
|
+
|
26
|
+
# Takes StringScanner instance.
|
27
|
+
#
|
28
|
+
# Looks for inline tag at the current scan pointer position, when
|
29
|
+
# found, moves scan pointer forward and performs the apporpriate
|
30
|
+
# replacement.
|
31
|
+
def replace(input)
|
32
|
+
if input.check(@re)
|
33
|
+
input.scan(@re).sub(@re) { apply_tpl($1, $2, $3) }
|
34
|
+
else
|
35
|
+
false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# applies the video template of the specified type
|
40
|
+
def apply_tpl(type, url, alt_text)
|
41
|
+
unless @templates.has_key?(type)
|
42
|
+
Logger.instance.warn(nil, "Unknown video type #{type}")
|
43
|
+
end
|
44
|
+
|
45
|
+
@templates[type].gsub(/(%\w)/) do
|
46
|
+
case $1
|
47
|
+
when '%u'
|
48
|
+
url
|
49
|
+
when '%a'
|
50
|
+
CGI.escapeHTML(alt_text||"")
|
51
|
+
else
|
52
|
+
$1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/lib/jsduck/io.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module JsDuck
|
2
|
+
|
3
|
+
# A helper to use instead the builtin IO class to read files in
|
4
|
+
# correct encoding.
|
5
|
+
#
|
6
|
+
# By default in Ruby 1.9 the encoding is auto-detected, which can
|
7
|
+
# have surprising results. So in here we read in all files in UTF-8
|
8
|
+
# (the default) or in some other encoding specified through --encoding
|
9
|
+
# option and convert it to UTF-8 internally.
|
10
|
+
class IO
|
11
|
+
@@encoding = "UTF-8"
|
12
|
+
|
13
|
+
# Sets the external encoding to be used for reading files.
|
14
|
+
# When it's different from UTF-8, the input will be converted to UTF-8.
|
15
|
+
def self.encoding=(e)
|
16
|
+
if e =~ /^UTF-8$/i
|
17
|
+
@@encoding = e
|
18
|
+
else
|
19
|
+
@@encoding = e+":UTF-8"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Reads given filename into string
|
24
|
+
def self.read(filename)
|
25
|
+
File.open(filename, "r:"+@@encoding) {|f| f.read }
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|