docrb-html 0.2.5 → 0.3.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.
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 %>