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.
Files changed (100) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +15 -0
  5. data/Rakefile +56 -0
  6. data/VERSION +1 -0
  7. data/bin/erlapi +26 -0
  8. data/erlapi.gemspec +138 -0
  9. data/lib/erlapi/generator/shtml.rb +353 -0
  10. data/lib/erlapi/generator/template/direct/_context.rhtml +172 -0
  11. data/lib/erlapi/generator/template/direct/class.rhtml +40 -0
  12. data/lib/erlapi/generator/template/direct/file.rhtml +30 -0
  13. data/lib/erlapi/generator/template/direct/index.rhtml +14 -0
  14. data/lib/erlapi/generator/template/direct/resources/apple-touch-icon.png +0 -0
  15. data/lib/erlapi/generator/template/direct/resources/css/main.css +263 -0
  16. data/lib/erlapi/generator/template/direct/resources/css/panel.css +383 -0
  17. data/lib/erlapi/generator/template/direct/resources/css/reset.css +53 -0
  18. data/lib/erlapi/generator/template/direct/resources/favicon.ico +0 -0
  19. data/lib/erlapi/generator/template/direct/resources/i/arrows.png +0 -0
  20. data/lib/erlapi/generator/template/direct/resources/i/results_bg.png +0 -0
  21. data/lib/erlapi/generator/template/direct/resources/i/tree_bg.png +0 -0
  22. data/lib/erlapi/generator/template/direct/resources/js/jquery-1.3.2.min.js +19 -0
  23. data/lib/erlapi/generator/template/direct/resources/js/jquery-effect.js +593 -0
  24. data/lib/erlapi/generator/template/direct/resources/js/main.js +22 -0
  25. data/lib/erlapi/generator/template/direct/resources/js/searchdoc.js +628 -0
  26. data/lib/erlapi/generator/template/direct/resources/panel/index.html +71 -0
  27. data/lib/erlapi/generator/template/merge/index.rhtml +14 -0
  28. data/lib/erlapi/generator/template/shtml/_context.rhtml +164 -0
  29. data/lib/erlapi/generator/template/shtml/class.rhtml +46 -0
  30. data/lib/erlapi/generator/template/shtml/file.rhtml +37 -0
  31. data/lib/erlapi/generator/template/shtml/index.rhtml +14 -0
  32. data/lib/erlapi/generator/template/shtml/resources/apple-touch-icon.png +0 -0
  33. data/lib/erlapi/generator/template/shtml/resources/css/main.css +191 -0
  34. data/lib/erlapi/generator/template/shtml/resources/css/panel.css +383 -0
  35. data/lib/erlapi/generator/template/shtml/resources/css/reset.css +53 -0
  36. data/lib/erlapi/generator/template/shtml/resources/favicon.ico +0 -0
  37. data/lib/erlapi/generator/template/shtml/resources/i/arrows.png +0 -0
  38. data/lib/erlapi/generator/template/shtml/resources/i/results_bg.png +0 -0
  39. data/lib/erlapi/generator/template/shtml/resources/i/tree_bg.png +0 -0
  40. data/lib/erlapi/generator/template/shtml/resources/js/jquery-1.3.2.min.js +19 -0
  41. data/lib/erlapi/generator/template/shtml/resources/js/main.js +34 -0
  42. data/lib/erlapi/generator/template/shtml/resources/js/searchdoc.js +628 -0
  43. data/lib/erlapi/generator/template/shtml/resources/panel/index.html +71 -0
  44. data/lib/erlapi/generator.rb +194 -0
  45. data/lib/erlapi/helpers.rb +26 -0
  46. data/lib/erlapi/merge.rb +217 -0
  47. data/lib/erlapi/parser.rb +134 -0
  48. data/lib/erlapi/shtml.rb +351 -0
  49. data/lib/erlapi/templatable.rb +51 -0
  50. data/lib/erlapi/templates/html/direct/_context.rhtml +172 -0
  51. data/lib/erlapi/templates/html/direct/class.rhtml +40 -0
  52. data/lib/erlapi/templates/html/direct/file.rhtml +30 -0
  53. data/lib/erlapi/templates/html/direct/index.rhtml +14 -0
  54. data/lib/erlapi/templates/html/direct/resources/apple-touch-icon.png +0 -0
  55. data/lib/erlapi/templates/html/direct/resources/css/main.css +263 -0
  56. data/lib/erlapi/templates/html/direct/resources/css/panel.css +383 -0
  57. data/lib/erlapi/templates/html/direct/resources/css/reset.css +53 -0
  58. data/lib/erlapi/templates/html/direct/resources/favicon.ico +0 -0
  59. data/lib/erlapi/templates/html/direct/resources/i/arrows.png +0 -0
  60. data/lib/erlapi/templates/html/direct/resources/i/results_bg.png +0 -0
  61. data/lib/erlapi/templates/html/direct/resources/i/tree_bg.png +0 -0
  62. data/lib/erlapi/templates/html/direct/resources/js/jquery-1.3.2.min.js +19 -0
  63. data/lib/erlapi/templates/html/direct/resources/js/jquery-effect.js +593 -0
  64. data/lib/erlapi/templates/html/direct/resources/js/main.js +22 -0
  65. data/lib/erlapi/templates/html/direct/resources/js/searchdoc.js +628 -0
  66. data/lib/erlapi/templates/html/direct/resources/panel/index.html +71 -0
  67. data/lib/erlapi/templates/html/merge/index.rhtml +14 -0
  68. data/lib/erlapi/templates/html/shtml/_context.rhtml +63 -0
  69. data/lib/erlapi/templates/html/shtml/class.rhtml +25 -0
  70. data/lib/erlapi/templates/html/shtml/file.rhtml +37 -0
  71. data/lib/erlapi/templates/html/shtml/index.rhtml +14 -0
  72. data/lib/erlapi/templates/html/shtml/resources/apple-touch-icon.png +0 -0
  73. data/lib/erlapi/templates/html/shtml/resources/css/main.css +263 -0
  74. data/lib/erlapi/templates/html/shtml/resources/css/panel.css +383 -0
  75. data/lib/erlapi/templates/html/shtml/resources/css/reset.css +53 -0
  76. data/lib/erlapi/templates/html/shtml/resources/favicon.ico +0 -0
  77. data/lib/erlapi/templates/html/shtml/resources/i/arrows.png +0 -0
  78. data/lib/erlapi/templates/html/shtml/resources/i/results_bg.png +0 -0
  79. data/lib/erlapi/templates/html/shtml/resources/i/tree_bg.png +0 -0
  80. data/lib/erlapi/templates/html/shtml/resources/js/jquery-1.3.2.min.js +19 -0
  81. data/lib/erlapi/templates/html/shtml/resources/js/jquery-effect.js +593 -0
  82. data/lib/erlapi/templates/html/shtml/resources/js/main.js +22 -0
  83. data/lib/erlapi/templates/html/shtml/resources/js/searchdoc.js +620 -0
  84. data/lib/erlapi/templates/html/shtml/resources/panel/index.html +71 -0
  85. data/lib/erlapi/templates/html/shtml/resources copy/apple-touch-icon.png +0 -0
  86. data/lib/erlapi/templates/html/shtml/resources copy/css/main.css +195 -0
  87. data/lib/erlapi/templates/html/shtml/resources copy/css/panel.css +383 -0
  88. data/lib/erlapi/templates/html/shtml/resources copy/css/reset.css +53 -0
  89. data/lib/erlapi/templates/html/shtml/resources copy/favicon.ico +0 -0
  90. data/lib/erlapi/templates/html/shtml/resources copy/i/arrows.png +0 -0
  91. data/lib/erlapi/templates/html/shtml/resources copy/i/results_bg.png +0 -0
  92. data/lib/erlapi/templates/html/shtml/resources copy/i/tree_bg.png +0 -0
  93. data/lib/erlapi/templates/html/shtml/resources copy/js/jquery-1.3.2.min.js +19 -0
  94. data/lib/erlapi/templates/html/shtml/resources copy/js/main.js +34 -0
  95. data/lib/erlapi/templates/html/shtml/resources copy/js/searchdoc.js +628 -0
  96. data/lib/erlapi/templates/html/shtml/resources copy/panel/index.html +71 -0
  97. data/lib/erlapi.rb +38 -0
  98. data/test/erlapi_test.rb +7 -0
  99. data/test/test_helper.rb +10 -0
  100. 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
@@ -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