brief 1.2.0 → 1.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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +70 -0
  3. data/Gemfile.lock +2 -2
  4. data/README.md +143 -70
  5. data/lib/brief/adapters/middleman.rb +2 -3
  6. data/lib/brief/briefcase.rb +28 -5
  7. data/lib/brief/cli/change.rb +7 -7
  8. data/lib/brief/cli/init.rb +10 -11
  9. data/lib/brief/cli/write.rb +23 -0
  10. data/lib/brief/configuration.rb +3 -4
  11. data/lib/brief/document/content_extractor.rb +2 -4
  12. data/lib/brief/document/front_matter.rb +4 -4
  13. data/lib/brief/document/rendering.rb +7 -9
  14. data/lib/brief/document/section/builder.rb +10 -10
  15. data/lib/brief/document/section/mapping.rb +5 -11
  16. data/lib/brief/document/section.rb +2 -3
  17. data/lib/brief/document/structure.rb +14 -15
  18. data/lib/brief/document/templating.rb +14 -0
  19. data/lib/brief/document.rb +20 -9
  20. data/lib/brief/document_mapper.rb +10 -10
  21. data/lib/brief/dsl.rb +5 -6
  22. data/lib/brief/model/definition.rb +37 -13
  23. data/lib/brief/model/persistence.rb +0 -2
  24. data/lib/brief/model.rb +50 -21
  25. data/lib/brief/repository.rb +2 -3
  26. data/lib/brief/util.rb +4 -4
  27. data/lib/brief/version.rb +1 -1
  28. data/lib/brief.rb +47 -33
  29. data/spec/fixtures/example/brief.rb +3 -0
  30. data/spec/fixtures/example/models/epic.rb +43 -5
  31. data/spec/fixtures/example/templates/user_story.md.erb +22 -0
  32. data/spec/lib/brief/briefcase_spec.rb +1 -1
  33. data/spec/lib/brief/dsl_spec.rb +1 -1
  34. data/spec/lib/brief/model_spec.rb +6 -1
  35. data/spec/lib/brief/persistence_spec.rb +1 -1
  36. data/spec/lib/brief/repository_spec.rb +1 -1
  37. data/spec/lib/brief/template_spec.rb +44 -0
  38. data/spec/spec_helper.rb +2 -2
  39. metadata +7 -2
@@ -1,15 +1,15 @@
1
1
  class Brief::Document::Section
2
2
  class Builder
3
- def self.run(source, options={})
3
+ def self.run(source, options = {})
4
4
  new(source, options).to_fragment
5
5
  end
6
6
 
7
7
  attr_accessor :source, :nodes, :low, :high
8
8
 
9
- def initialize(source, options={})
9
+ def initialize(source, options = {})
10
10
  @source = source.map do |item|
11
11
  level, group = item
12
- [level, group.map {|f| f.is_a?(String) ? Nokogiri::HTML.fragment(f) : f }]
12
+ [level, group.map { |f| f.is_a?(String) ? Nokogiri::HTML.fragment(f) : f }]
13
13
  end
14
14
 
15
15
  @low = options.fetch(:low, 1)
@@ -28,7 +28,7 @@ class Brief::Document::Section
28
28
  next_level, next_fragments = source[n]
29
29
 
30
30
  if next_level && (next_level == level) && (level > low)
31
- new_fragment = (fragments + next_fragments).map(&:to_html).join("")
31
+ new_fragment = (fragments + next_fragments).map(&:to_html).join('')
32
32
  source[index] = [level, [Nokogiri::HTML.fragment(new_fragment)]]
33
33
  source[n] = nil
34
34
  end
@@ -49,7 +49,7 @@ class Brief::Document::Section
49
49
  next_level, next_fragment = source[n]
50
50
 
51
51
  if fragment && next_level && (next_level > level)
52
- parent = fragment.css("section, article").first
52
+ parent = fragment.css('section, article').first
53
53
  parent.add_child(next_fragment)
54
54
  source[index] = [level, fragment]
55
55
  source[n] = nil
@@ -63,14 +63,14 @@ class Brief::Document::Section
63
63
 
64
64
  self.nodes = source.map(&:last)
65
65
 
66
- self.nodes.each do |node|
67
- parent = node.css("section, article").first
66
+ nodes.each do |node|
67
+ parent = node.css('section, article').first
68
68
  if %w(h1 h2 h3 h4 h5 h6).include?(parent.children.first.name)
69
69
  parent['data-heading'] = parent.children.first.text
70
70
  end
71
71
  end
72
72
 
73
- self.nodes.map!(&:to_html)
73
+ nodes.map!(&:to_html)
74
74
  end
75
75
 
76
76
  def maxed_out?
@@ -82,8 +82,8 @@ class Brief::Document::Section
82
82
  end
83
83
 
84
84
  def to_fragment
85
- @html = nodes.join("") unless nodes.empty?
86
- Nokogiri::HTML.fragment(@html || "<div/>")
85
+ @html = nodes.join('') unless nodes.empty?
86
+ Nokogiri::HTML.fragment(@html || '<div/>')
87
87
  end
88
88
  end
89
89
  end
@@ -1,6 +1,6 @@
1
1
  class Brief::Document::Section
2
2
  class Mapping
3
- def initialize(title, options={})
3
+ def initialize(title, options = {})
4
4
  @title = title
5
5
  @options = options
6
6
  @config = {}.to_mash
@@ -14,23 +14,17 @@ class Brief::Document::Section
14
14
  config.selectors
15
15
  end
16
16
 
17
- def config
18
- @config
19
- end
17
+ attr_reader :config
20
18
 
21
- def options
22
- @options
23
- end
19
+ attr_reader :options
24
20
 
25
- def title
26
- @title
27
- end
21
+ attr_reader :title
28
22
 
29
23
  def selector
30
24
  @selector || :next
31
25
  end
32
26
 
33
- def each(*args, &block)
27
+ def each(*args, &_block)
34
28
  @selector = args.first
35
29
  self
36
30
  end
@@ -19,10 +19,10 @@ class Brief::Document::Section
19
19
  settings = config.selector_config[selector]
20
20
 
21
21
  if Headings.include?(selector)
22
- headings = fragment.css("article > h2")
22
+ headings = fragment.css('article > h2')
23
23
  articles = headings.map(&:parent)
24
24
 
25
- if !settings.empty?
25
+ unless settings.empty?
26
26
  articles.compact.each do |article|
27
27
  data.push(settings.inject({}.to_mash) do |memo, pair|
28
28
  attribute, selector = pair
@@ -38,4 +38,3 @@ class Brief::Document::Section
38
38
  @items = data
39
39
  end
40
40
  end
41
-
@@ -2,7 +2,7 @@ module Brief
2
2
  class Document::Structure
3
3
  attr_accessor :fragment, :content_lines
4
4
 
5
- def initialize(fragment,content_lines=[])
5
+ def initialize(fragment, content_lines = [])
6
6
  @fragment = fragment
7
7
  @content_lines = content_lines
8
8
  end
@@ -12,7 +12,7 @@ module Brief
12
12
  if line.match(/^#/)
13
13
  line = line.strip
14
14
  level = line.count('#')
15
- text = line.gsub('#','').strip
15
+ text = line.gsub('#', '').strip
16
16
 
17
17
  if level > 0 && text.length > 0
18
18
  line_number = index + 1
@@ -55,16 +55,16 @@ module Brief
55
55
 
56
56
  mapping.map! do |item|
57
57
  level, group = item
58
- group.reject! {|i| i.text == "\n" }
58
+ group.reject! { |i| i.text == "\n" }
59
59
 
60
60
  if level == 0
61
- base_fragment = fragment = Nokogiri::HTML.fragment("<div class='brief top level'>#{ group.map(&:to_html).join("") }</div>")
61
+ base_fragment = fragment = Nokogiri::HTML.fragment("<div class='brief top level'>#{ group.map(&:to_html).join('') }</div>")
62
62
  elsif level <= lowest_level
63
- fragment = Nokogiri::HTML.fragment("<section>#{ group.map(&:to_html).join("") }</section>")
63
+ fragment = Nokogiri::HTML.fragment("<section>#{ group.map(&:to_html).join('') }</section>")
64
64
  elsif level > lowest_level
65
65
  # should be able to look at the document section mappings and
66
66
  # apply custom css classes to these based on the name of the section
67
- fragment = Nokogiri::HTML.fragment("<article>#{ group.map(&:to_html).join("") }</article>")
67
+ fragment = Nokogiri::HTML.fragment("<article>#{ group.map(&:to_html).join('') }</article>")
68
68
  end
69
69
 
70
70
  [level, [fragment]]
@@ -74,9 +74,9 @@ module Brief
74
74
  end
75
75
 
76
76
  def levels
77
- l = fragment.css("[data-level]").map {|el| el.attr('data-level').to_i }
77
+ l = fragment.css('[data-level]').map { |el| el.attr('data-level').to_i }
78
78
  l.reject!(&:nil?)
79
- l.reject! {|v| v.to_i == 0 }
79
+ l.reject! { |v| v.to_i == 0 }
80
80
  l.uniq!
81
81
  l
82
82
  end
@@ -89,8 +89,8 @@ module Brief
89
89
  levels.min
90
90
  end
91
91
 
92
- def headings_at_level(level, options={})
93
- matches = heading_elements.select {|el| el.level.to_i == level.to_i }
92
+ def headings_at_level(level, options = {})
93
+ matches = heading_elements.select { |el| el.level.to_i == level.to_i }
94
94
 
95
95
  if options[:text]
96
96
  matches.map(&:text)
@@ -101,9 +101,8 @@ module Brief
101
101
 
102
102
  def heading_with_text(text)
103
103
  headings_with_text(text).tap do |results|
104
- raise 'no section found with content: ' + text if results.length == 0
105
- raise 'more than one section found with content: ' + text if results.length >= 2
106
-
104
+ fail 'no section found with content: ' + text if results.length == 0
105
+ fail 'more than one section found with content: ' + text if results.length >= 2
107
106
  end.first
108
107
  end
109
108
 
@@ -120,7 +119,7 @@ module Brief
120
119
  end
121
120
 
122
121
  def heading_elements
123
- @heading_elements ||= fragment.css("h1,h2,h3,h4,h5,h6").map do |el|
122
+ @heading_elements ||= fragment.css('h1,h2,h3,h4,h5,h6').map do |el|
124
123
  if el.attr('data-level').to_i > 0
125
124
  {
126
125
  level: el.attr('data-level'),
@@ -138,7 +137,7 @@ module Brief
138
137
  end
139
138
 
140
139
  def level(element)
141
- element.name.to_s.gsub(/^h/i,'').to_i
140
+ element.name.to_s.gsub(/^h/i, '').to_i
142
141
  end
143
142
  end
144
143
  end
@@ -0,0 +1,14 @@
1
+ module Brief::Document::Templating
2
+ extend ActiveSupport::Concern
3
+
4
+ def generate_content
5
+ model_class.generate_template_content_from(@frontmatter)
6
+ end
7
+
8
+ module ClassMethods
9
+ def create_from_data(data = {})
10
+ data = data.to_mash if data.is_a?(Hash)
11
+ new(data)
12
+ end
13
+ end
14
+ end
@@ -2,19 +2,27 @@ module Brief
2
2
  class Document
3
3
  include Brief::Document::Rendering
4
4
  include Brief::Document::FrontMatter
5
+ include Brief::Document::Templating
5
6
 
6
7
  attr_accessor :path, :content, :frontmatter, :raw_content
7
8
 
8
- def initialize(path, options={})
9
- @path = Pathname(path)
10
- @options = options
9
+ def initialize(path, options = {})
10
+ if path.respond_to?(:key?) && options.empty?
11
+ @frontmatter = path.to_mash
12
+ else
13
+ @path = Pathname(path)
14
+ end
15
+
16
+ @options = options.to_mash
11
17
 
12
- if self.path.exist?
18
+ if @path && self.path.exist?
13
19
  @raw_content = path.read
14
20
  load_frontmatter
21
+ elsif options[:contents]
22
+ @raw_content = options[:contents]
15
23
  end
16
24
 
17
- self.model_class.try(:models).try(:<<, to_model) unless model_instance_registered?
25
+ model_class.try(:models).try(:<<, to_model) unless model_instance_registered?
18
26
  end
19
27
 
20
28
  def data
@@ -34,6 +42,10 @@ module Brief
34
42
  @sections
35
43
  end
36
44
 
45
+ def content
46
+ @content || generate_content
47
+ end
48
+
37
49
  # Shortcut for querying the rendered HTML by css selectors.
38
50
  #
39
51
  # This will allow for model data attributes to be pulled from the
@@ -87,8 +99,8 @@ module Brief
87
99
  # and ensures that there is a 1-1 relationship between a document path
88
100
  # and the model.
89
101
  def model_instance_registered?
90
- self.model_class && self.model_class.models.any? do |model|
91
- model.path == self.path
102
+ model_class && model_class.models.any? do |model|
103
+ model.path == path
92
104
  end
93
105
  end
94
106
 
@@ -97,7 +109,7 @@ module Brief
97
109
  end
98
110
 
99
111
  def structure
100
- @structure_analyzer ||= Brief::Document::Structure.new(fragment, self.raw_content.lines.to_a)
112
+ @structure_analyzer ||= Brief::Document::Structure.new(fragment, raw_content.lines.to_a)
101
113
  end
102
114
 
103
115
  def parser
@@ -120,4 +132,3 @@ module Brief
120
132
  end
121
133
  end
122
134
  end
123
-
@@ -20,7 +20,7 @@ module Brief::DocumentMapper
20
20
 
21
21
  def initialize(opts = {})
22
22
  unless Brief::DocumentMapper::VALID_OPERATORS.include?(opts[:operator])
23
- raise 'Operator not supported'
23
+ fail 'Operator not supported'
24
24
  end
25
25
 
26
26
  @attribute, @operator = opts[:attribute], opts[:operator]
@@ -36,18 +36,18 @@ module Brief::DocumentMapper
36
36
  end
37
37
 
38
38
  def where(constraints_hash)
39
- selector_hash = constraints_hash.reject { |key, value| !key.is_a? Selector }
40
- symbol_hash = constraints_hash.reject { |key, value| key.is_a? Selector }
39
+ selector_hash = constraints_hash.reject { |key, _value| !key.is_a? Selector }
40
+ symbol_hash = constraints_hash.reject { |key, _value| key.is_a? Selector }
41
41
  symbol_hash.each do |attribute, value|
42
- selector = Selector.new(:attribute => attribute, :operator => 'equal')
43
- selector_hash.update({ selector => value })
42
+ selector = Selector.new(attribute: attribute, operator: 'equal')
43
+ selector_hash.update(selector => value)
44
44
  end
45
45
  @where.merge! selector_hash
46
46
  self
47
47
  end
48
48
 
49
49
  def order_by(field)
50
- @order_by = field.is_a?(Symbol) ? {field => :asc} : field
50
+ @order_by = field.is_a?(Symbol) ? { field => :asc } : field
51
51
  self
52
52
  end
53
53
 
@@ -62,11 +62,11 @@ module Brief::DocumentMapper
62
62
  end
63
63
 
64
64
  def first
65
- self.all.first
65
+ all.first
66
66
  end
67
67
 
68
68
  def last
69
- self.all.last
69
+ all.last
70
70
  end
71
71
 
72
72
  def run_query
@@ -129,7 +129,7 @@ module Brief::DocumentMapper
129
129
  end
130
130
 
131
131
  def inspect
132
- "Query: #{ @where.map {|k,v| "#{k.attribute} #{k.operator} #{v}" }}"
132
+ "Query: #{ @where.map { |k, v| "#{k.attribute} #{k.operator} #{v}" }}"
133
133
  end
134
134
 
135
135
  def method_missing(meth, *args, &block)
@@ -153,7 +153,7 @@ class Symbol
153
153
 
154
154
  unless method_defined?(:"<=>")
155
155
  def <=>(other)
156
- self.to_s <=> other.to_s
156
+ to_s <=> other.to_s
157
157
  end
158
158
  end
159
159
  end
data/lib/brief/dsl.rb CHANGED
@@ -2,8 +2,7 @@ module Brief
2
2
  module DSL
3
3
  extend ActiveSupport::Concern
4
4
 
5
- def config(options={}, &block)
6
- Brief::Configuration.instance.load_options(options) unless options.nil? || options.empty?
5
+ def config(options = {}, &block)
7
6
  Brief::Configuration.instance.instance_eval(&block) if block_given?
8
7
  end
9
8
 
@@ -23,7 +22,7 @@ module Brief
23
22
  #
24
23
  # this will find all of the Post models from the documents matching PATH_GLOB
25
24
  # and call the publish method on them
26
- def action(identifier, options={}, &block)
25
+ def action(identifier, _options = {}, &block)
27
26
  Object.class.class_eval do
28
27
  command "#{identifier}" do |c|
29
28
  c.syntax = "brief #{identifier}"
@@ -32,16 +31,16 @@ module Brief
32
31
  c.action do |args, opts|
33
32
  briefcase = Brief.case
34
33
 
35
- path_args = args.select {|arg| arg.is_a?(String) && arg.match(/\.md$/) }
34
+ path_args = args.select { |arg| arg.is_a?(String) && arg.match(/\.md$/) }
36
35
 
37
36
  path_args.select! do |arg|
38
37
  path = briefcase.repository.root.join(arg)
39
38
  path.exist?
40
39
  end
41
40
 
42
- path_args.map! {|p| briefcase.repository.root.join(p) }
41
+ path_args.map! { |p| briefcase.repository.root.join(p) }
43
42
 
44
- models = path_args.map {|path| Brief::Document.new(path) }.map(&:to_model)
43
+ models = path_args.map { |path| Brief::Document.new(path) }.map(&:to_model)
45
44
 
46
45
  block.call(Brief.case, models, opts)
47
46
  end
@@ -6,15 +6,17 @@ module Brief
6
6
  :content_schema,
7
7
  :options,
8
8
  :defined_helpers,
9
- :section_mappings
9
+ :section_mappings,
10
+ :template_body,
11
+ :example_body
10
12
 
11
- def initialize(name, options={})
13
+ def initialize(name, options = {})
12
14
  @name = name
13
15
  @options = options
14
- @type_alias = options.fetch(:type_alias) { name.downcase.parameterize.gsub(/-/,'_') }
16
+ @type_alias = options.fetch(:type_alias) { name.downcase.parameterize.gsub(/-/, '_') }
15
17
  @metadata_schema = {}.to_mash
16
18
  @section_mappings = {}.to_mash
17
- @content_schema = {attributes:{}}.to_mash
19
+ @content_schema = { attributes: {} }.to_mash
18
20
  @model_class = options[:model_class]
19
21
  end
20
22
 
@@ -44,13 +46,19 @@ module Brief
44
46
  def apply_config
45
47
  # define a virtus attribute mapping
46
48
  metadata_schema.values.each do |settings|
47
- model_class.send(:attribute, *(settings[:args]))
49
+ begin
50
+ settings[:args] = Array(settings[:args])
51
+ settings[:args][1] = String if settings[:args][1] == ''
52
+ model_class.send(:attribute, *(settings[:args]))
53
+ rescue => e
54
+ raise "Error in metadata schema definition.\n #{ settings.inspect } \n\n #{e.message}"
55
+ end
48
56
  end
49
57
 
50
58
  # defined helpers adds an anonymous module include
51
- Array(self.defined_helpers).each {|mod| model_class.send(:include, mod) }
59
+ Array(defined_helpers).each { |mod| model_class.send(:include, mod) }
52
60
 
53
- model_class.defined_actions += Array(self.defined_actions)
61
+ model_class.defined_actions += Array(defined_actions)
54
62
  true
55
63
  end
56
64
 
@@ -61,23 +69,39 @@ module Brief
61
69
  end
62
70
 
63
71
  def model_class
64
- @model_class || model_namespace.const_get(type_alias.camelize) rescue nil
72
+ @model_class || model_namespace.const_get(type_alias.camelize) rescue Brief.default_model_class
65
73
  end
66
74
 
67
75
  def model_namespace
68
76
  Brief.configuration.model_namespace || Brief::Model
69
77
  end
70
78
 
71
- def meta(options={}, &block)
79
+ def meta(_options = {}, &block)
72
80
  @current = :meta
73
81
  instance_eval(&block)
74
82
  end
75
83
 
76
- def content(options={}, &block)
84
+ def content(_options = {}, &block)
77
85
  @current = :content
78
86
  instance_eval(&block)
79
87
  end
80
88
 
89
+ def example(body = nil, _options = {})
90
+ if body.is_a?(Hash)
91
+ options = body
92
+ elsif body.is_a?(String)
93
+ self.example_body = body
94
+ end
95
+ end
96
+
97
+ def template(body = nil, _options = {})
98
+ if body.is_a?(Hash)
99
+ options = body
100
+ elsif body.is_a?(String)
101
+ self.template_body = body
102
+ end
103
+ end
104
+
81
105
  def has_actions?
82
106
  !@defined_actions.empty?
83
107
  end
@@ -120,17 +144,17 @@ module Brief
120
144
  if meth.to_sym == :define_section
121
145
  opts = args.extract_options!
122
146
  identifier = args.first
123
- self.section_mappings[identifier] ||= Brief::Document::Section::Mapping.new(identifier, opts)
147
+ section_mappings[identifier] ||= Brief::Document::Section::Mapping.new(identifier, opts)
124
148
  section_mapping(identifier).instance_eval(&block) if block
125
149
  else
126
- self.content_schema.attributes[meth] = {args: args, block: block}
150
+ content_schema.attributes[meth] = { args: args, block: block }
127
151
  end
128
152
  elsif inside_meta?
129
153
  if args.first.is_a?(Hash)
130
154
  args.unshift(String)
131
155
  end
132
156
  args.unshift(meth)
133
- self.metadata_schema[meth] = {args: args, block: block}
157
+ metadata_schema[meth] = { args: args, block: block }
134
158
  else
135
159
  super
136
160
  end
@@ -1,7 +1,5 @@
1
1
  module Brief
2
2
  module Model::Persistence
3
3
  extend ActiveSupport::Concern
4
-
5
-
6
4
  end
7
5
  end
data/lib/brief/model.rb CHANGED
@@ -15,8 +15,8 @@ module Brief
15
15
 
16
16
  class_attribute :models, :after_initialization_hooks, :defined_actions
17
17
 
18
- self.models = Array(self.models).to_set
19
- self.defined_actions = Array(self.defined_actions).to_set
18
+ self.models = Array(models).to_set
19
+ self.defined_actions = Array(defined_actions).to_set
20
20
 
21
21
  class << self
22
22
  include Enumerable
@@ -68,16 +68,24 @@ module Brief
68
68
  table[type_alias]
69
69
  end
70
70
 
71
+ def self.lookup_class_from_args(args = [])
72
+ args = Array(args)
73
+
74
+ if model_class = for_type(args.first)
75
+ model_class
76
+ end
77
+ end
78
+
71
79
  def self.finalize
72
80
  Virtus.finalize
73
81
  classes.each(&:finalize)
74
82
  end
75
83
 
76
84
  def ==(other)
77
- self.path == other.path
85
+ path == other.path
78
86
  end
79
87
 
80
- def extract_content(options={})
88
+ def extract_content(options = {})
81
89
  document.extract_content(options)
82
90
  end
83
91
 
@@ -90,7 +98,7 @@ module Brief
90
98
  klass = self
91
99
 
92
100
  klass.name ||= klass.to_s.split('::').last.humanize
93
- klass.type_alias ||= klass.name.parameterize.gsub(/-/,'_')
101
+ klass.type_alias ||= klass.name.parameterize.gsub(/-/, '_')
94
102
 
95
103
  klass.attribute_set.map(&:name).each do |attr|
96
104
  unless klass.method_defined?("find_by_#{ attr }")
@@ -105,39 +113,35 @@ module Brief
105
113
  Brief::Repository.define_document_finder_methods
106
114
  end
107
115
 
108
- def where(*args, &block)
116
+ def where(*args, &_block)
109
117
  Brief::DocumentMapper::Query.new(self).send(:where, *args)
110
118
  end
111
119
 
112
120
  def each(*args, &block)
113
- Array(self.models).send(:each, *args, &block)
121
+ Array(models).send(:each, *args, &block)
114
122
  end
115
123
 
116
124
  def after_initialize(&block)
117
125
  (self.after_initialization_hooks ||= []).push(block)
118
126
  end
119
127
 
120
- def name=(value)
121
- @name = value
122
- end
128
+ attr_writer :name
123
129
 
124
130
  def name
125
- @name || to_s.split('::').last.underscore.gsub('_',' ').titlecase
131
+ @name || to_s.split('::').last.underscore.gsub('_', ' ').titlecase
126
132
  end
127
133
 
128
- def type_alias=(value)
129
- @type_alias = value
130
- end
134
+ attr_writer :type_alias
131
135
 
132
136
  def type_alias
133
- @type_alias || name.parameterize.gsub(/-/,'_')
137
+ @type_alias || name.parameterize.gsub(/-/, '_')
134
138
  end
135
139
 
136
140
  def definition
137
141
  @definition ||= Brief::Model::Definition.new(name, type_alias: type_alias, model_class: self)
138
142
  end
139
143
 
140
- def definition=(value)
144
+ def definition=(_value)
141
145
  @definition
142
146
  end
143
147
 
@@ -149,18 +153,43 @@ module Brief
149
153
  definition.send(:section_mappings, *args)
150
154
  end
151
155
 
156
+ def generate_template_content_from(object, include_frontmatter = true)
157
+ @erb ||= ERB.new(template_body)
158
+ content = @erb.result(binding)
159
+ frontmatter = object.slice(*attribute_names)
160
+
161
+ base = ''
162
+ base += frontmatter.to_hash.to_yaml + "---\n" if include_frontmatter
163
+ base += content
164
+
165
+ base
166
+ end
167
+
168
+ def attribute_names
169
+ attribute_set.map(&:name)
170
+ end
171
+
172
+ def template_body(*args)
173
+ res = definition.send(:template_body, *args)
174
+ res.to_s.length == 0 ? example_body : res.to_s.strip
175
+ end
176
+
177
+ def example_body(*args)
178
+ definition.send(:example_body, *args).to_s.strip
179
+ end
180
+
152
181
  def method_missing(meth, *args, &block)
153
- if %w(meta content actions helpers).include?(meth.to_s)
182
+ if %w(meta content template example actions helpers).include?(meth.to_s)
154
183
  definition.send(meth, *args, &block)
155
184
  finalize
156
185
  elsif meth.to_s.match(/^on_(.*)_change$/)
157
- create_change_handler($1, *args, &block)
186
+ create_change_handler(Regexp.last_match[1], *args, &block)
158
187
  else
159
188
  super
160
189
  end
161
190
  end
162
191
 
163
- def create_change_handler(attribute, *args, &block)
192
+ def create_change_handler(_attribute, *_args, &block)
164
193
  block.call(self)
165
194
  end
166
195
  end
@@ -178,8 +207,8 @@ module Brief
178
207
  end
179
208
  end
180
209
 
181
- def set_slug_from(column=:name)
182
- self.slug = send(column).to_s.downcase.parameterize if self.slug.to_s.length == 0
210
+ def set_slug_from(column = :name)
211
+ self.slug = send(column).to_s.downcase.parameterize if slug.to_s.length == 0
183
212
  end
184
213
  end
185
214
  end
@@ -9,7 +9,7 @@ module Brief
9
9
  documents.send(:each, *args, &block)
10
10
  end
11
11
 
12
- def initialize(briefcase, options={})
12
+ def initialize(briefcase, options = {})
13
13
  @briefcase = briefcase
14
14
  @options = options
15
15
 
@@ -40,7 +40,7 @@ module Brief
40
40
  end
41
41
 
42
42
  def document_paths
43
- Dir[root.join("**/*.md").to_s].map {|p| Pathname(p) }
43
+ Dir[root.join('**/*.md').to_s].map { |p| Pathname(p) }
44
44
  end
45
45
 
46
46
  def self.define_document_finder_methods
@@ -52,6 +52,5 @@ module Brief
52
52
  end
53
53
  end
54
54
  end
55
-
56
55
  end
57
56
  end