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
data/lib/docrb-html.rb ADDED
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ require "erb"
6
+ require "sassc"
7
+ require "nokogiri"
8
+ require "redcarpet"
9
+ require "rouge"
10
+ require "rouge/plugins/redcarpet"
11
+
12
+ require_relative "renderer/version"
13
+ require_relative "renderer/core_extensions"
14
+ require_relative "renderer/markdown"
15
+
16
+ class Renderer
17
+ ASSETS_PATH = Pathname.new(__dir__).join("../assets")
18
+ TEMPLATES_PATH = Pathname.new(__dir__).join("../templates")
19
+ STYLE_BASE = SassC::Engine.new(File.read(ASSETS_PATH.join("style.scss")),
20
+ style: :compressed,
21
+ load_paths: [ASSETS_PATH]).render
22
+ end
23
+
24
+ require_relative "renderer/template"
25
+ require_relative "renderer/component"
26
+ require_relative "renderer/helpers"
27
+ require_relative "renderer/page"
28
+ require_relative "renderer/metadata"
29
+ require_relative "renderer/entities"
30
+
31
+ class Renderer
32
+ def now = Time.now.strftime("%A, %-d %b %Y %H:%M:%S %Z")
33
+
34
+ def output_path(*args) = File.join(@output, *args.map(&:to_s))
35
+
36
+ def initialize(source, spec, output)
37
+ @output = output
38
+ @footer = Component::Footer.new(version: VERSION, updated_at: now)
39
+ @spec = spec
40
+ @source = source
41
+ Helpers.current_renderer = self
42
+ end
43
+
44
+ def git_url(loc)
45
+ url = @spec[:git_url]
46
+ tip = @spec[:git_tip]
47
+ filename = clean_file_path(loc)
48
+ "#{url}/blob/#{tip}#{filename}#L#{loc.line_start}"
49
+ end
50
+
51
+ def clean_file_path(definition) = definition.file_path.gsub(@spec[:git_root], "")
52
+
53
+ def make_outline
54
+ (@source.nodes.by_kind(:module) + @source.nodes.by_kind(:class))
55
+ .map { outline(_1) }
56
+ end
57
+
58
+ def outline(object, level = 0)
59
+ {
60
+ level:,
61
+ object:,
62
+ classes: object.classes.map { outline(_1, level + 1) },
63
+ modules: object.modules.map { outline(_1, level + 1) }
64
+ }
65
+ end
66
+
67
+ def render
68
+ project_header = Component::ProjectHeader.new(
69
+ name: @spec[:name],
70
+ description: @spec[:summary],
71
+ license: @spec[:license],
72
+ owner: Metadata.format_authors(@spec[:authors]),
73
+ links: Metadata.project_links(@spec)
74
+ )
75
+
76
+ index = Page.new(title: "#{@spec[:name]} - Docrb") do
77
+ readme = Component::Markdown.new(source: Markdown.render(@spec[:readme]))
78
+
79
+ [
80
+ project_header,
81
+ Component::TabBar.new(
82
+ selected_index: 0,
83
+ items: [
84
+ { name: "Readme", href: "/" },
85
+ { name: "Components", href: "/components.html" }
86
+ ]
87
+ ),
88
+ readme,
89
+ @footer
90
+ ]
91
+ end
92
+
93
+ components = Page.new(title: "Components - #{@spec[:name]} - Docrb") do
94
+ [
95
+ project_header,
96
+ Component::TabBar.new(
97
+ selected_index: 1,
98
+ items: [
99
+ { name: "Readme", href: "/" },
100
+ { name: "Components", href: "/components.html" }
101
+ ]
102
+ ),
103
+ Component::ComponentList.new(list: make_outline),
104
+ @footer
105
+ ]
106
+ end
107
+
108
+ pages(@source.nodes.by_kind(:class, :module))
109
+
110
+ FileUtils.mkdir_p @output
111
+
112
+ index.render_to(output_path("index.html"))
113
+ components.render_to(output_path("components.html"))
114
+ File.write(output_path("style.css"), STYLE_BASE)
115
+
116
+ copy_assets
117
+ end
118
+
119
+ def copy_assets
120
+ [
121
+ "js/filtering.js",
122
+ "favicon.ico"
123
+ ].each do |file|
124
+ File.write(output_path(File.basename(file)),
125
+ File.read(ASSETS_PATH.join(file)))
126
+ end
127
+ end
128
+
129
+ def pages(comps, parents = [])
130
+ comps.each do |comp|
131
+ title = "#{comp.name} - #{@spec[:name]} - Docrb"
132
+ page = Page.new(title:, level: parents.count) do
133
+ [
134
+ Component::ClassHeader.new(
135
+ type: comp.kind,
136
+ name: comp.name,
137
+ definitions: comp.defined_by.map do |by|
138
+ {
139
+ filename: File.basename(by.file_path),
140
+ git_url: git_url(by)
141
+ }
142
+ end
143
+ ),
144
+ Component::Breadcrumb.new(
145
+ project_name: @spec[:name],
146
+ items: (parents + [comp]).map.with_index do |p, idx|
147
+ { name: p.name, parents: parents[0...idx].map(&:name) }
148
+ end
149
+ ),
150
+ Component::DocBox.new(
151
+ item: comp,
152
+ meta: @spec
153
+ ),
154
+ @footer
155
+ ]
156
+ end
157
+
158
+ parent_dir = output_path(*parents.map(&:name))
159
+ FileUtils.mkdir_p(parent_dir)
160
+ page.render_to(File.join(parent_dir, "#{comp.name}.html"))
161
+
162
+ pages(comp.classes + comp.modules, parents + [comp])
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ class Component
5
+ class Attribute < Component
6
+ prop :item, :kind, :omit_type
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ class Component
5
+ class AttributeDisplay < Component
6
+ prop :item, :attr_type, :omit_link, :kind, :omit_type
7
+
8
+ def prepare
9
+ @attr_type = case item.type
10
+ when :accessor then "read/write"
11
+ when :reader then "read-only"
12
+ else "write-only"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ class Component
5
+ class ConstantDisplay < Component
6
+ prop :item, :omit_link
7
+ end
8
+ end
9
+ end
@@ -3,32 +3,40 @@
3
3
  class Renderer
4
4
  class Component
5
5
  class DocBox < Component
6
- prop :item, :meta, :defs, :has_class_docs, :has_class_details, :has_attrs,
7
- :has_class_methods, :has_instance_methods, :page_components,
8
- :defs, :sdefs, :attrs
6
+ prop :item, :meta, :has_class_docs, :has_class_details,
7
+ :instance_methods, :has_instance_methods,
8
+ :class_methods, :has_class_methods,
9
+ :has_instance_attributes, :instance_attributes,
10
+ :has_class_attributes, :class_attributes,
11
+ :has_constants, :constants,
12
+ :page_components
9
13
 
10
14
  def prepare
11
- @item = defs.specialized_projection.find_path(@item)
15
+ @has_class_docs = (item.doc && !item.doc.empty?) || false
16
+ @instance_methods = item.all_instance_methods
17
+ @class_methods = item.all_class_methods
18
+ @instance_attributes = item.kind == :class ? item.all_instance_attributes : []
19
+ @class_attributes = item.all_class_attributes
20
+ @constants = item.constants
12
21
 
13
- @has_class_docs = item[:doc] && !item[:doc].empty?
14
- @defs = item.defs || []
15
- @sdefs = item.sdefs || []
16
- @attrs = item.attributes || []
17
-
18
- @has_attrs = !@attrs.empty?
19
- @has_class_methods = !@sdefs.empty?
20
- @has_instance_methods = !@defs.empty?
22
+ @has_instance_attributes = !@instance_attributes.empty?
23
+ @has_class_attributes = !@class_attributes.empty?
24
+ @has_class_methods = !@class_methods.empty?
25
+ @has_instance_methods = !@instance_methods.empty?
21
26
  @has_class_details =
22
- !item[:inherits].nil? \
23
- || !item.fetch(:extends, []).empty? \
24
- || !item.fetch(:includes, []).empty? \
25
- || !item.fetch(:modules, []).empty? \
26
- || !item.fetch(:classes, []).empty?
27
+ (item.kind == :class && !item.inherits.nil?) \
28
+ || !item.extends.empty? \
29
+ || !item.includes.empty? \
30
+ || !item.modules.empty? \
31
+ || !item.classes.empty?
32
+ @has_constants = !@constants.empty?
27
33
 
28
34
  @page_components = {
29
35
  "class-documentation" => { enabled: has_class_docs, name: "Class Documentation" },
30
36
  "class-details" => { enabled: has_class_details, name: "Inheritance" },
31
- "attributes" => { enabled: has_attrs, name: "Attributes" },
37
+ "constants" => { enabled: has_constants, name: "Constants" },
38
+ "class-attributes" => { enabled: has_class_attributes, name: "Class Attributes" },
39
+ "instance-attributes" => { enabled: has_instance_attributes, name: "Instance Attributes" },
32
40
  "class-methods" => { enabled: has_class_methods, name: "Class Methods" },
33
41
  "instance-methods" => { enabled: has_instance_methods, name: "Instance Methods" }
34
42
  }
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ class Component
5
+ class DocumentationComment < Component
6
+ prop :doc, :class_name
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ class Component
5
+ class FieldBlock < Component
6
+ prop :fields
7
+ end
8
+ end
9
+ end
@@ -3,9 +3,14 @@
3
3
  class Renderer
4
4
  class Component
5
5
  class MethodArgument < Component
6
- prop :type, :name, :value, :value_type, :computed
6
+ prop :type, :name, :value, :value_type, :computed, :arg
7
7
 
8
8
  def prepare
9
+ @type = @arg.kind
10
+ @name = @arg.name
11
+ @value = @arg.value&.source
12
+ @value_type = @arg.value_type
13
+
9
14
  @computed = {
10
15
  rest: rest_arg,
11
16
  name:,
@@ -15,17 +20,17 @@ class Renderer
15
20
  end
16
21
 
17
22
  def continuation_for_type
18
- if type == "kwarg" || type == "kwoptarg"
23
+ if arg.keyword? && !arg.rest?
19
24
  :colon
20
- elsif type&.index("opt")&.zero?
25
+ elsif arg.optional?
21
26
  :equal
22
27
  end
23
28
  end
24
29
 
25
30
  REST_ARG_BY_TYPE = {
26
- "kwrestarg" => :double,
27
- "restarg" => :single,
28
- "blockarg" => :block
31
+ kwrest: :double,
32
+ rest: :single,
33
+ block: :block
29
34
  }.freeze
30
35
 
31
36
  def rest_arg
@@ -36,71 +41,22 @@ class Renderer
36
41
  return if value_type.nil?
37
42
 
38
43
  case value_type
39
- when "sym"
44
+ when :symbol, :bool
40
45
  { kind: :symbol, value: }
41
- when "bool"
42
- { kind: :symbol, value: value.inspect }
43
- when "nil"
46
+ when :nil
44
47
  { kind: :symbol, value: "nil" }
45
- when "int"
48
+ when :number
46
49
  { kind: :number, value: }
47
- when "str"
50
+ when :string
48
51
  { kind: :string, value: }
49
- when "send"
50
- method_call_argument(value)
51
- when "const"
52
- const_value(value)
52
+ when :call
53
+ { kind: :call, value: }
54
+ when :const
55
+ { kind: :const, value: [value] }
53
56
  else
54
57
  { kind: :plain, value: }
55
58
  end
56
59
  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
60
  end
105
61
  end
106
62
  end
@@ -3,7 +3,7 @@
3
3
  class Renderer
4
4
  class Component
5
5
  class MethodDisplay < Component
6
- prop :visibility, :type, :name, :href, :args, :doc, :decoration, :short_type
6
+ prop :item, :omit_type, :parent
7
7
  end
8
8
  end
9
9
  end
@@ -3,7 +3,7 @@
3
3
  class Renderer
4
4
  class Component
5
5
  class MethodList < Component
6
- prop :list
6
+ prop :list, :omit_type, :parent
7
7
  end
8
8
  end
9
9
  end
@@ -3,21 +3,32 @@
3
3
  class Renderer
4
4
  class Component
5
5
  class Reference < Component
6
- prop :ref, :unresolved, :path
6
+ prop :unresolved, :path, :ref_type, :object, :value
7
7
 
8
8
  def prepare
9
- @unresolved = !ref[:ref_path]
10
- return if @unresolved
9
+ case @object
10
+ when Docrb::Parser::Reference
11
+ @unresolved = !@object.fulfilled?
12
+ @path = [@object.path.last]
13
+ return if @unresolved
11
14
 
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
15
+ @object = @object.dereference!
16
+ prepare
17
+ when Docrb::Parser::Container
18
+ @path = [@object.name]
19
+ @ref_type = @object.kind
20
+ parent = @object.parent
21
+ until parent.nil?
22
+ @path << parent.name
23
+ parent = parent.parent
24
+ end
25
+ @path << ""
26
+ @path.reverse!
27
+ else
28
+ @ref_type = :pure
29
+ @value = @object[:value]
30
+ @object = @object[:object]
31
+ end
21
32
  end
22
33
  end
23
34
  end
@@ -3,13 +3,7 @@
3
3
  class Renderer
4
4
  class Component
5
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
6
+ prop :contents, :inline
13
7
  end
14
8
  end
15
9
  end
@@ -4,11 +4,11 @@ class Renderer
4
4
  class Component
5
5
  attr_accessor :id
6
6
 
7
- def self.prop(*names)
8
- attr_accessor(*names)
7
+ def self.prop(*)
8
+ attr_accessor(*)
9
9
 
10
10
  @props ||= []
11
- @props.append(*names)
11
+ @props.append(*)
12
12
  end
13
13
 
14
14
  class << self
@@ -38,7 +38,7 @@ class Renderer
38
38
 
39
39
  def render(&)
40
40
  prepare
41
- opts = props.map { [_1, send(_1)] }.to_h
41
+ opts = props.to_h { [_1, send(_1)] }
42
42
  opts[:id] = @id
43
43
  template.render(HELPERS, **opts, &)
44
44
  end
@@ -2,10 +2,21 @@
2
2
 
3
3
  class String
4
4
  def snakify
5
- gsub(/::/, "/")
5
+ gsub("::", "/")
6
6
  .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
7
7
  .gsub(/([a-z\d])([A-Z])/, '\1_\2')
8
8
  .tr("-", "_")
9
9
  .downcase
10
10
  end
11
11
  end
12
+
13
+ class Object
14
+ def object_id_hex = "0x#{object_id.to_s(16).rjust(16, "0")}"
15
+
16
+ def self.memo(name, &)
17
+ define_method(name) do
18
+ @__memoized_variables__ ||= {}
19
+ @__memoized_variables__[name] ||= instance_exec(&)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ module Entities
5
+ class Attribute
6
+ attr_accessor :name, :source, :definition, :overriding, :parent
7
+
8
+ def initialize(parent, name, model)
9
+ @name = name
10
+ @parent = parent
11
+ @source = model[:source] # TODO
12
+ @definition = AttributeDefinition.new(self, model[:definition])
13
+ @overriding = model[:overriding] # TODO
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ module Entities
5
+ class AttributeDefinition
6
+ attr_reader :defined_by, :doc, :name, :reader_visibility, :writer_visibility, :type, :parent
7
+
8
+ def initialize(parent, model)
9
+ @parent = parent
10
+ @defined_by = model[:defined_by]
11
+ @doc = model[:doc] # TODO
12
+ @name = model[:name]
13
+ @reader_visibility = model[:reader_visibility].to_sym
14
+ @writer_visibility = model[:writer_visibility].to_sym
15
+ @type = model[:type] # TODO
16
+ end
17
+
18
+ def accessor? = reader? && writer?
19
+ def reader? = reader_visibility == :public
20
+ def writer? = writer_visibility == :public
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ module Entities
5
+ class Base
6
+ attr_accessor :name, :parent, :references
7
+
8
+ def initialize(parent, name)
9
+ @parent = parent
10
+ @name = name
11
+ @references = []
12
+ end
13
+
14
+ def type = raise NotImplementedError, "Classes inheriting Entities::Base must implement #type"
15
+
16
+ def module? = type == :module
17
+
18
+ def class? = type == :class
19
+
20
+ def def? = type == :def
21
+
22
+ def static? = type == :sdef
23
+
24
+ def root
25
+ obj = self
26
+ loop do
27
+ return obj if obj.parent.nil?
28
+
29
+ obj = obj.parent
30
+ end
31
+
32
+ raise "Orphaned object"
33
+ end
34
+
35
+ def inspect = "#<#{self.class.name}:#{object_id_hex} #{name}>"
36
+
37
+ def to_s = inspect
38
+
39
+ def root? = module? && parent.nil?
40
+
41
+ def register_reference(ref)
42
+ @references << ref
43
+ end
44
+
45
+ def full_path
46
+ parents = []
47
+ parent = self.parent
48
+ until parent.root?
49
+ parents << parent
50
+ parent = parent.parent
51
+ end
52
+
53
+ parents.reverse!
54
+ parents << self
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Renderer
4
+ module Entities
5
+ class Class < Container
6
+ attr_accessor :attributes, :inherits
7
+
8
+ def initialize(parent, model)
9
+ super(parent, model)
10
+ @attributes = model.fetch(:attributes, {}).map { |k, v| Attribute.new(self, k.to_s, v) }
11
+ @inherits = init_reference(model[:inherits], :inherits)
12
+ end
13
+
14
+ def type = :class
15
+ end
16
+ end
17
+ end