mint 0.5.1 → 0.7.1

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 (50) hide show
  1. data/Gemfile +18 -0
  2. data/README.md +3 -3
  3. data/bin/mint +27 -27
  4. data/bin/mint-epub +6 -6
  5. data/config/syntax.yaml +12 -12
  6. data/{templates → config/templates}/base/style.sass +11 -4
  7. data/config/templates/default/css/style.css +158 -0
  8. data/config/templates/default/layout.haml +8 -0
  9. data/{templates → config/templates}/default/style.sass +0 -0
  10. data/{templates/default → config/templates/protocol}/layout.haml +0 -0
  11. data/config/templates/protocol/style.sass +20 -0
  12. data/config/templates/reset.css +92 -0
  13. data/config/templates/zen/css/style.css +145 -0
  14. data/{templates/pro → config/templates/zen}/layout.haml +0 -0
  15. data/config/templates/zen/style.sass +24 -0
  16. data/features/config.feature +21 -0
  17. data/features/publish.feature +3 -3
  18. data/features/support/env.rb +9 -27
  19. data/features/templates.feature +79 -0
  20. data/lib/mint.rb +11 -11
  21. data/lib/mint/{commandline.rb → command_line.rb} +96 -80
  22. data/lib/mint/css.rb +43 -34
  23. data/lib/mint/document.rb +99 -93
  24. data/lib/mint/helpers.rb +21 -17
  25. data/lib/mint/layout.rb +1 -1
  26. data/lib/mint/mint.rb +92 -36
  27. data/lib/mint/plugin.rb +5 -5
  28. data/lib/mint/plugins/epub.rb +51 -51
  29. data/lib/mint/resource.rb +2 -2
  30. data/lib/mint/style.rb +2 -2
  31. data/lib/mint/version.rb +1 -1
  32. data/spec/command_line_spec.rb +87 -0
  33. data/spec/css_spec.rb +46 -0
  34. data/spec/document_spec.rb +38 -40
  35. data/spec/helpers_spec.rb +101 -83
  36. data/spec/layout_spec.rb +1 -1
  37. data/spec/mint_spec.rb +184 -60
  38. data/spec/plugin_spec.rb +61 -67
  39. data/spec/plugins/epub_spec.rb +47 -47
  40. data/spec/resource_spec.rb +9 -9
  41. data/spec/spec_helper.rb +20 -93
  42. data/spec/style_spec.rb +6 -8
  43. data/spec/support/fixtures/content.md +16 -0
  44. data/spec/support/fixtures/dynamic.sass +3 -0
  45. data/spec/support/fixtures/layout.haml +3 -0
  46. data/spec/support/fixtures/static.css +3 -0
  47. data/spec/support/matchers.rb +15 -0
  48. metadata +160 -70
  49. data/spec/commandline_spec.rb +0 -91
  50. data/templates/pro/style.sass +0 -0
data/lib/mint.rb CHANGED
@@ -1,11 +1,11 @@
1
- require 'mint/helpers'
2
- require 'mint/mint'
3
- require 'mint/resource'
4
- require 'mint/layout'
5
- require 'mint/style'
6
- require 'mint/document'
7
- require 'mint/version'
8
- require 'mint/css'
9
- require 'mint/commandline'
10
- require 'mint/exceptions'
11
- require 'mint/plugin'
1
+ require "mint/helpers"
2
+ require "mint/mint"
3
+ require "mint/resource"
4
+ require "mint/layout"
5
+ require "mint/style"
6
+ require "mint/document"
7
+ require "mint/version"
8
+ require "mint/css"
9
+ require "mint/command_line"
10
+ require "mint/exceptions"
11
+ require "mint/plugin"
@@ -1,6 +1,9 @@
1
- require 'pathname'
2
- require 'yaml'
3
- require 'optparse'
1
+ require "pathname"
2
+ require "yaml"
3
+ require "optparse"
4
+ require "fileutils"
5
+
6
+ require "active_support/core_ext/object/blank"
4
7
 
5
8
  module Mint
6
9
  module CommandLine
@@ -14,22 +17,24 @@ module Mint
14
17
  # @return [Hash] a structured set of options that the commandline
15
18
  # executable accepts
16
19
  def self.options
17
- options_file = "../../../#{Mint.files[:syntax]}"
20
+ options_file = "../../../config/#{Mint.files[:syntax]}"
18
21
  YAML.load_file File.expand_path(options_file, __FILE__)
19
22
  end
20
23
 
21
- # Yields each commandline option specified by options_metadata as
22
- # a key/value pair to a block. If the option does not take a param, the value
23
- # will be specified as true.
24
+ # Parses ARGV according to the specified or default commandline syntax
24
25
  #
25
- # @param [Hash, #[]] options_metadata a structured set of options that the executable
26
- # can use to parse commandline configuration options
27
- # @return [OptionParser] an object that will parse ARGV when called
28
- def self.parser(options_metadata=Mint::CommandLine.options)
29
- optparse = OptionParser.new do |opts|
30
- opts.banner = 'Usage: mint [command] files [options]'
31
-
32
- Helpers.symbolize_keys(options_metadata).each do |k,v|
26
+ # @param [Array] argv a list of arguments to parse
27
+ # @param [Hash] opts default parsing options (to specify syntax file)
28
+ # @return [Hash] an object that contains parsed options, remaining arguments,
29
+ # and a help message
30
+ def self.parse(argv, opts={})
31
+ opts = { syntax: options }.merge(opts)
32
+ parsed_options = {}
33
+
34
+ parser = OptionParser.new do |cli|
35
+ cli.banner = "Usage: mint [command] files [options]"
36
+
37
+ Helpers.symbolize_keys(opts[:syntax]).each do |k,v|
33
38
  has_param = v[:parameter]
34
39
 
35
40
  v[:short] = "-#{v[:short]}"
@@ -37,49 +42,20 @@ module Mint
37
42
 
38
43
  if has_param
39
44
  v[:long] << " PARAM"
40
- opts.on v[:short], v[:long], v[:description] do |p|
41
- yield k.to_sym, p
45
+ cli.on v[:short], v[:long], v[:description] do |p|
46
+ parsed_options[k.to_sym] = p
42
47
  end
43
48
  else
44
- opts.on v[:short], v[:long], v[:description] do
45
- yield k, true
49
+ cli.on v[:short], v[:long], v[:description] do
50
+ parsed_options[k.to_sym] = true
46
51
  end
47
52
  end
48
53
  end
49
54
  end
50
- end
51
-
52
- # Returns a hash of all active options specified by file (for all scopes).
53
- # That is, if you specify file as 'config.yaml', this will return the aggregate
54
- # of all config.yaml-specified options in the Mint path, where more local
55
- # members of the path take precedence over more global ones.
56
- #
57
- # @param [String] file a filename pointing to a Mint configuration file
58
- # @return [Hash] a structured set of configuration options
59
- def self.configuration(file=Mint.files[:config])
60
- return nil unless file
61
- config_file = Pathname.new file
62
-
63
- # Merge config options from all config files on the Mint path,
64
- # where more local options take precedence over more global
65
- # options
66
- configuration = Mint.path(true).map {|p| p + config_file }.
67
- select(&:exist?).
68
- map {|p| YAML.load_file p }.
69
- reverse.
70
- reduce(Mint.default_options) {|r,p| r.merge p }
71
-
72
- Helpers.symbolize_keys configuration
73
- end
74
55
 
75
- # Returns all configuration options (as specified by the aggregate
76
- # of all config files), along with opts, where opts take precedence.
77
- #
78
- # @param [Hash] additional options to add to the current configuration
79
- # @return [Hash] a structured set of configuration options with opts
80
- # overriding any options from config files
81
- def self.configuration_with(opts)
82
- configuration.merge opts
56
+ transient_argv = argv.dup
57
+ parser.parse! transient_argv
58
+ { argv: transient_argv, options: parsed_options, help: parser.help }
83
59
  end
84
60
 
85
61
  # Mint built-in commands
@@ -92,19 +68,64 @@ module Mint
92
68
  puts message
93
69
  end
94
70
 
71
+ # Install the named file as a template
72
+ #
95
73
  # @param [File] file the file to install to the appropriate Mint directory
96
74
  # @param [Hash] commandline_options a structured set of options, including
97
75
  # a scope label that the method will use to choose the appropriate
98
76
  # installation directory
99
77
  # @return [void]
100
78
  def self.install(file, commandline_options={})
101
- commandline_options[:local] = true
102
- scope = [:global, :user, :local].
79
+ opts = { scope: :local }.merge(commandline_options)
80
+ scope = [:global, :user].
103
81
  select {|e| commandline_options[e] }.
104
- first
82
+ first || :local
83
+
84
+ filename, ext = file.split "."
85
+
86
+ name = commandline_options[:template] || filename
87
+ type = Mint.css_formats.include?(ext) ? :style : :layout
88
+ destination = Mint.template_path(name, type, :scope => opts[:scope], :ext => ext)
89
+ FileUtils.mkdir_p File.expand_path("#{destination}/..")
105
90
 
106
- directory = Mint.path_for_scope(scope)
107
- FileUtils.copy file, directory
91
+ puts "reading file"
92
+ puts File.read file
93
+
94
+ if File.exist? file
95
+ FileUtils.cp file, destination
96
+ else
97
+ raise "[error] no such file"
98
+ end
99
+ end
100
+
101
+ # Uninstall the named template
102
+ #
103
+ # @param [String] name the name of the template to be uninstalled
104
+ # @param [Hash] commandline_options a structured set of options, including
105
+ # a scope label that the method will use to choose the appropriate
106
+ # installation directory
107
+ # @return [void]
108
+ def self.uninstall(name, commandline_options={})
109
+ opts = { scope: :local }.merge(commandline_options)
110
+ FileUtils.rm_r Mint.template_path(name, :all, :scope => opts[:scope])
111
+ end
112
+
113
+ # List the installed templates
114
+ #
115
+ # @return [void]
116
+ def self.templates(filter=nil, commandline_options={})
117
+ scopes = Mint::SCOPE_NAMES.select do |s|
118
+ commandline_options[s]
119
+ end.presence || Mint::SCOPE_NAMES
120
+
121
+ Mint.templates(:scopes => scopes).
122
+ grep(Regexp.new(filter || "")).
123
+ sort.
124
+ each do |template|
125
+ print File.basename template
126
+ print " [#{template}]" if commandline_options[:verbose]
127
+ puts
128
+ end
108
129
  end
109
130
 
110
131
  # Retrieve named template file (probably a built-in or installed
@@ -115,21 +136,25 @@ module Mint
115
136
  # a layout or style flag that the method will use to choose the appropriate
116
137
  # file to edit
117
138
  # @return [void]
118
- def self.edit(name, commandline_options)
139
+ def self.edit(name, commandline_options={})
119
140
  layout = commandline_options[:layout]
120
141
  style = commandline_options[:style]
121
142
 
122
- if layout and not style
123
- layout_or_style = :layout
124
- elsif style
125
- layout_or_style = :style
143
+ # Allow for convenient editing (edit "default" works just as well
144
+ # as edit :style => "default")
145
+ if style
146
+ name, layout_or_style = style, :style
147
+ elsif layout
148
+ name, layout_or_style = layout, :layout
126
149
  else
127
- puts optparse.help
150
+ layout_or_style = :style
128
151
  end
129
152
 
153
+ abort "[error] no template specified" if name.nil? || name.empty?
154
+
130
155
  file = Mint.lookup_template name, layout_or_style
131
156
 
132
- editor = ENV['EDITOR'] || 'vi'
157
+ editor = ENV["EDITOR"] || "vi"
133
158
  system "#{editor} #{file}"
134
159
  end
135
160
 
@@ -142,9 +167,8 @@ module Mint
142
167
  # @return [void]
143
168
  def self.configure(opts, scope=:local)
144
169
  config_directory = Mint.path_for_scope(scope, true)
145
- config_file = config_directory + Mint.files[:config]
146
- Helpers.ensure_directory config_directory
147
- Helpers.update_yaml! opts, config_file
170
+ FileUtils.mkdir_p config_directory
171
+ Helpers.update_yaml! "#{config_directory}/#{Mint.files[:defaults]}", opts
148
172
  end
149
173
 
150
174
  # Tries to set a config option (at the specified scope) per
@@ -156,7 +180,7 @@ module Mint
156
180
  # a scope label that the method will use to choose the appropriate
157
181
  # scope
158
182
  # @return [void]
159
- def self.set(key, value, commandline_options)
183
+ def self.set(key, value, commandline_options={})
160
184
  commandline_options[:local] = true
161
185
  scope = [:global, :user, :local].
162
186
  select {|e| commandline_options[e] }.
@@ -170,7 +194,7 @@ module Mint
170
194
  #
171
195
  # @return [void]
172
196
  def self.config
173
- puts YAML.dump(configuration)
197
+ puts YAML.dump(Mint.configuration)
174
198
  end
175
199
 
176
200
  # Renders and writes to file all resources described by a document.
@@ -184,18 +208,10 @@ module Mint
184
208
  # @param [Hash, #[]] commandline_options a structured set of configuration options
185
209
  # that will guide Mint.publish!
186
210
  # @return [void]
187
- def self.publish!(files, commandline_options)
188
- documents = []
189
- options = configuration_with commandline_options
190
-
191
- options[:root] ||= Dir.getwd
192
-
193
- # Eventually render_style should be replaced with file
194
- # change detection
195
- render_style = true
196
- files.each do |file|
197
- Document.new(file, options).publish! :render_style => render_style
198
- render_style = false
211
+ def self.publish!(files, commandline_options={})
212
+ options = { root: Dir.getwd }.merge(Mint.configuration_with commandline_options)
213
+ files.each_with_index do |file, idx|
214
+ Document.new(file, options).publish!(:render_style => (idx == 0))
199
215
  end
200
216
  end
201
217
  end
data/lib/mint/css.rb CHANGED
@@ -1,61 +1,70 @@
1
+ require "sass"
2
+
1
3
  module Mint
2
4
  module CSS
3
- def container
4
- 'container'
5
+ def self.container
6
+ "container"
5
7
  end
6
8
 
7
- # Maps a "DSL" onto actual CSS. This is not yet implemented, but
8
- # the plan is to translate this ...
9
+ # Maps a "DSL" onto actual CSS. Translates this ...
9
10
  #
10
11
  # ---
11
12
  # Font: Helvetica
12
- # Margin: 1 in
13
- # Line spacing: 1.25
13
+ # Margin: 1in
14
+ # Orientation: Landscape
14
15
  #
15
16
  # ... into something like:
16
17
  #
17
18
  # #container {
18
- # font: (value specified and cleaned up)
19
- # padding-left: (value specified and cleaned up)
20
- # ...
21
- # p { line-height: (value specified and cleaned up) }
19
+ # font-family: Helvetica;
20
+ # padding-left: 1in;
21
+ # @page { size: landscape };
22
22
  # }
23
- def mappings
23
+ def self.mappings
24
24
  {
25
- font: 'font',
26
- color: 'color',
27
- top_margin: 'padding-top',
28
- bottom_margin: 'padding-bottom',
29
- left_margin: 'padding-left',
30
- right_margin: 'padding-right',
31
- top: 'padding-top',
32
- bottom: 'padding-bottom',
33
- left: 'padding-left',
34
- right: 'padding-right',
35
- height: 'height',
36
- width: 'width',
37
- line_spacing: 'p { line-height: %s }',
38
- bullet: 'bullet-shape',
39
- indentation: 'text-indent',
40
- after_paragraph: 'margin-bottom',
41
- before_paragraph: 'margin-top',
42
- smart_typography: 'optimizeLegibility'
25
+ font: "font-family",
26
+ font_size: "font-size",
27
+ font_color: "color",
28
+ color: "color",
29
+ top_margin: "padding-top",
30
+ top: "padding-top",
31
+ bottom_margin: "padding-bottom",
32
+ bottom: "padding-bottom",
33
+ left_margin: "padding-left",
34
+ left: "padding-left",
35
+ right_margin: "padding-right",
36
+ right: "padding-right",
37
+ height: "height",
38
+ width: "width",
39
+ columns: "column-count",
40
+ column_gap: "column-gap",
41
+ orientation: "@page { size: %s }",
42
+ indentation: "p+p { text-indent: %s }",
43
+ indent: "p+p { text-indent: %s }",
44
+ bullet: "li { list-style-type: %s }",
45
+ bullet_image: "li { list-style-image: url(%s) }",
46
+ after_paragraph: "margin-bottom",
47
+ before_paragraph: "margin-top"
43
48
  }
44
49
  end
45
50
 
46
- def format(key, value)
51
+ def self.stylify(key, value)
47
52
  selector = mappings[Helpers.symbolize key]
48
53
 
49
- if selector.include? '%'
54
+ if selector.nil?
55
+ ""
56
+ elsif selector.include? "%"
50
57
  selector % value
51
58
  else
52
59
  "#{selector || key}: #{value}"
53
60
  end
54
61
  end
55
62
 
56
- def parse(style)
57
- css = style.map {|k,v| format(k, v) }.join("\n ")
58
- "##{container} {\n #{css.strip}\n}"
63
+ def self.parse(style)
64
+ css = style.map {|k,v| stylify(k, v) }.join("\n ")
65
+ container_scope = "##{container}\n #{css.strip}\n"
66
+ engine = Sass::Engine.new(container_scope)
67
+ engine.silence_sass_warnings { engine.render }
59
68
  end
60
69
  end
61
70
  end
data/lib/mint/document.rb CHANGED
@@ -1,15 +1,69 @@
1
- require 'mint/resource'
2
- require 'mint/layout'
3
- require 'mint/style'
1
+ require "mint/resource"
2
+ require "mint/layout"
3
+ require "mint/style"
4
4
 
5
5
  module Mint
6
6
  class Document < Resource
7
7
  METADATA_DELIM = "\n\n"
8
8
 
9
+ # Creates a new Mint Document object. Can be block initialized.
10
+ # Accepts source and options. Block initialization occurs after
11
+ # all defaults are set, so not all options must be specified.
12
+ def initialize(source, opts={})
13
+ options = Mint.default_options.merge opts
14
+
15
+ # Loads source and destination, which will be used for
16
+ # all source_* and destination_* virtual attributes.
17
+ super(source, options)
18
+ self.type = :document
19
+
20
+ # Each of these should invoke explicitly defined method
21
+ self.content = source
22
+ self.layout = options[:layout]
23
+ self.style = options[:style]
24
+ self.style_destination = options[:style_destination]
25
+
26
+ # The template option will override layout and style choices
27
+ self.template = options[:template]
28
+
29
+ # Yield self to block after all other parameters are loaded,
30
+ # so we only have to tweak. (We don't have to give up our
31
+ # defaults or re-test blocks beyond them being tweaked.)
32
+ yield self if block_given?
33
+ end
34
+
35
+ # Renders content in the context of layout and returns as a String.
36
+ def render(args={})
37
+ intermediate_content = layout.render self, args
38
+ Mint.after_render(intermediate_content)
39
+ end
40
+
41
+ # Writes all rendered content where a) possible, b) required,
42
+ # and c) specified. Outputs to specified file.
43
+ def publish!(opts={})
44
+ options = { :render_style => true }.merge(opts)
45
+ FileUtils.mkdir_p self.destination_directory
46
+ File.open(self.destination_file, "w+") do |f|
47
+ f << self.render
48
+ end
49
+
50
+ # Only renders style if a) it's specified by the options path and
51
+ # b) it actually needs rendering (i.e., it's in template form and
52
+ # not raw, browser-parseable CSS) or it if it doesn't need
53
+ # rendering but there is an explicit style_destination.
54
+ if options[:render_style]
55
+ FileUtils.mkdir_p style_destination_directory
56
+ File.open(self.style_destination_file, "w+") do |f|
57
+ f << self.style.render
58
+ end
59
+ end
60
+
61
+ Mint.after_publish(self, opts)
62
+ end
63
+
9
64
  # Implicit readers are paired with explicit accessors. This
10
65
  # allows for processing variables before storing them.
11
- attr_reader :content, :layout, :style
12
- attr_accessor :metadata
66
+ attr_reader :content, :metadata, :layout, :style
13
67
 
14
68
  # Passes content through a renderer before assigning it to be
15
69
  # the Document's content
@@ -21,11 +75,12 @@ module Mint
21
75
  tempfile = Helpers.generate_temp_file! content
22
76
  original_content = File.read content
23
77
 
24
- metadata, text = Document.parse_metadata_from original_content
25
- self.metadata = metadata
78
+ @metadata, text = Document.parse_metadata_from original_content
26
79
  intermediate_content = Mint.before_render text
27
80
 
28
- File.open(tempfile, 'w') {|file| file << intermediate_content }
81
+ File.open(tempfile, "w") do |file|
82
+ file << intermediate_content
83
+ end
29
84
 
30
85
  @renderer = Mint.renderer tempfile
31
86
  @content = @renderer.render
@@ -65,6 +120,17 @@ module Mint
65
120
  abort "Template '#{style}' does not exist."
66
121
  end
67
122
 
123
+ # Overrides layout and style settings with named template.
124
+ #
125
+ # @param [String] template the name of the template to set as
126
+ # layout and string
127
+ def template=(template)
128
+ if template
129
+ self.layout = template
130
+ self.style = template
131
+ end
132
+ end
133
+
68
134
  # Explanation of style_destination:
69
135
  #
70
136
  # I'm going to maintain a document's official style_destination
@@ -126,72 +192,6 @@ module Mint
126
192
  style_destination_directory_path.to_s
127
193
  end
128
194
 
129
- # Overrides layout and style settings with named template.
130
- #
131
- # @param [String] template the name of the template to set as
132
- # layout and string
133
- def template=(template)
134
- if template
135
- self.layout = template
136
- self.style = template
137
- end
138
- end
139
-
140
- # Creates a new Mint Document object. Can be block initialized.
141
- # Accepts source and options. Block initialization occurs after
142
- # all defaults are set, so not all options must be specified.
143
- def initialize(source, opts={})
144
- options = Mint.default_options.merge opts
145
-
146
- # Loads source and destination, which will be used for
147
- # all source_* and destination_* virtual attributes.
148
- super(source, options)
149
- self.type = :document
150
-
151
- # Each of these should invoke explicitly defined method
152
- self.content = source
153
- self.layout = options[:layout]
154
- self.style = options[:style]
155
- self.style_destination = options[:style_destination]
156
-
157
- # The template option will override layout and style choices
158
- self.template = options[:template]
159
-
160
- # Yield self to block after all other parameters are loaded,
161
- # so we only have to tweak. (We don't have to give up our
162
- # defaults or re-test blocks beyond them being tweaked.)
163
- yield self if block_given?
164
- end
165
-
166
- # Renders content in the context of layout and returns as a String.
167
- def render(args={})
168
- intermediate_content = layout.render self, args
169
- Mint.after_render(intermediate_content)
170
- end
171
-
172
- # Writes all rendered content where a) possible, b) required,
173
- # and c) specified. Outputs to specified file.
174
- def publish!(opts={})
175
- options = { :render_style => true }.merge(opts)
176
- FileUtils.mkdir_p self.destination_directory
177
- File.open(self.destination_file, 'w+') do |f|
178
- f << self.render
179
- end
180
-
181
- # Only renders style if a) it's specified by the options path and
182
- # b) it actually needs rendering (i.e., it's in template form and
183
- # not raw, browser-parseable CSS) or it if it doesn't need
184
- # rendering but there is an explicit style_destination.
185
- if options[:render_style]
186
- FileUtils.mkdir_p style_destination_directory
187
- File.open(self.style_destination_file, 'w+') do |f|
188
- f << self.style.render
189
- end
190
- end
191
-
192
- Mint.after_publish(self, opts)
193
- end
194
-
195
195
  # Convenience methods for views
196
196
 
197
197
  # Returns a relative path from the document to its stylesheet. Can
@@ -201,29 +201,35 @@ module Mint
201
201
  self.destination_directory).to_s
202
202
  end
203
203
 
204
- protected
205
-
206
- def self.metadata_chunk(text)
207
- text.split(METADATA_DELIM).first
204
+ def inline_styles
205
+ CSS.parse(metadata)
208
206
  end
209
207
 
210
- def self.metadata_from(text)
211
- raw_metadata = YAML.load metadata_chunk(text)
212
- raw_metadata.is_a?(String) ? {} : raw_metadata
213
- rescue
214
- {}
215
- end
208
+ # Functions
216
209
 
217
- def self.parse_metadata_from(text)
218
- metadata = metadata_from text
219
- new_text =
220
- if !metadata.empty?
221
- text.sub metadata_chunk(text) + METADATA_DELIM, ''
222
- else
223
- text
224
- end
210
+ class << self
211
+ def metadata_chunk(text)
212
+ text.split(METADATA_DELIM).first
213
+ end
225
214
 
226
- [metadata, new_text]
215
+ def metadata_from(text)
216
+ raw_metadata = YAML.load metadata_chunk(text)
217
+ raw_metadata.is_a?(String) ? {} : raw_metadata
218
+ rescue
219
+ {}
220
+ end
221
+
222
+ def parse_metadata_from(text)
223
+ metadata = metadata_from text
224
+ new_text =
225
+ if !metadata.empty?
226
+ text.sub metadata_chunk(text) + METADATA_DELIM, ""
227
+ else
228
+ text
229
+ end
230
+
231
+ [metadata, new_text]
232
+ end
227
233
  end
228
234
  end
229
235
  end