prepor-erlapi 0.1.8
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/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +15 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/bin/erlapi +26 -0
- data/erlapi.gemspec +138 -0
- data/lib/erlapi/generator/shtml.rb +353 -0
- data/lib/erlapi/generator/template/direct/_context.rhtml +172 -0
- data/lib/erlapi/generator/template/direct/class.rhtml +40 -0
- data/lib/erlapi/generator/template/direct/file.rhtml +30 -0
- data/lib/erlapi/generator/template/direct/index.rhtml +14 -0
- data/lib/erlapi/generator/template/direct/resources/apple-touch-icon.png +0 -0
- data/lib/erlapi/generator/template/direct/resources/css/main.css +263 -0
- data/lib/erlapi/generator/template/direct/resources/css/panel.css +383 -0
- data/lib/erlapi/generator/template/direct/resources/css/reset.css +53 -0
- data/lib/erlapi/generator/template/direct/resources/favicon.ico +0 -0
- data/lib/erlapi/generator/template/direct/resources/i/arrows.png +0 -0
- data/lib/erlapi/generator/template/direct/resources/i/results_bg.png +0 -0
- data/lib/erlapi/generator/template/direct/resources/i/tree_bg.png +0 -0
- data/lib/erlapi/generator/template/direct/resources/js/jquery-1.3.2.min.js +19 -0
- data/lib/erlapi/generator/template/direct/resources/js/jquery-effect.js +593 -0
- data/lib/erlapi/generator/template/direct/resources/js/main.js +22 -0
- data/lib/erlapi/generator/template/direct/resources/js/searchdoc.js +628 -0
- data/lib/erlapi/generator/template/direct/resources/panel/index.html +71 -0
- data/lib/erlapi/generator/template/merge/index.rhtml +14 -0
- data/lib/erlapi/generator/template/shtml/_context.rhtml +164 -0
- data/lib/erlapi/generator/template/shtml/class.rhtml +46 -0
- data/lib/erlapi/generator/template/shtml/file.rhtml +37 -0
- data/lib/erlapi/generator/template/shtml/index.rhtml +14 -0
- data/lib/erlapi/generator/template/shtml/resources/apple-touch-icon.png +0 -0
- data/lib/erlapi/generator/template/shtml/resources/css/main.css +191 -0
- data/lib/erlapi/generator/template/shtml/resources/css/panel.css +383 -0
- data/lib/erlapi/generator/template/shtml/resources/css/reset.css +53 -0
- data/lib/erlapi/generator/template/shtml/resources/favicon.ico +0 -0
- data/lib/erlapi/generator/template/shtml/resources/i/arrows.png +0 -0
- data/lib/erlapi/generator/template/shtml/resources/i/results_bg.png +0 -0
- data/lib/erlapi/generator/template/shtml/resources/i/tree_bg.png +0 -0
- data/lib/erlapi/generator/template/shtml/resources/js/jquery-1.3.2.min.js +19 -0
- data/lib/erlapi/generator/template/shtml/resources/js/main.js +34 -0
- data/lib/erlapi/generator/template/shtml/resources/js/searchdoc.js +628 -0
- data/lib/erlapi/generator/template/shtml/resources/panel/index.html +71 -0
- data/lib/erlapi/generator.rb +194 -0
- data/lib/erlapi/helpers.rb +26 -0
- data/lib/erlapi/merge.rb +217 -0
- data/lib/erlapi/parser.rb +134 -0
- data/lib/erlapi/shtml.rb +351 -0
- data/lib/erlapi/templatable.rb +51 -0
- data/lib/erlapi/templates/html/direct/_context.rhtml +172 -0
- data/lib/erlapi/templates/html/direct/class.rhtml +40 -0
- data/lib/erlapi/templates/html/direct/file.rhtml +30 -0
- data/lib/erlapi/templates/html/direct/index.rhtml +14 -0
- data/lib/erlapi/templates/html/direct/resources/apple-touch-icon.png +0 -0
- data/lib/erlapi/templates/html/direct/resources/css/main.css +263 -0
- data/lib/erlapi/templates/html/direct/resources/css/panel.css +383 -0
- data/lib/erlapi/templates/html/direct/resources/css/reset.css +53 -0
- data/lib/erlapi/templates/html/direct/resources/favicon.ico +0 -0
- data/lib/erlapi/templates/html/direct/resources/i/arrows.png +0 -0
- data/lib/erlapi/templates/html/direct/resources/i/results_bg.png +0 -0
- data/lib/erlapi/templates/html/direct/resources/i/tree_bg.png +0 -0
- data/lib/erlapi/templates/html/direct/resources/js/jquery-1.3.2.min.js +19 -0
- data/lib/erlapi/templates/html/direct/resources/js/jquery-effect.js +593 -0
- data/lib/erlapi/templates/html/direct/resources/js/main.js +22 -0
- data/lib/erlapi/templates/html/direct/resources/js/searchdoc.js +628 -0
- data/lib/erlapi/templates/html/direct/resources/panel/index.html +71 -0
- data/lib/erlapi/templates/html/merge/index.rhtml +14 -0
- data/lib/erlapi/templates/html/shtml/_context.rhtml +63 -0
- data/lib/erlapi/templates/html/shtml/class.rhtml +25 -0
- data/lib/erlapi/templates/html/shtml/file.rhtml +37 -0
- data/lib/erlapi/templates/html/shtml/index.rhtml +14 -0
- data/lib/erlapi/templates/html/shtml/resources/apple-touch-icon.png +0 -0
- data/lib/erlapi/templates/html/shtml/resources/css/main.css +263 -0
- data/lib/erlapi/templates/html/shtml/resources/css/panel.css +383 -0
- data/lib/erlapi/templates/html/shtml/resources/css/reset.css +53 -0
- data/lib/erlapi/templates/html/shtml/resources/favicon.ico +0 -0
- data/lib/erlapi/templates/html/shtml/resources/i/arrows.png +0 -0
- data/lib/erlapi/templates/html/shtml/resources/i/results_bg.png +0 -0
- data/lib/erlapi/templates/html/shtml/resources/i/tree_bg.png +0 -0
- data/lib/erlapi/templates/html/shtml/resources/js/jquery-1.3.2.min.js +19 -0
- data/lib/erlapi/templates/html/shtml/resources/js/jquery-effect.js +593 -0
- data/lib/erlapi/templates/html/shtml/resources/js/main.js +22 -0
- data/lib/erlapi/templates/html/shtml/resources/js/searchdoc.js +620 -0
- data/lib/erlapi/templates/html/shtml/resources/panel/index.html +71 -0
- data/lib/erlapi/templates/html/shtml/resources copy/apple-touch-icon.png +0 -0
- data/lib/erlapi/templates/html/shtml/resources copy/css/main.css +195 -0
- data/lib/erlapi/templates/html/shtml/resources copy/css/panel.css +383 -0
- data/lib/erlapi/templates/html/shtml/resources copy/css/reset.css +53 -0
- data/lib/erlapi/templates/html/shtml/resources copy/favicon.ico +0 -0
- data/lib/erlapi/templates/html/shtml/resources copy/i/arrows.png +0 -0
- data/lib/erlapi/templates/html/shtml/resources copy/i/results_bg.png +0 -0
- data/lib/erlapi/templates/html/shtml/resources copy/i/tree_bg.png +0 -0
- data/lib/erlapi/templates/html/shtml/resources copy/js/jquery-1.3.2.min.js +19 -0
- data/lib/erlapi/templates/html/shtml/resources copy/js/main.js +34 -0
- data/lib/erlapi/templates/html/shtml/resources copy/js/searchdoc.js +628 -0
- data/lib/erlapi/templates/html/shtml/resources copy/panel/index.html +71 -0
- data/lib/erlapi.rb +38 -0
- data/test/erlapi_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +154 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
class Erlapi::Generator
|
|
3
|
+
attr_accessor :data, :output_dir, :source_dir
|
|
4
|
+
|
|
5
|
+
GENERATOR_DIRS = [File.join('sdoc', 'generator'), File.join('rdoc', 'generator')]
|
|
6
|
+
|
|
7
|
+
# Used in js to reduce index sizes
|
|
8
|
+
TYPE_CLASS = 1
|
|
9
|
+
TYPE_METHOD = 2
|
|
10
|
+
TYPE_FILE = 3
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
TEMPLATE_DIR = Pathname.new(File.dirname(__FILE__)) + 'templates' + 'html' + 'shtml'
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
FILE_DIR = 'files'
|
|
17
|
+
CLASS_DIR = 'classes'
|
|
18
|
+
|
|
19
|
+
RESOURCES_DIR = 'resources'
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
include ERB::Util
|
|
23
|
+
include Erlapi::Templatable
|
|
24
|
+
include Erlapi::Helpers
|
|
25
|
+
|
|
26
|
+
def initialize(options = {})
|
|
27
|
+
self.output_dir = Pathname.new(options[:output_dir])
|
|
28
|
+
|
|
29
|
+
self.output_dir.mkdir if !self.output_dir.directory?
|
|
30
|
+
|
|
31
|
+
self.data = options[:data]
|
|
32
|
+
define_paths
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def define_paths
|
|
36
|
+
@tree_file = output_dir + 'panel' + 'tree.js'
|
|
37
|
+
@search_index_file = output_dir + 'panel' + 'search_index.js'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def generate(options = {})
|
|
41
|
+
@options = options
|
|
42
|
+
copy_resources
|
|
43
|
+
generate_search_index
|
|
44
|
+
generate_class_tree
|
|
45
|
+
generate_class_files
|
|
46
|
+
generate_index_file
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
### Copy all the resource files to output dir
|
|
50
|
+
def copy_resources
|
|
51
|
+
resources_path = File.join(TEMPLATE_DIR, RESOURCES_DIR) + '/.'
|
|
52
|
+
debug_msg "Copying #{resources_path}/** to #{output_dir}/**"
|
|
53
|
+
FileUtils.cp_r resources_path.to_s, output_dir.to_s, :preserve => true
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
### Generate a documentation file for each class
|
|
57
|
+
def generate_class_files
|
|
58
|
+
debug_msg "Generating class documentation in #{output_dir}"
|
|
59
|
+
templatefile = TEMPLATE_DIR + 'class.rhtml'
|
|
60
|
+
|
|
61
|
+
self.data.each do |mod_name, mod|
|
|
62
|
+
if mod_name
|
|
63
|
+
debug_msg " working on %s" % [ mod.title]
|
|
64
|
+
outfile = output_dir + (mod.title + '.html')
|
|
65
|
+
# rel_prefix = OUTPUT_DIR.relative_path_from( outfile.dirname )
|
|
66
|
+
|
|
67
|
+
debug_msg " rendering #{outfile}"
|
|
68
|
+
self.render_template( templatefile, binding(), outfile )
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
### Create index.html with frameset
|
|
74
|
+
def generate_index_file
|
|
75
|
+
debug_msg "Generating index file in #{output_dir}"
|
|
76
|
+
templatefile = TEMPLATE_DIR + 'index.rhtml'
|
|
77
|
+
outfile = output_dir + 'index.html'
|
|
78
|
+
index_path = self.data.to_a.first[1].title + '.html'
|
|
79
|
+
self.render_template( templatefile, binding(), outfile )
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
### Create class tree structure and write it as json
|
|
83
|
+
def generate_class_tree
|
|
84
|
+
debug_msg "Generating class tree"
|
|
85
|
+
tree = self.data.map { |mod_name, mod| [mod_name, mod_name + '.html', '', []] }.sort{ |a, b| a[0] <=> b[0] }
|
|
86
|
+
debug_msg " writing class tree to %s" % @tree_file
|
|
87
|
+
File.open(@tree_file, "w", 0644) do |f|
|
|
88
|
+
f.write('var tree = '); f.write(tree.to_json)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def generate_search_index
|
|
93
|
+
debug_msg "Generating search index"
|
|
94
|
+
|
|
95
|
+
index = {
|
|
96
|
+
:searchIndex => [],
|
|
97
|
+
:longSearchIndex => [],
|
|
98
|
+
:info => []
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
add_class_search_index(index)
|
|
102
|
+
add_method_search_index(index)
|
|
103
|
+
|
|
104
|
+
debug_msg " writing search index to %s" % @search_index_file
|
|
105
|
+
data = {
|
|
106
|
+
:index => index
|
|
107
|
+
}
|
|
108
|
+
File.open(@search_index_file, "w", 0644) do |f|
|
|
109
|
+
f.write('var search_data = '); f.write(data.to_json)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
### Add classes to search +index+ array
|
|
115
|
+
def add_class_search_index(index)
|
|
116
|
+
debug_msg " generating class search index"
|
|
117
|
+
|
|
118
|
+
self.data.each do |mod_name, mod|
|
|
119
|
+
index[:searchIndex].push( search_string(mod.title) )
|
|
120
|
+
index[:longSearchIndex].push( search_string(mod.title) )
|
|
121
|
+
index[:info].push([
|
|
122
|
+
mod.title,
|
|
123
|
+
'',
|
|
124
|
+
mod.title + '.html',
|
|
125
|
+
'',
|
|
126
|
+
snippet(mod.summary),
|
|
127
|
+
TYPE_CLASS
|
|
128
|
+
])
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
### Add methods to search +index+ array
|
|
133
|
+
def add_method_search_index(index)
|
|
134
|
+
debug_msg " generating method search index"
|
|
135
|
+
|
|
136
|
+
list = self.data.map { |mod_name, mod|
|
|
137
|
+
mod.funcs
|
|
138
|
+
}.flatten
|
|
139
|
+
|
|
140
|
+
list.each do |func|
|
|
141
|
+
func.short_names.each do |func_name|
|
|
142
|
+
index[:searchIndex].push( search_string(func.p_module.title + ':' + func_name) + '()' )
|
|
143
|
+
index[:longSearchIndex].push(search_string(func_name))
|
|
144
|
+
index[:info].push([
|
|
145
|
+
func_name,
|
|
146
|
+
func.p_module.title + ':' + func_name,
|
|
147
|
+
func.p_module.title + '.html#' + func.ref,
|
|
148
|
+
'',
|
|
149
|
+
snippet(func.summary),
|
|
150
|
+
TYPE_METHOD
|
|
151
|
+
])
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
### Build search index key
|
|
159
|
+
def search_string(string)
|
|
160
|
+
string ||= ''
|
|
161
|
+
string.downcase.gsub(/\s/,'')
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def snippet(str)
|
|
165
|
+
str ||= ''
|
|
166
|
+
if str =~ /^(?>\s*)[^\#]/
|
|
167
|
+
content = str
|
|
168
|
+
else
|
|
169
|
+
content = str.gsub(/^\s*(#+)\s*/, '')
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
content = content.sub(/^(.{100,}?)\s.*/m, "\\1").gsub(/\r?\n/m, ' ')
|
|
173
|
+
|
|
174
|
+
begin
|
|
175
|
+
content.to_json
|
|
176
|
+
rescue # might fail on non-unicode string
|
|
177
|
+
begin
|
|
178
|
+
content = Iconv.conv('latin1//ignore', "UTF8", content) # remove all non-unicode chars
|
|
179
|
+
content.to_json
|
|
180
|
+
rescue
|
|
181
|
+
content = '' # something hugely wrong happend
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
content
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
### Output progress information if debugging is enabled
|
|
188
|
+
def debug_msg( *msg )
|
|
189
|
+
return unless $DEBUG_DOC
|
|
190
|
+
$stderr.puts( *msg )
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Erlapi::Helpers
|
|
2
|
+
def each_letter_group(methods, &block)
|
|
3
|
+
group = {:name => '', :methods => []}
|
|
4
|
+
methods.sort{ |a, b| a.name <=> b.name }.each do |method|
|
|
5
|
+
gname = group_name method.name
|
|
6
|
+
if gname != group[:name]
|
|
7
|
+
yield group unless group[:methods].size == 0
|
|
8
|
+
group = {
|
|
9
|
+
:name => gname,
|
|
10
|
+
:methods => []
|
|
11
|
+
}
|
|
12
|
+
end
|
|
13
|
+
group[:methods].push(method)
|
|
14
|
+
end
|
|
15
|
+
yield group unless group[:methods].size == 0
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
protected
|
|
19
|
+
def group_name name
|
|
20
|
+
if match = name.match(/^([a-z])/i)
|
|
21
|
+
match[1].upcase
|
|
22
|
+
else
|
|
23
|
+
'#'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/erlapi/merge.rb
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
require 'optparse'
|
|
2
|
+
require 'pathname'
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'json'
|
|
5
|
+
|
|
6
|
+
require 'sdoc/templatable'
|
|
7
|
+
|
|
8
|
+
class SDoc::Merge
|
|
9
|
+
include SDoc::Templatable
|
|
10
|
+
|
|
11
|
+
FLAG_FILE = "created.rid"
|
|
12
|
+
|
|
13
|
+
def initialize()
|
|
14
|
+
@names = []
|
|
15
|
+
@urls = []
|
|
16
|
+
@op_dir = 'doc'
|
|
17
|
+
@title = ''
|
|
18
|
+
@directories = []
|
|
19
|
+
template_dir = RDoc::Generator::SHtml.template_dir('merge')
|
|
20
|
+
@template_dir = Pathname.new File.expand_path(template_dir)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def merge(options)
|
|
24
|
+
parse_options options
|
|
25
|
+
|
|
26
|
+
@outputdir = Pathname.new( @op_dir )
|
|
27
|
+
|
|
28
|
+
check_directories
|
|
29
|
+
setup_output_dir
|
|
30
|
+
setup_names
|
|
31
|
+
copy_files
|
|
32
|
+
copy_docs if @urls.empty?
|
|
33
|
+
merge_search_index
|
|
34
|
+
merge_tree
|
|
35
|
+
generate_index_file
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def parse_options(options)
|
|
39
|
+
opts = OptionParser.new do |opt|
|
|
40
|
+
opt.banner = "Usage: sdoc-merge [options] directories"
|
|
41
|
+
|
|
42
|
+
opt.on("-n", "--names [NAMES]", "Names of merged repositories. Comma separated") do |v|
|
|
43
|
+
@names = v.split(',').map{|name| name.strip }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
opt.on("-o", "--op [DIRECTORY]", "Set the output directory") do |v|
|
|
47
|
+
@op_dir = v
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
opt.on("-t", "--title [TITLE]", "Set the title of merged file") do |v|
|
|
51
|
+
@title = v
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
opt.on("-u", "--urls [URLS]", "Paths to merged docs. If you \n" +
|
|
55
|
+
"set this files and classes won't be actualy copied to merged build") do |v|
|
|
56
|
+
@urls = v.split(' ').map{|name| name.strip }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
opts.parse! options
|
|
60
|
+
@directories = options.dup
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def merge_tree
|
|
64
|
+
tree = []
|
|
65
|
+
@directories.each_with_index do |dir, i|
|
|
66
|
+
name = @names[i]
|
|
67
|
+
url = @urls.empty? ? name : @urls[i]
|
|
68
|
+
filename = File.join dir, RDoc::Generator::SHtml::TREE_FILE
|
|
69
|
+
data = open(filename).read.sub(/var tree =\s*/, '')
|
|
70
|
+
subtree = JSON.parse data, :max_nesting => 35
|
|
71
|
+
item = [
|
|
72
|
+
name,
|
|
73
|
+
url + '/' + extract_index_path(dir),
|
|
74
|
+
'',
|
|
75
|
+
append_path(subtree, url)
|
|
76
|
+
]
|
|
77
|
+
tree << item
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
dst = File.join @op_dir, RDoc::Generator::SHtml::TREE_FILE
|
|
81
|
+
FileUtils.mkdir_p File.dirname(dst)
|
|
82
|
+
File.open(dst, "w", 0644) do |f|
|
|
83
|
+
f.write('var tree = '); f.write(tree.to_json)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def append_path subtree, path
|
|
88
|
+
subtree.map do |item|
|
|
89
|
+
item[1] = path + '/' + item[1] unless item[1].empty?
|
|
90
|
+
item[3] = append_path item[3], path
|
|
91
|
+
item
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def merge_search_index
|
|
96
|
+
items = []
|
|
97
|
+
@indexes = {}
|
|
98
|
+
@directories.each_with_index do |dir, i|
|
|
99
|
+
name = @names[i]
|
|
100
|
+
url = @urls.empty? ? name : @urls[i]
|
|
101
|
+
filename = File.join dir, RDoc::Generator::SHtml::SEARCH_INDEX_FILE
|
|
102
|
+
data = open(filename).read.sub(/var search_data =\s*/, '')
|
|
103
|
+
subindex = JSON.parse data, :max_nesting => 35
|
|
104
|
+
@indexes[name] = subindex
|
|
105
|
+
|
|
106
|
+
searchIndex = subindex["index"]["searchIndex"]
|
|
107
|
+
longSearchIndex = subindex["index"]["longSearchIndex"]
|
|
108
|
+
subindex["index"]["info"].each_with_index do |info, j|
|
|
109
|
+
info[2] = url + '/' + info[2]
|
|
110
|
+
info[6] = i
|
|
111
|
+
items << {
|
|
112
|
+
:info => info,
|
|
113
|
+
:searchIndex => searchIndex[j],
|
|
114
|
+
:longSearchIndex => name + ' ' + longSearchIndex[j]
|
|
115
|
+
}
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
items.sort! do |a, b|
|
|
119
|
+
# type (class/method/file) or name or doc part or namespace
|
|
120
|
+
[a[:info][5], a[:info][0], a[:info][6], a[:info][1]] <=> [b[:info][5], b[:info][0], b[:info][6], b[:info][1]]
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
index = {
|
|
124
|
+
:searchIndex => items.map{|item| item[:searchIndex]},
|
|
125
|
+
:longSearchIndex => items.map{|item| item[:longSearchIndex]},
|
|
126
|
+
:info => items.map{|item| item[:info]}
|
|
127
|
+
}
|
|
128
|
+
search_data = {
|
|
129
|
+
:index => index,
|
|
130
|
+
:badges => @names
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
dst = File.join @op_dir, RDoc::Generator::SHtml::SEARCH_INDEX_FILE
|
|
134
|
+
FileUtils.mkdir_p File.dirname(dst)
|
|
135
|
+
File.open(dst, "w", 0644) do |f|
|
|
136
|
+
f.write('var search_data = '); f.write(search_data.to_json)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def extract_index_path dir
|
|
141
|
+
filename = File.join dir, 'index.html'
|
|
142
|
+
content = File.open(filename) { |f| f.read }
|
|
143
|
+
match = content.match(/<frame\s+src="([^"]+)"\s+name="docwin"/mi)
|
|
144
|
+
if match
|
|
145
|
+
match[1]
|
|
146
|
+
else
|
|
147
|
+
''
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def generate_index_file
|
|
152
|
+
templatefile = @template_dir + 'index.rhtml'
|
|
153
|
+
outfile = @outputdir + 'index.html'
|
|
154
|
+
url = @urls.empty? ? @names[0] : @urls[0]
|
|
155
|
+
index_path = url + '/' + extract_index_path(@directories[0])
|
|
156
|
+
|
|
157
|
+
render_template templatefile, binding(), outfile
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def setup_names
|
|
161
|
+
unless @names.size > 0
|
|
162
|
+
@directories.each do |dir|
|
|
163
|
+
name = File.basename dir
|
|
164
|
+
name = File.basename File.dirname(dir) if name == 'doc'
|
|
165
|
+
@names << name
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def copy_docs
|
|
171
|
+
@directories.each_with_index do |dir, i|
|
|
172
|
+
name = @names[i]
|
|
173
|
+
index_dir = File.dirname(RDoc::Generator::SHtml::TREE_FILE)
|
|
174
|
+
FileUtils.mkdir_p(File.join(@op_dir, name))
|
|
175
|
+
|
|
176
|
+
Dir.new(dir).each do |item|
|
|
177
|
+
if File.directory?(File.join(dir, item)) && item != '.' && item != '..' && item != index_dir
|
|
178
|
+
FileUtils.cp_r File.join(dir, item), File.join(@op_dir, name, item), :preserve => true
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def copy_files
|
|
185
|
+
dir = @directories.first
|
|
186
|
+
Dir.new(dir).each do |item|
|
|
187
|
+
if item != '.' && item != '..' && item != RDoc::Generator::SHtml::FILE_DIR && item != RDoc::Generator::SHtml::CLASS_DIR
|
|
188
|
+
FileUtils.cp_r File.join(dir, item), @op_dir, :preserve => true
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def setup_output_dir
|
|
194
|
+
if File.exists? @op_dir
|
|
195
|
+
error "#{@op_dir} allready exists"
|
|
196
|
+
end
|
|
197
|
+
FileUtils.mkdir_p @op_dir
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def check_directories
|
|
201
|
+
@directories.each do |dir|
|
|
202
|
+
unless File.exists?(File.join(dir, FLAG_FILE)) &&
|
|
203
|
+
File.exists?(File.join(dir, RDoc::Generator::SHtml::TREE_FILE)) &&
|
|
204
|
+
File.exists?(File.join(dir, RDoc::Generator::SHtml::SEARCH_INDEX_FILE))
|
|
205
|
+
error "#{dir} does not seem to be an sdoc directory"
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
##
|
|
211
|
+
# Report an error message and exit
|
|
212
|
+
|
|
213
|
+
def error(msg)
|
|
214
|
+
raise RDoc::Error, msg
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
require 'nokogiri'
|
|
2
|
+
|
|
3
|
+
module Erlapi::Parser
|
|
4
|
+
class Base
|
|
5
|
+
attr_accessor :src_dir, :template_dir, :files, :modules, :entities_coder
|
|
6
|
+
def initialize(src_dir = nil)
|
|
7
|
+
self.files = []
|
|
8
|
+
self.modules = {}
|
|
9
|
+
self.src_dir = Pathname.new(src_dir || File.join(File.dirname(__FILE__), '..', 'src'))
|
|
10
|
+
self.template_dir = File.join(File.dirname(__FILE__), 'templates')
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def parse
|
|
14
|
+
files.each do |file|
|
|
15
|
+
puts "Parsing #{file}"
|
|
16
|
+
doc = Nokogiri::XML(File.read(file))
|
|
17
|
+
|
|
18
|
+
mod = Erlapi::Parser::Module.new(self, doc)
|
|
19
|
+
self.modules[mod.title] = mod if mod.valid
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def inner_xml(node)
|
|
24
|
+
node.is_a?(Nokogiri::XML::NodeSet) ? node.collect{|j| j.children.to_xml}.join('') : node.children.to_xml
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def special_tags(str)
|
|
28
|
+
str.gsub!(/<c>(.*?)<\/c>/mi, '<tt>\1</tt>')
|
|
29
|
+
str.gsub!(/<code.*?>(.*?)<\/code>/mi, '<pre>\1</pre>')
|
|
30
|
+
str.gsub!(/<v.*?>(.*?)<\/v>/mi, '<b>\1</b><br/>')
|
|
31
|
+
str.gsub!(/<input.*?>(.*?)<\/input>/mi, '<tt>\1</tt><br/>')
|
|
32
|
+
str
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def prepare_string(str)
|
|
36
|
+
str.gsub(/\\\\/, '\\')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def files
|
|
40
|
+
load_files(src_dir.realpath)
|
|
41
|
+
@files
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def load_files(dir_path)
|
|
45
|
+
dir = Dir.new(dir_path)
|
|
46
|
+
dir.each do |file_name|
|
|
47
|
+
full_path = File.join(dir.path, file_name)
|
|
48
|
+
if file_name != '.' && file_name != '..'
|
|
49
|
+
if File.directory?(full_path)
|
|
50
|
+
load_files(full_path)
|
|
51
|
+
else
|
|
52
|
+
@files << full_path if File.extname(file_name) == '.xml'
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
dir.close
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class Module
|
|
62
|
+
attr_accessor :parser, :title, :summary, :desc, :datatypes, :funcs, :sections, :valid, :doc
|
|
63
|
+
def initialize(parser, doc)
|
|
64
|
+
self.doc = doc
|
|
65
|
+
self.parser = parser
|
|
66
|
+
self.title = doc.css('module').inner_html
|
|
67
|
+
self.summary = doc.css('modulesummary').inner_html || ''
|
|
68
|
+
if self.title && self.title != ''
|
|
69
|
+
self.valid = true
|
|
70
|
+
else
|
|
71
|
+
self.valid = false
|
|
72
|
+
end
|
|
73
|
+
if valid
|
|
74
|
+
define_desc
|
|
75
|
+
define_sections
|
|
76
|
+
define_funcs
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def define_desc
|
|
81
|
+
self.desc = self.parser.special_tags(self.parser.inner_xml(doc.css('description')))
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def define_sections
|
|
85
|
+
self.sections = []
|
|
86
|
+
doc.css('section').each do |node|
|
|
87
|
+
self.sections << Erlapi::Parser::Section.new(self, node)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def define_funcs
|
|
92
|
+
self.funcs = []
|
|
93
|
+
doc.css('funcs func').each do |node|
|
|
94
|
+
func = Erlapi::Parser::Func.new(self, node)
|
|
95
|
+
self.funcs << func if func.short_name
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
class Func
|
|
101
|
+
attr_accessor :p_module, :short_name, :names, :summary, :types, :desc, :ref, :short_names
|
|
102
|
+
|
|
103
|
+
def initialize(p_module, node)
|
|
104
|
+
self.p_module = p_module
|
|
105
|
+
self.names = node.css('name').map {|v| v.inner_html}
|
|
106
|
+
if self.names
|
|
107
|
+
self.short_names = self.names.map { |n| n.match(/([\w\d_-]*)\(/) ? $~[1] : nil }.compact.uniq
|
|
108
|
+
self.short_name = self.short_names.first if self.short_names
|
|
109
|
+
end
|
|
110
|
+
self.ref = self.names.first.gsub(/[^\w]/, '')
|
|
111
|
+
self.summary = parser.inner_xml(node.css('fsummary'))
|
|
112
|
+
self.types = parser.special_tags(parser.inner_xml(node.css('type')))
|
|
113
|
+
self.desc = parser.special_tags(parser.inner_xml(node.css('desc')))
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def parser
|
|
117
|
+
self.p_module.parser
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
class Section
|
|
122
|
+
attr_accessor :p_module, :name, :desc
|
|
123
|
+
|
|
124
|
+
def initialize(p_module, node)
|
|
125
|
+
self.p_module = p_module
|
|
126
|
+
self.name = node.css('title').inner_html
|
|
127
|
+
self.desc = parser.special_tags(parser.inner_xml(node))
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def parser
|
|
131
|
+
self.p_module.parser
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|