docrb-html 0.2.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +1 -1
  3. data/.rubocop.yml +32 -15
  4. data/Gemfile +11 -1
  5. data/Gemfile.lock +52 -2
  6. data/assets/breadcrumb.scss +0 -1
  7. data/assets/class_header.scss +1 -0
  8. data/assets/constant_display.scss +16 -0
  9. data/assets/doc_box.scss +34 -4
  10. data/assets/documentation_block.scss +29 -1
  11. data/assets/field_block.scss +46 -0
  12. data/assets/js/filtering.js +3 -3
  13. data/assets/links.scss +0 -2
  14. data/assets/method_argument.scss +2 -8
  15. data/assets/method_display.scss +4 -0
  16. data/assets/method_list.scss +40 -0
  17. data/assets/reference.scss +1 -1
  18. data/assets/style.scss +3 -0
  19. data/assets/svg.scss +37 -0
  20. data/assets/symbol.scss +1 -1
  21. data/assets/text_block.scss +9 -9
  22. data/bin/smoke +5 -0
  23. data/{renderer.gemspec → docrb-html.gemspec} +2 -0
  24. data/exe/docrb-html +1 -1
  25. data/lib/docrb-html.rb +165 -0
  26. data/lib/renderer/component/attribute.rb +9 -0
  27. data/lib/renderer/component/attribute_display.rb +17 -0
  28. data/lib/renderer/component/constant_display.rb +9 -0
  29. data/lib/renderer/component/doc_box.rb +26 -18
  30. data/lib/renderer/component/documentation_comment.rb +9 -0
  31. data/lib/renderer/component/field_block.rb +9 -0
  32. data/lib/renderer/component/method_argument.rb +19 -63
  33. data/lib/renderer/component/method_display.rb +1 -1
  34. data/lib/renderer/component/method_list.rb +1 -1
  35. data/lib/renderer/component/reference.rb +23 -12
  36. data/lib/renderer/component/text_block.rb +1 -7
  37. data/lib/renderer/component.rb +4 -4
  38. data/lib/renderer/core_extensions.rb +12 -1
  39. data/lib/renderer/entities/attribute.rb +17 -0
  40. data/lib/renderer/entities/attribute_definition.rb +23 -0
  41. data/lib/renderer/entities/base.rb +58 -0
  42. data/lib/renderer/entities/class.rb +17 -0
  43. data/lib/renderer/entities/container.rb +52 -0
  44. data/lib/renderer/entities/method.rb +18 -0
  45. data/lib/renderer/entities/method_argument.rb +27 -0
  46. data/lib/renderer/entities/method_definition.rb +25 -0
  47. data/lib/renderer/entities/module.rb +29 -0
  48. data/lib/renderer/entities/reference.rb +103 -0
  49. data/lib/renderer/entities/source_definition.rb +17 -0
  50. data/lib/renderer/entities.rb +30 -0
  51. data/lib/renderer/helpers.rb +77 -19
  52. data/lib/renderer/markdown.rb +62 -0
  53. data/lib/renderer/metadata.rb +10 -26
  54. data/lib/renderer/template.rb +4 -6
  55. data/lib/renderer/version.rb +1 -1
  56. data/script/makecomponent +1 -1
  57. data/templates/attribute.erb +10 -0
  58. data/templates/attribute_display.erb +22 -0
  59. data/templates/breadcrumb.erb +9 -9
  60. data/templates/class_header.erb +6 -7
  61. data/templates/component_list.erb +14 -8
  62. data/templates/constant_display.erb +13 -0
  63. data/templates/doc_box.erb +40 -31
  64. data/templates/documentation_block.erb +2 -11
  65. data/templates/documentation_comment.erb +23 -0
  66. data/templates/field_block.erb +15 -0
  67. data/templates/method_argument.erb +4 -4
  68. data/templates/method_display.erb +14 -21
  69. data/templates/method_list.erb +52 -8
  70. data/templates/reference.erb +10 -7
  71. data/templates/text_block.erb +13 -14
  72. metadata +60 -8
  73. data/lib/renderer/defs/specialized_object.rb +0 -172
  74. data/lib/renderer/defs/specialized_projection.rb +0 -31
  75. data/lib/renderer/defs.rb +0 -180
  76. data/lib/renderer.rb +0 -131
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ module Entities
5
+ class Container < Base
6
+ attr_accessor :classes, :modules, :extends, :includes, :defs, :sdefs, :defined_by, :doc, :constants
7
+
8
+ def initialize(parent, model)
9
+ super(parent, model[:name])
10
+ @classes = init_entities(model, :classes, as: Class)
11
+ @modules = init_entities(model, :modules, as: Module)
12
+ @extends = init_references!(model, :extends)
13
+ @includes = init_references!(model, :includes)
14
+ @constants = model[:constants] || {}
15
+ @defs = model.fetch(:defs, {}).map { |k, v| Method.new(self, :def, k.to_s, v) }
16
+ @sdefs = model.fetch(:sdefs, {}).map { |k, v| Method.new(self, :sdef, k.to_s, v) }
17
+ @defined_by = init_entities(model, :defined_by, as: SourceDefinition)
18
+ end
19
+
20
+ def find_nested_container(named)
21
+ @modules.find { _1.name == named } || @classes.find { _1.name == named }
22
+ end
23
+
24
+ def resolve_class_path(path)
25
+ path.shift if path.first == "::"
26
+ obj = find_nested_container(path.shift)
27
+ return if obj.nil?
28
+
29
+ until path.empty?
30
+ obj = obj.find_nested_container(path.shift)
31
+ return if obj.nil?
32
+ end
33
+
34
+ obj
35
+ end
36
+
37
+ def init_entities(model, key, as:) = model.fetch(key, []).map { as.new(self, _1) }
38
+
39
+ def init_reference!(model, attr) = Reference.new(self, model, attr)
40
+
41
+ def init_references!(model, key, attr: nil)
42
+ model.fetch(key, []).map { init_reference!(_1, attr || key) }
43
+ end
44
+
45
+ def init_reference(model, attr)
46
+ return if model.nil?
47
+
48
+ Reference.new(self, model, attr)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ module Entities
5
+ class Method < Base
6
+ attr_accessor :overriding, :source, :definition
7
+
8
+ def initialize(parent, type, name, model)
9
+ super(parent, name)
10
+ @overriding = model[:overriding] # TODO
11
+ @type = type
12
+ @definition = MethodDefinition.new(self, model)
13
+ end
14
+
15
+ attr_reader :type
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ module Entities
5
+ class MethodArgument
6
+ attr_accessor :name, :type, :value, :value_type, :parent
7
+
8
+ def initialize(parent, arg)
9
+ @parent = parent
10
+ @name = arg[:name]
11
+ @type = arg[:type].to_sym
12
+ @value = arg[:value]
13
+ @value_type = arg[:value_type]
14
+ end
15
+
16
+ def positional? = type == :arg || type == :optarg
17
+
18
+ def optional? = type == :optarg || type == :kwoptarg
19
+
20
+ def kwarg? = type == :kwarg || type == :kwoptarg
21
+
22
+ def rest? = type == :restarg || type == :kwrestarg
23
+
24
+ def block? = type == :blockarg
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ module Entities
5
+ class MethodDefinition
6
+ attr_accessor :args, :defined_by, :doc, :name, :overridden_by, :visibility, :parent
7
+
8
+ def initialize(parent, model)
9
+ @parent = parent
10
+ @args = model[:definition][:args].map { MethodArgument.new(self, _1) }
11
+ @defined_by = SourceDefinition.new(nil, model[:definition][:defined_by])
12
+ @doc = model[:definition][:doc]
13
+ @name = model[:definition][:name]
14
+ @overridden_by = model[:definition][:overridden_by] # TODO
15
+ @visibility = model[:definition][:visibility].to_sym
16
+ end
17
+
18
+ def protected? = visibility == :protected?
19
+
20
+ def public? = visibility == :public?
21
+
22
+ def private? = visibility == :private?
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ module Entities
5
+ class Module < Container
6
+ def type = :module
7
+
8
+ def initialize(parent, model)
9
+ if parent.nil?
10
+ as_root { super }
11
+ else
12
+ super
13
+ end
14
+ end
15
+
16
+ def resolve_references! = @references.each(&:resolve!)
17
+
18
+ private
19
+
20
+ def as_root
21
+ old_root = Entities.current_root
22
+ Entities.current_root = self
23
+ yield
24
+ ensure
25
+ Entities.current_root = old_root
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ module Entities
5
+ class Reference
6
+ def initialize(parent, model, field)
7
+ @parent = parent
8
+ @root = Entities.current_root
9
+ @root.register_reference(self)
10
+
11
+ if model.is_a? String
12
+ @name = model
13
+ @class_path = []
14
+ else
15
+ @name = model[:name]
16
+ @class_path = model[:class_path]
17
+ end
18
+ @field = field
19
+ @target = nil
20
+ @broken = false
21
+ end
22
+
23
+ def resolved? = !@target.nil? || @broken
24
+
25
+ def broken? = @broken
26
+
27
+ def resolve!
28
+ return __resolve_from_root__ if @class_path.first == "::"
29
+ return __resolve_from_class_path__ unless @class_path.empty?
30
+
31
+ location = __location__.dup
32
+ until location.empty?
33
+ container = location.shift.find_nested_container(@name)
34
+ return __assign__(container) if container
35
+ end
36
+
37
+ __assign__ @root.find_nested_container(@name)
38
+ end
39
+
40
+ def method_missing(name, *)
41
+ return @target.send(name, *) if @target.respond_to?(name)
42
+
43
+ return @name if name == :name
44
+
45
+ super
46
+ end
47
+
48
+ def respond_to_missing?(name, include_private = false)
49
+ @target&.respond_to_missing?(name, include_private) || super
50
+ end
51
+
52
+ def inspect
53
+ full_name = [@class_path, @name].flatten.join("::")
54
+ "#<#{self.class.name}:#{object_id_hex} #{broken? ? "broken" : "valid"} reference to #{full_name}>"
55
+ end
56
+
57
+ def to_s = inspect
58
+
59
+ private
60
+
61
+ def __location__
62
+ return @location if @location
63
+
64
+ parents = []
65
+ current = @parent.parent
66
+
67
+ while current&.parent
68
+ parents << current
69
+ current = current.parent
70
+ end
71
+
72
+ @location = parents
73
+ end
74
+
75
+ def __broken__
76
+ @broken = true
77
+ nil
78
+ end
79
+
80
+ def __assign__(target)
81
+ (@target = target) or __broken__
82
+ end
83
+
84
+ def __resolve_from_root__
85
+ container = @root.resolve_class_path(@class_path.dup) or return __broken__
86
+ __assign__ container.find_nested_container(@name)
87
+ end
88
+
89
+ def __resolve_from_class_path__
90
+ location = __location__.dup
91
+ container = nil
92
+
93
+ while !container && !location.empty? && !@class_path.empty?
94
+ container = location.shift&.find_nested_container(@class_path.first)
95
+ end
96
+ return __broken__ if container.nil?
97
+
98
+ container = container.resolve_class_path(@class_path[1..].dup) or return __broken__
99
+ __assign__ container.find_nested_container(@name)
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ module Entities
5
+ class SourceDefinition
6
+ attr_accessor :end_at, :start_at, :source, :markdown_source, :filename
7
+
8
+ def initialize(_parent, model)
9
+ @end_at = model[:end_at]
10
+ @start_at = model[:start_at]
11
+ @source = model[:source]
12
+ @markdown_source = model[:markdown_source]
13
+ @filename = model[:filename]
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "entities/base"
4
+ require_relative "entities/container"
5
+
6
+ require_relative "entities/method"
7
+ require_relative "entities/method_argument"
8
+ require_relative "entities/method_definition"
9
+ require_relative "entities/module"
10
+ require_relative "entities/class"
11
+ require_relative "entities/source_definition"
12
+ require_relative "entities/attribute"
13
+ require_relative "entities/attribute_definition"
14
+ require_relative "entities/reference"
15
+
16
+ class Renderer
17
+ module Entities
18
+ def self.current_root = Thread.current[:current_root]
19
+
20
+ def self.current_root=(val)
21
+ Thread.current[:current_root] = val
22
+ end
23
+
24
+ def self.load_from(path)
25
+ model = JSON.load_file(path, symbolize_names: true)
26
+ Module.new(nil, model)
27
+ .tap(&:resolve_references!)
28
+ end
29
+ end
30
+ end
@@ -1,26 +1,43 @@
1
1
  class Renderer
2
2
  class Helpers
3
+ class << self
4
+ attr_reader :current_renderer
5
+ end
6
+
7
+ class << self
8
+ attr_writer :current_renderer
9
+ end
10
+
3
11
  def svg(name, **kwargs)
4
12
  attrs = {}
5
13
  cls = kwargs.delete(:class_name)
6
- attrs["class"] = cls if cls
14
+ title = kwargs.delete(:title)
15
+ attrs["class"] = cls if cls && !title
7
16
  kwargs.each { |k, v| attrs[k.to_s] = v.to_s }
8
17
 
9
18
  svg = File.read(Renderer::ASSETS_PATH.join("images/#{name}.svg"))
10
- return svg if attrs.empty?
19
+ return svg if attrs.empty? && title.nil?
11
20
 
12
21
  doc = Nokogiri::XML svg
13
22
  attrs.each do |k, v|
14
23
  doc.css("svg")[0][k] = v
15
24
  end
16
- doc.to_xml.split("\n").tap(&:shift).join("\n")
25
+ doc = doc.to_xml.split("\n").tap(&:shift).join("\n")
26
+ return doc if title.nil?
27
+
28
+ <<~HTML
29
+ <div class="svg-container #{cls}">
30
+ <div class="svg-title">#{title}</div>
31
+ #{doc}
32
+ </div>
33
+ HTML
17
34
  end
18
35
 
19
36
  def div(class_name, **kwargs, &block)
20
37
  classes = [class_name, kwargs.delete(:class_name)].flatten.compact
21
38
  args = kwargs
22
- .compact
23
- .map { |k, v| "#{k}=\"#{v.gsub(/"/, "\\\"")}\"" }
39
+ .compact
40
+ .map { |k, v| "#{k}=\"#{v.gsub('"', "\\\"")}\"" }
24
41
 
25
42
  start_tag = "<div class=\"#{classes.join(" ")}\" #{args.join(" ")}>"
26
43
  end_tag = "</div>"
@@ -31,10 +48,10 @@ class Renderer
31
48
  raw = block.call
32
49
 
33
50
  captured = if fake_buffer.empty?
34
- raw
35
- else
36
- fake_buffer
37
- end
51
+ raw
52
+ else
53
+ fake_buffer
54
+ end
38
55
  ensure
39
56
  block.binding.local_variable_set(:_erbout, "#{start_tag}#{captured}#{end_tag}")
40
57
  end
@@ -46,21 +63,21 @@ class Renderer
46
63
  raw = block.call
47
64
 
48
65
  captured = if fake_buffer.empty?
49
- raw
50
- else
51
- fake_buffer
52
- end
66
+ raw
67
+ else
68
+ fake_buffer
69
+ end
53
70
  ensure
54
71
  block.binding.local_variable_set(:_erbout, old_buffer)
55
72
  end
56
73
 
57
- def git_url(source) = Renderer::Defs.singleton.git_url(source)
74
+ def git_url(source) = self.class.current_renderer.git_url(source)
58
75
 
59
- def clean_file_path(source) = Renderer::Defs.singleton.clean_file_path(source)
76
+ def clean_file_path(source) = self.class.current_renderer.clean_file_path(source)
60
77
 
61
78
  def line_range(source)
62
- from = source[:start_at]
63
- to = source[:end_at]
79
+ from = source.line_start
80
+ to = source.line_end
64
81
 
65
82
  if from == to
66
83
  "line #{from}"
@@ -68,11 +85,52 @@ class Renderer
68
85
  "lines #{from} to #{to}"
69
86
  end
70
87
  end
88
+
89
+ def source_of(obj, parent = nil)
90
+ parent ||= obj.parent
91
+
92
+ case (v = parent.source_of(obj))
93
+ when :inherited, :included, :extended then v.to_s
94
+ when :self then ("override" if obj.try(:overriding))
95
+ else raise "WTF? Source of #{obj} is #{v.inspect}!"
96
+ end
97
+ end
98
+
99
+ def path_of(object, root: true)
100
+ return [] if object.nil? && !root
101
+ return [object.name] + path_of(object.parent, root: false) unless root
102
+
103
+ path = ["#{object.name}.html"] + path_of(object.parent, root: false)
104
+ path << ""
105
+ path.reverse.join("/")
106
+ end
107
+
108
+ def link_for(object)
109
+ case object
110
+ when Docrb::Parser::Attribute, Docrb::Parser::Method, Docrb::Parser::Constant
111
+ "#{path_of(object.parent)}##{anchor_for(object)}"
112
+ when Docrb::Parser::Class, Docrb::Parser::Module
113
+ path_of(object)
114
+ else
115
+ raise ArgumentError, "#link_for cannot link #{object.class.name}"
116
+ end
117
+ end
118
+
119
+ def anchor_for(object)
120
+ case object
121
+ when Docrb::Parser::Attribute then "#{object.type}-attr-#{object.name}"
122
+ when Docrb::Parser::Method then "#{object.type}-method-#{object.name}"
123
+ when Docrb::Parser::Constant then "const-#{object.name}"
124
+ when Docrb::Parser::Class, Docrb::Parser::Module then ""
125
+ else
126
+ raise ArgumentError, "#anchor_for cannot process #{object.class.name}"
127
+ end
128
+ end
71
129
  end
72
130
 
73
131
  Component.constants
74
- .reject { _1 == :HELPERS }
75
- .each do |cls|
132
+ .reject { _1 == :HELPERS }
133
+ .each do |cls|
76
134
  Helpers.define_method(cls.to_s.snakify) do |**kwargs|
77
135
  Component.const_get(cls).new(**kwargs).render
78
136
  end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ # Renderer provides a Redcarpet renderer with Rouge extensions
5
+ class MarkdownRenderer < Redcarpet::Render::HTML
6
+ def initialize(extensions = {})
7
+ super extensions.merge(link_attributes: { target: "_blank" })
8
+ end
9
+ include Rouge::Plugins::Redcarpet
10
+ end
11
+
12
+ # InlineRenderer provides a renderer for inline contents. This renderer
13
+ # does not emit paragraph tags.
14
+ class InlineRenderer < MarkdownRenderer
15
+ def paragraph(text)
16
+ text
17
+ end
18
+ end
19
+
20
+ # Markdown provides utilities for generating HTML from markdown contents
21
+ class Markdown
22
+ # Internal: Creates a new renderer based on a provided type by setting
23
+ # sensible defaults.
24
+ #
25
+ # type - Type of the renderer to be initialised. Use Renderer or
26
+ # InlineRenderer
27
+ def self.make_render(type)
28
+ Redcarpet::Markdown.new(
29
+ type,
30
+ fenced_code_blocks: true,
31
+ autolink: true
32
+ )
33
+ end
34
+
35
+ # Renders a given input using the default renderer.
36
+ #
37
+ # input - Markdown content to be rendered
38
+ #
39
+ # Returns an HTML string containing the rendered Markdown content
40
+ def self.render(input)
41
+ make_render(MarkdownRenderer).render(input)
42
+ end
43
+
44
+ # Renders a given input using the inline renderer.
45
+ #
46
+ # input - Markdown content to be rendered
47
+ #
48
+ # Returns an HTML string containing the rendered Markdown content
49
+ def self.inline(input)
50
+ make_render(InlineRenderer).render(input)
51
+ end
52
+
53
+ # Renders a given Ruby source code into HTML
54
+ #
55
+ # source - Source code to be rendered
56
+ #
57
+ # Returns an HTML string containing the rendered source code
58
+ def self.render_source(source)
59
+ render("```ruby\n#{source}\n```")
60
+ end
61
+ end
62
+ end
@@ -2,11 +2,7 @@
2
2
 
3
3
  class Renderer
4
4
  class Metadata
5
- def initialize(base)
6
- @data = JSON.parse(File.read("#{base}/metadata.json"))
7
- end
8
-
9
- def format_authors
5
+ def self.format_authors(authors)
10
6
  return nil if authors.nil? || authors.count.zero?
11
7
  return authors.first if authors.length == 1
12
8
 
@@ -14,31 +10,19 @@ class Renderer
14
10
  "#{authors.first}, and #{others} other#{others > 1 ? "s" : ""}"
15
11
  end
16
12
 
17
- def project_links
13
+ def self.project_links(meta)
18
14
  links = []
19
- links << { kind: "rubygems", href: host_url } if host_url
20
-
21
- if git_url
22
- links << if git_url.index("github.com/")
23
- { kind: "github", href: git_url }
24
- else
25
- { kind: "git", href: git_url }
26
- end
15
+ links << { kind: "rubygems", href: meta[:host_url] } if meta.key? :host_url
16
+
17
+ if meta.key? :git_url
18
+ links << if meta[:git_url].index("github.com/")
19
+ { kind: "github", href: meta[:git_url] }
20
+ else
21
+ { kind: "git", href: meta[:git_url] }
22
+ end
27
23
  end
28
24
 
29
25
  links
30
26
  end
31
-
32
- def method_missing(method_name, *arguments, &)
33
- if @data.include? method_name.to_s
34
- @data[method_name.to_s]
35
- else
36
- super
37
- end
38
- end
39
-
40
- def respond_to_missing?(method_name, include_private = false)
41
- @data.key?(method_name.to_s) || super
42
- end
43
27
  end
44
28
  end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  class Renderer
4
2
  class Template
5
3
  class Bind
@@ -8,11 +6,11 @@ class Renderer
8
6
  @keys = keys
9
7
  end
10
8
 
11
- def method_missing(method_name, *args, **kwargs, &)
9
+ def method_missing(method_name, ...)
12
10
  if @keys.include? method_name
13
11
  @keys[method_name]
14
12
  else
15
- @obj.send(method_name, *args, **kwargs, &)
13
+ @obj.send(method_name, ...)
16
14
  end
17
15
  end
18
16
 
@@ -30,8 +28,8 @@ class Renderer
30
28
  @template.filename = path.to_s
31
29
  end
32
30
 
33
- def render(b, *args, **kwargs)
34
- bind = Bind.new(b, *args, **kwargs)
31
+ def render(bin, *, **)
32
+ bind = Bind.new(bin, *, **)
35
33
  @template.result(bind.make_binding)
36
34
  end
37
35
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Renderer
4
- VERSION = "0.2.5"
4
+ VERSION = "0.3.0"
5
5
  end
data/script/makecomponent CHANGED
@@ -4,7 +4,7 @@
4
4
  require_relative "../lib/renderer/core_extensions"
5
5
  name = ARGV.first.snakify
6
6
  real_name = ARGV.first
7
- dashed_name = name.gsub(/_/, "-")
7
+ dashed_name = name.gsub("_", "-")
8
8
  File.write("assets/#{name}.scss", "div.#{dashed_name}-base {\n\n}\n")
9
9
  styles = File.read("assets/style.scss")
10
10
  File.write("assets/style.scss", "#{styles}@import './#{name}';\n")
@@ -0,0 +1,10 @@
1
+ <div class="attribute-container"
2
+ data-origin="<%= source_of(item) %>"
3
+ data-type="attribute"
4
+ id="<%= kind %>-attr-<%= item.name %>"
5
+ >
6
+ <%= attribute_display(item: item, kind:, omit_type:) %>
7
+ <div class="doc-block">
8
+ <%= documentation_block(doc: item.doc) %>
9
+ </div>
10
+ </div>
@@ -0,0 +1,22 @@
1
+ <% div("method-display-base", id:) do %>
2
+ <% if (dec = source_of(item)) %>
3
+ <%= svg(dec.to_s.downcase, class_name: "decoration", title: dec.to_s.capitalize) %>
4
+ <% end %>
5
+ <% if kind && !omit_type %>
6
+ <%= typedef(name: "#{kind.capitalize} Attribute") %>
7
+ <% end %>
8
+ <% name = capture do %>
9
+ <div class="container">
10
+ <div class="method-name"><%= item.name %></div>
11
+ </div>
12
+ <% end %>
13
+ <% if omit_link %>
14
+ <%= name %>
15
+ <% else %>
16
+ <a class="dashed" href="<%= link_for(item) %>"><%= name %></a>
17
+ <% end %>
18
+ <div class="label"><%= attr_type %></div>
19
+ <% if (visibility = item.doc&.dig(:meta, :visibility_annotation)) %>
20
+ <div class="label"><%= visibility %></div>
21
+ <% end %>
22
+ <% end %>