docrb-html 0.2.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.
- checksums.yaml +7 -0
- data/.editorconfig +21 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +52 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +37 -0
- data/assets/breadcrumb.scss +25 -0
- data/assets/checkbox.scss +34 -0
- data/assets/class_header.scss +75 -0
- data/assets/class_mod_name.scss +8 -0
- data/assets/component_list.scss +4 -0
- data/assets/container.scss +9 -0
- data/assets/doc_box.scss +79 -0
- data/assets/documentation_block.scss +5 -0
- data/assets/favicon.ico +0 -0
- data/assets/fonts.scss +105 -0
- data/assets/footer.scss +15 -0
- data/assets/images/balance.svg +9 -0
- data/assets/images/breadcrumb_separator.svg +1 -0
- data/assets/images/checkbox-off.svg +1 -0
- data/assets/images/checkbox-on.svg +1 -0
- data/assets/images/chevron.svg +1 -0
- data/assets/images/docrb-label.svg +20 -0
- data/assets/images/github.svg +11 -0
- data/assets/images/home.svg +1 -0
- data/assets/images/inherited.svg +1 -0
- data/assets/images/override.svg +1 -0
- data/assets/images/questionmark.svg +1 -0
- data/assets/images/rubygems.svg +9 -0
- data/assets/images/user.svg +12 -0
- data/assets/js/filtering.js +66 -0
- data/assets/links.scss +16 -0
- data/assets/markdown.scss +41 -0
- data/assets/method_argument.scss +75 -0
- data/assets/method_display.scss +27 -0
- data/assets/method_list.scss +51 -0
- data/assets/project_header.scss +55 -0
- data/assets/reference.scss +36 -0
- data/assets/shared.scss +23 -0
- data/assets/style.scss +43 -0
- data/assets/symbol.scss +5 -0
- data/assets/tab_bar.scss +22 -0
- data/assets/text_block.scss +23 -0
- data/assets/type_definition.scss +3 -0
- data/assets/typedef.scss +6 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/exe/docrb-html +12 -0
- data/lib/renderer/component/breadcrumb.rb +14 -0
- data/lib/renderer/component/checkbox.rb +9 -0
- data/lib/renderer/component/class_header.rb +14 -0
- data/lib/renderer/component/class_mod_name.rb +9 -0
- data/lib/renderer/component/component_list.rb +15 -0
- data/lib/renderer/component/doc_box.rb +38 -0
- data/lib/renderer/component/documentation_block.rb +9 -0
- data/lib/renderer/component/footer.rb +9 -0
- data/lib/renderer/component/markdown.rb +9 -0
- data/lib/renderer/component/method_argument.rb +106 -0
- data/lib/renderer/component/method_display.rb +9 -0
- data/lib/renderer/component/method_list.rb +9 -0
- data/lib/renderer/component/project_header.rb +9 -0
- data/lib/renderer/component/reference.rb +24 -0
- data/lib/renderer/component/symbol.rb +9 -0
- data/lib/renderer/component/tab_bar.rb +9 -0
- data/lib/renderer/component/text_block.rb +15 -0
- data/lib/renderer/component/type_definition.rb +9 -0
- data/lib/renderer/component/typedef.rb +9 -0
- data/lib/renderer/component.rb +50 -0
- data/lib/renderer/core_extensions.rb +11 -0
- data/lib/renderer/defs/specialized_object.rb +172 -0
- data/lib/renderer/defs/specialized_projection.rb +31 -0
- data/lib/renderer/defs.rb +180 -0
- data/lib/renderer/helpers.rb +82 -0
- data/lib/renderer/metadata.rb +44 -0
- data/lib/renderer/page.rb +17 -0
- data/lib/renderer/template.rb +38 -0
- data/lib/renderer/version.rb +5 -0
- data/lib/renderer.rb +129 -0
- data/renderer.gemspec +31 -0
- data/script/makecomponent +23 -0
- data/script/reload.js +14 -0
- data/script/serve +2 -0
- data/script/watch +17 -0
- data/templates/base.erb +25 -0
- data/templates/breadcrumb.erb +28 -0
- data/templates/checkbox.erb +8 -0
- data/templates/class_header.erb +53 -0
- data/templates/class_mod_name.erb +3 -0
- data/templates/component_list.erb +21 -0
- data/templates/doc_box.erb +82 -0
- data/templates/documentation_block.erb +18 -0
- data/templates/footer.erb +9 -0
- data/templates/markdown.erb +3 -0
- data/templates/method_argument.erb +29 -0
- data/templates/method_display.erb +28 -0
- data/templates/method_list.erb +25 -0
- data/templates/project_header.erb +38 -0
- data/templates/reference.erb +14 -0
- data/templates/symbol.erb +3 -0
- data/templates/tab_bar.erb +7 -0
- data/templates/text_block.erb +16 -0
- data/templates/type_definition.erb +4 -0
- data/templates/typedef.erb +3 -0
- metadata +178 -0
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Renderer
|
4
|
+
class Component
|
5
|
+
class MethodArgument < Component
|
6
|
+
prop :type, :name, :value, :value_type, :computed
|
7
|
+
|
8
|
+
def prepare
|
9
|
+
@computed = {
|
10
|
+
rest: rest_arg,
|
11
|
+
name:,
|
12
|
+
continuation: continuation_for_type,
|
13
|
+
value: value_for_argument
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def continuation_for_type
|
18
|
+
if type == "kwarg" || type == "kwoptarg"
|
19
|
+
:colon
|
20
|
+
elsif type&.index("opt")&.zero?
|
21
|
+
:equal
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
REST_ARG_BY_TYPE = {
|
26
|
+
"kwrestarg" => :double,
|
27
|
+
"restarg" => :single,
|
28
|
+
"blockarg" => :block
|
29
|
+
}.freeze
|
30
|
+
|
31
|
+
def rest_arg
|
32
|
+
REST_ARG_BY_TYPE[type]
|
33
|
+
end
|
34
|
+
|
35
|
+
def value_for_argument
|
36
|
+
return if value_type.nil?
|
37
|
+
|
38
|
+
case value_type
|
39
|
+
when "sym"
|
40
|
+
{ kind: :symbol, value: }
|
41
|
+
when "bool"
|
42
|
+
{ kind: :symbol, value: value.inspect }
|
43
|
+
when "nil"
|
44
|
+
{ kind: :symbol, value: "nil" }
|
45
|
+
when "int"
|
46
|
+
{ kind: :number, value: }
|
47
|
+
when "str"
|
48
|
+
{ kind: :string, value: }
|
49
|
+
when "send"
|
50
|
+
method_call_argument(value)
|
51
|
+
when "const"
|
52
|
+
const_value(value)
|
53
|
+
else
|
54
|
+
{ kind: :plain, value: }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def method_call_argument(value)
|
59
|
+
class_path = value[:target].map do |i|
|
60
|
+
next { kind: :symbol, value: "self" } if i == "self"
|
61
|
+
|
62
|
+
# TODO: Is this plain?
|
63
|
+
[{ kind: :class_or_module, value: i }, { kind: :plain, value: "::" }]
|
64
|
+
end.flatten
|
65
|
+
|
66
|
+
class_path.pop
|
67
|
+
|
68
|
+
{
|
69
|
+
kind: :method_call_argument,
|
70
|
+
value: [
|
71
|
+
class_path,
|
72
|
+
{ kind: :plain, value: "." },
|
73
|
+
{ kind: :plain, value: value[:name] }
|
74
|
+
].flatten
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
def const_value(value)
|
79
|
+
class_path = value[:target].map do |i|
|
80
|
+
# TODO: Is this plain?
|
81
|
+
[{ kind: :class_or_module, value: i }, { kind: :continuation, double: true }]
|
82
|
+
end.flatten
|
83
|
+
|
84
|
+
class_path.pop
|
85
|
+
|
86
|
+
if class_path.empty?
|
87
|
+
return {
|
88
|
+
kind: :const,
|
89
|
+
value: [
|
90
|
+
{ kind: :class_or_module, value: value[:name] }
|
91
|
+
].flatten
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
{
|
96
|
+
kind: :const,
|
97
|
+
value: [
|
98
|
+
class_path,
|
99
|
+
{ kind: :continuation, double: true },
|
100
|
+
{ kind: :class_or_module, value: value[:name] }
|
101
|
+
].flatten
|
102
|
+
}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Renderer
|
4
|
+
class Component
|
5
|
+
class Reference < Component
|
6
|
+
prop :ref, :unresolved, :path
|
7
|
+
|
8
|
+
def prepare
|
9
|
+
@unresolved = !ref[:ref_path]
|
10
|
+
return if @unresolved
|
11
|
+
|
12
|
+
components = ref[:ref_path].dup
|
13
|
+
@path = if ref[:ref_type] == "method"
|
14
|
+
method_name = components.pop
|
15
|
+
parent_name = components.pop
|
16
|
+
components + ["#{parent_name}.html#{method_name}"]
|
17
|
+
else
|
18
|
+
last = components.pop
|
19
|
+
(components + ["#{last}.html"]).compact
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Renderer
|
4
|
+
class Component
|
5
|
+
class TextBlock < Component
|
6
|
+
prop :list
|
7
|
+
|
8
|
+
def prepare
|
9
|
+
return unless !@list.nil? && !@list.is_a?(Array)
|
10
|
+
|
11
|
+
@list = [{ type: "html", contents: @list }]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Renderer
|
4
|
+
class Component
|
5
|
+
attr_accessor :id
|
6
|
+
|
7
|
+
def self.prop(*names)
|
8
|
+
attr_accessor(*names)
|
9
|
+
|
10
|
+
@props ||= []
|
11
|
+
@props.append(*names)
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr_writer :template
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.template
|
19
|
+
return @template_instance if @template_instance
|
20
|
+
|
21
|
+
t_name = @template || name.split("::").last.snakify
|
22
|
+
@template_instance = Template.new("templates/#{t_name}.erb")
|
23
|
+
end
|
24
|
+
|
25
|
+
def props = @props ||= self.class.instance_variable_get(:@props) || []
|
26
|
+
def template = self.class.template
|
27
|
+
|
28
|
+
def initialize(**kwargs)
|
29
|
+
@id = kwargs.delete(:id)
|
30
|
+
kwargs.each do |k, v|
|
31
|
+
raise ArgumentError, "Unknown property #{k} for #{self.class.name}" unless props.include? k
|
32
|
+
|
33
|
+
send("#{k}=", v)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def prepare; end
|
38
|
+
|
39
|
+
def render(&)
|
40
|
+
prepare
|
41
|
+
opts = props.map { [_1, send(_1)] }.to_h
|
42
|
+
opts[:id] = @id
|
43
|
+
template.render(HELPERS, **opts, &)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
Dir[Pathname.new(__dir__).join("component/*.rb")].each do |file|
|
49
|
+
require_relative "component/#{Pathname.new(file).basename}"
|
50
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Renderer
|
4
|
+
class Defs
|
5
|
+
class SpecializedObject
|
6
|
+
def initialize(obj, parent, provider)
|
7
|
+
@obj = obj
|
8
|
+
@provider = provider
|
9
|
+
prepare(parent)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.specialize(obj, parent, provider)
|
13
|
+
return nil if obj.nil?
|
14
|
+
|
15
|
+
new(obj, parent, provider)
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](key) = @obj[key]
|
19
|
+
def fetch(*, **, &) = @obj.fetch(*, **, &)
|
20
|
+
|
21
|
+
def resolve(name)
|
22
|
+
named = named_as(name)
|
23
|
+
modules.find(&named) \
|
24
|
+
|| classes.find(&named) \
|
25
|
+
|| attributes&.find(&named) \
|
26
|
+
|| defs.find(&named) \
|
27
|
+
|| sdefs.find(&named)
|
28
|
+
end
|
29
|
+
|
30
|
+
def resolve_inheritance(name)
|
31
|
+
named = named_as(name)
|
32
|
+
modules.find(&named) \
|
33
|
+
|| classes.find(&named) \
|
34
|
+
|| parent&.resolve_inheritance(name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def resolve_parent(name)
|
38
|
+
parent = self[:parent]
|
39
|
+
return { type: "Unknown Ref", name: } unless parent
|
40
|
+
|
41
|
+
parent.resolve(name) || parent.resolve_parent(name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def resolve_path(path)
|
45
|
+
p = path.dup
|
46
|
+
obj = self
|
47
|
+
until p.empty?
|
48
|
+
obj = obj.resolve(p[0])
|
49
|
+
return unless obj
|
50
|
+
|
51
|
+
p.shift
|
52
|
+
end
|
53
|
+
obj
|
54
|
+
end
|
55
|
+
|
56
|
+
def resolve_qualified(obj)
|
57
|
+
result = nil
|
58
|
+
query = nil
|
59
|
+
|
60
|
+
if obj[:class_path]&.length&.> 0
|
61
|
+
query = obj[:class_path] + [obj[:name]]
|
62
|
+
result = root.resolve_path(query)
|
63
|
+
else
|
64
|
+
query = obj[:name]
|
65
|
+
result = resolve(query)
|
66
|
+
result ||= resolve_inheritance(query)
|
67
|
+
end
|
68
|
+
|
69
|
+
puts "Qualified resolution of #{query.inspect} by #{name} failed." unless result
|
70
|
+
|
71
|
+
result
|
72
|
+
end
|
73
|
+
|
74
|
+
def method_missing(method_name, *args, **kwargs, &)
|
75
|
+
var = "@#{method_name}".to_sym
|
76
|
+
if instance_variables.include?(var)
|
77
|
+
instance_variable_get(var)
|
78
|
+
elsif @obj.key? method_name
|
79
|
+
@obj.fetch(method_name)
|
80
|
+
else
|
81
|
+
super
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def respond_to_missing?(method_name, include_private = false)
|
86
|
+
instance_variables.include?("@#{method_name}".to_sym) || @obj.key?(method_name) || super
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_s
|
90
|
+
"<SpecializedObject for #{@provider.path_of(@obj).join("::")}>"
|
91
|
+
end
|
92
|
+
|
93
|
+
def inspect = to_s
|
94
|
+
|
95
|
+
def prepare_inheritance
|
96
|
+
@inheritance_prepared = true
|
97
|
+
@inherits = coerce_inheritance_data(@obj[:inherits])
|
98
|
+
@extends = @obj[:extends]&.map { resolve_qualified _1 }
|
99
|
+
@includes = @obj[:includes]&.map { resolve_qualified _1 }
|
100
|
+
@classes.each(&:prepare_inheritance)
|
101
|
+
@modules.each(&:prepare_inheritance)
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def make_path
|
107
|
+
r = [name]
|
108
|
+
p = parent
|
109
|
+
while p
|
110
|
+
r << p.name
|
111
|
+
p = p.parent
|
112
|
+
end
|
113
|
+
|
114
|
+
r.reverse
|
115
|
+
end
|
116
|
+
|
117
|
+
def parent_of(parent)
|
118
|
+
return unless parent
|
119
|
+
|
120
|
+
p = parent
|
121
|
+
while p
|
122
|
+
return p unless p.parent
|
123
|
+
|
124
|
+
p = p.parent
|
125
|
+
end
|
126
|
+
|
127
|
+
p
|
128
|
+
end
|
129
|
+
|
130
|
+
def specialize_defs(defs, _parent)
|
131
|
+
defs.values.map do |i|
|
132
|
+
decoration = if i[:source] == "inheritance"
|
133
|
+
"inherited"
|
134
|
+
elsif i[:overriding]
|
135
|
+
"override"
|
136
|
+
else
|
137
|
+
""
|
138
|
+
end
|
139
|
+
|
140
|
+
origin = i[:source]
|
141
|
+
|
142
|
+
@provider.find_source(i)
|
143
|
+
.merge({ decoration:, origin: })
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def coerce_inheritance_data(obj)
|
148
|
+
return obj if obj.nil?
|
149
|
+
|
150
|
+
resolve_inheritance(obj) || obj
|
151
|
+
end
|
152
|
+
|
153
|
+
def prepare(parent)
|
154
|
+
@inheritance_prepared = true
|
155
|
+
@parent = parent
|
156
|
+
@defs = specialize_defs(@obj[:defs], self)
|
157
|
+
@sdefs = specialize_defs(@obj[:sdefs], self)
|
158
|
+
@attributes = (@obj[:attributes] || {}).values.map do |v|
|
159
|
+
@provider.prepare_attr(v)
|
160
|
+
end
|
161
|
+
|
162
|
+
@root = parent_of(parent)
|
163
|
+
@path = make_path
|
164
|
+
|
165
|
+
@classes = @obj[:classes].map { SpecializedObject.specialize(_1, self, @provider) }
|
166
|
+
@modules = @obj[:modules].map { SpecializedObject.specialize(_1, self, @provider) }
|
167
|
+
end
|
168
|
+
|
169
|
+
def named_as(n) = ->(o) { o.name == n }
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Renderer
|
4
|
+
class Defs
|
5
|
+
class SpecializedProjection < Array
|
6
|
+
def initialize(provider)
|
7
|
+
super()
|
8
|
+
@provider = provider
|
9
|
+
replace((provider.modules + provider.classes)
|
10
|
+
.map { provider.specialize_object _1 }
|
11
|
+
.each(&:prepare_inheritance))
|
12
|
+
end
|
13
|
+
|
14
|
+
def find_path(path)
|
15
|
+
path = @provider.path_of(path) unless path.is_a? Array
|
16
|
+
p = path.dup
|
17
|
+
obj = find { _1.name == p.first }
|
18
|
+
p.shift
|
19
|
+
return unless obj
|
20
|
+
|
21
|
+
until p.empty?
|
22
|
+
obj = obj.resolve(p.first)
|
23
|
+
p.shift
|
24
|
+
return unless obj
|
25
|
+
end
|
26
|
+
|
27
|
+
obj
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "defs/specialized_object"
|
4
|
+
require_relative "defs/specialized_projection"
|
5
|
+
|
6
|
+
class Renderer
|
7
|
+
class Defs
|
8
|
+
class << self
|
9
|
+
attr_reader :singleton
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_writer :singleton
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(base, metadata)
|
17
|
+
@data = JSON.parse(File.read("#{base}/data.json"), symbolize_names: true)
|
18
|
+
@meta = metadata
|
19
|
+
Defs.singleton = self
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :meta
|
23
|
+
|
24
|
+
def classes = @classes ||= make_paths(@data[:classes])
|
25
|
+
def modules = @modules ||= make_paths(@data[:modules])
|
26
|
+
|
27
|
+
def make_paths(obj)
|
28
|
+
return [] unless obj
|
29
|
+
|
30
|
+
obj.each { set_parent(_1, nil) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_parent(obj, parent)
|
34
|
+
obj[:parent] = parent
|
35
|
+
obj[:classes].each { set_parent(_1, obj) }
|
36
|
+
obj[:modules].each { set_parent(_1, obj) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def document_outline
|
40
|
+
(classes + modules).map { outline(_1) }
|
41
|
+
end
|
42
|
+
|
43
|
+
def outline(object, level = 0)
|
44
|
+
defs = object[:defs].values.map { map_method(_1) }.sort_by { _1[:name] }
|
45
|
+
sdefs = object[:sdefs].values.map { map_method(_1) }.sort_by { _1[:name] }
|
46
|
+
attributes = object[:attributes]&.values&.map { prepare_attr(_1) }&.sort_by { _1[:name] }
|
47
|
+
|
48
|
+
{
|
49
|
+
level:,
|
50
|
+
name: object[:name],
|
51
|
+
type: object[:type],
|
52
|
+
classes: object[:classes].map { outline(_1, level + 1) },
|
53
|
+
modules: object[:modules].map { outline(_1, level + 1) },
|
54
|
+
defs: defs + sdefs,
|
55
|
+
attributes:
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def map_method(met)
|
60
|
+
decoration = if met[:source] == "inheritance"
|
61
|
+
"inherited"
|
62
|
+
elsif met[:overriding]
|
63
|
+
"override"
|
64
|
+
end
|
65
|
+
|
66
|
+
obj = find_source(met)
|
67
|
+
type = [].tap do |arr|
|
68
|
+
arr << "Class" if obj[:type] == "defs"
|
69
|
+
arr << "Method"
|
70
|
+
end.join(" ")
|
71
|
+
|
72
|
+
{
|
73
|
+
name: obj[:name],
|
74
|
+
visibility: obj[:visibility],
|
75
|
+
args: obj[:args],
|
76
|
+
type:,
|
77
|
+
short_type: obj[:type],
|
78
|
+
doc: obj[:doc],
|
79
|
+
decoration:
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def find_source(met)
|
84
|
+
obj = met
|
85
|
+
obj = obj[:definition] while obj[:source] != "source"
|
86
|
+
obj[:definition]
|
87
|
+
end
|
88
|
+
|
89
|
+
def prepare_attr(met)
|
90
|
+
decoration = if met[:source] == "inheritance"
|
91
|
+
"inherited"
|
92
|
+
elsif met[:overriding]
|
93
|
+
"override"
|
94
|
+
end
|
95
|
+
origin = met[:source]
|
96
|
+
att = find_source(met)
|
97
|
+
visibility = if att[:reader_visibility] == "public" && att[:writer_visibility] == "public"
|
98
|
+
"read/write"
|
99
|
+
elsif att[:reader_visibility] == "public" && att[:writer_visibility] != "public"
|
100
|
+
"read-only"
|
101
|
+
else
|
102
|
+
"write-only"
|
103
|
+
end
|
104
|
+
|
105
|
+
{
|
106
|
+
name: att[:name],
|
107
|
+
type: "Attribute",
|
108
|
+
visibility:,
|
109
|
+
decoration:,
|
110
|
+
origin:,
|
111
|
+
doc: att[:doc]
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
def path_of(item)
|
116
|
+
p = []
|
117
|
+
parent = item
|
118
|
+
until parent.nil?
|
119
|
+
p << parent[:name]
|
120
|
+
parent = parent[:parent]
|
121
|
+
end
|
122
|
+
p.reverse
|
123
|
+
end
|
124
|
+
|
125
|
+
def definitions_of(item)
|
126
|
+
item[:defined_by]&.map do |d|
|
127
|
+
path_components = d[:filename].split("/")
|
128
|
+
{
|
129
|
+
name: path_components.last,
|
130
|
+
href: git_url(d)
|
131
|
+
}
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def git_url(definition)
|
136
|
+
"#{@meta.git_url}/blob/#{@meta.git_tip}#{definition[:filename].gsub(@meta.git_root,
|
137
|
+
"")}#L#{definition[:start_at]}"
|
138
|
+
end
|
139
|
+
|
140
|
+
def clean_file_path(definition) = definition[:filename].gsub(meta.git_root, "")
|
141
|
+
|
142
|
+
def specialized_projection
|
143
|
+
@specialized_projection ||= SpecializedProjection.new(self)
|
144
|
+
end
|
145
|
+
|
146
|
+
def specialize_data
|
147
|
+
@specialize_data ||= (data[:modules] + data[:classes])
|
148
|
+
.map { specialize_object _1 }
|
149
|
+
.each(&:prepare_inheritance)
|
150
|
+
end
|
151
|
+
|
152
|
+
def specialize_object(obj, parent = nil)
|
153
|
+
SpecializedObject.specialize(obj, parent, self)
|
154
|
+
end
|
155
|
+
|
156
|
+
def by_name(n) = ->(o) { o[:name] == n }
|
157
|
+
|
158
|
+
def doc_for(path)
|
159
|
+
path = path_of(path) if path.is_a? Hash
|
160
|
+
path = path.dup
|
161
|
+
named = by_name(path.shift)
|
162
|
+
root = classes.find(&named) || modules.find(&named)
|
163
|
+
|
164
|
+
return unless root
|
165
|
+
|
166
|
+
find_recursive(path, root)
|
167
|
+
end
|
168
|
+
|
169
|
+
def find_recursive(path, root)
|
170
|
+
return root if path.empty?
|
171
|
+
|
172
|
+
named = by_name(path.shift)
|
173
|
+
next_item = root.classes.find(&named) || root.modules.find(&named)
|
174
|
+
|
175
|
+
return nil unless next_item
|
176
|
+
|
177
|
+
find_recursive(path, next_item)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|