brief 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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