jekyll 2.0.3 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of jekyll might be problematic. Click here for more details.

Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -2
  3. data/CONTRIBUTING.markdown +2 -2
  4. data/History.markdown +86 -0
  5. data/README.markdown +5 -30
  6. data/Rakefile +4 -9
  7. data/docs/jp/CONTRIBUTING.jp.markdown +2 -2
  8. data/docs/jp/README.jp.markdown +1 -2
  9. data/features/collections.feature +40 -3
  10. data/features/data.feature +41 -1
  11. data/features/frontmatter_defaults.feature +57 -0
  12. data/features/post_data.feature +12 -0
  13. data/features/rendering.feature +34 -0
  14. data/features/step_definitions/jekyll_steps.rb +5 -1
  15. data/features/support/env.rb +0 -3
  16. data/jekyll.gemspec +6 -5
  17. data/lib/jekyll.rb +18 -1
  18. data/lib/jekyll/cleaner.rb +22 -2
  19. data/lib/jekyll/collection.rb +9 -2
  20. data/lib/jekyll/command.rb +20 -10
  21. data/lib/jekyll/commands/build.rb +10 -47
  22. data/lib/jekyll/commands/serve.rb +1 -0
  23. data/lib/jekyll/configuration.rb +13 -1
  24. data/lib/jekyll/converters/markdown/redcarpet_parser.rb +9 -2
  25. data/lib/jekyll/convertible.rb +31 -2
  26. data/lib/jekyll/deprecator.rb +1 -1
  27. data/lib/jekyll/document.rb +21 -3
  28. data/lib/jekyll/excerpt.rb +1 -1
  29. data/lib/jekyll/filters.rb +16 -12
  30. data/lib/jekyll/frontmatter_defaults.rb +3 -3
  31. data/lib/jekyll/log_adapter.rb +102 -0
  32. data/lib/jekyll/post.rb +5 -5
  33. data/lib/jekyll/renderer.rb +9 -5
  34. data/lib/jekyll/site.rb +38 -18
  35. data/lib/jekyll/static_file.rb +1 -0
  36. data/lib/jekyll/stevenson.rb +54 -98
  37. data/lib/jekyll/tags/highlight.rb +13 -5
  38. data/lib/jekyll/url.rb +2 -2
  39. data/lib/jekyll/utils.rb +15 -7
  40. data/lib/jekyll/version.rb +1 -1
  41. data/lib/site_template/_config.yml +2 -0
  42. data/lib/site_template/_includes/footer.html +8 -8
  43. data/lib/site_template/_includes/header.html +1 -1
  44. data/lib/site_template/css/main.css +7 -2
  45. data/lib/site_template/feed.xml +10 -1
  46. data/site/_config.yml +1 -0
  47. data/site/_data/docs.yml +1 -0
  48. data/site/_includes/anchor_links.html +28 -23
  49. data/site/_includes/css/font-awesome.css +3 -3
  50. data/site/_includes/css/style.css +4 -0
  51. data/site/_includes/news_contents.html +11 -1
  52. data/site/_includes/top.html +0 -1
  53. data/site/_layouts/default.html +1 -0
  54. data/site/_posts/2013-07-25-jekyll-1-0-4-released.markdown +1 -1
  55. data/site/_posts/2013-07-25-jekyll-1-1-2-released.markdown +1 -1
  56. data/site/_posts/2014-06-04-jekyll-stickers-1-dollar-stickermule.markdown +19 -0
  57. data/site/_posts/2014-06-28-jekyll-turns-21-i-mean-2-1-0.markdown +27 -0
  58. data/site/docs/collections.md +59 -1
  59. data/site/docs/configuration.md +91 -21
  60. data/site/docs/continuous-integration.md +177 -0
  61. data/site/docs/contributing.md +2 -2
  62. data/site/docs/datafiles.md +47 -3
  63. data/site/docs/deployment-methods.md +3 -3
  64. data/site/docs/extras.md +3 -5
  65. data/site/docs/history.md +86 -0
  66. data/site/docs/installation.md +3 -1
  67. data/site/docs/pagination.md +2 -1
  68. data/site/docs/permalinks.md +4 -4
  69. data/site/docs/plugins.md +6 -0
  70. data/site/docs/quickstart.md +0 -6
  71. data/site/docs/resources.md +1 -1
  72. data/site/docs/templates.md +1 -1
  73. data/site/docs/troubleshooting.md +1 -1
  74. data/site/docs/windows.md +2 -2
  75. data/site/fonts/FontAwesome.otf +0 -0
  76. data/site/fonts/fontawesome-webfont.eot +0 -0
  77. data/site/fonts/fontawesome-webfont.svg +469 -379
  78. data/site/fonts/fontawesome-webfont.ttf +0 -0
  79. data/site/fonts/fontawesome-webfont.woff +0 -0
  80. data/site/img/jekyll-sticker.jpg +0 -0
  81. data/test/helper.rb +0 -3
  82. data/test/source/_data/categories/dairy.yaml +6 -0
  83. data/test/source/_data/members.json +12 -0
  84. data/test/source/_methods/site/initialize.md +1 -2
  85. data/test/source/_posts/2009-01-27-no-category.textile +6 -0
  86. data/test/source/_slides/example-slide-1.html +4 -0
  87. data/test/source/_slides/example-slide-2.html +7 -0
  88. data/test/source/_with.dots/all.dots/2.4.0.md +5 -0
  89. data/test/source/_with.dots/file.with.dots.md +0 -0
  90. data/test/source/environment.html +5 -0
  91. data/test/test_cleaner.rb +77 -0
  92. data/test/test_collections.rb +52 -3
  93. data/test/test_command.rb +25 -28
  94. data/test/test_configuration.rb +10 -1
  95. data/test/test_document.rb +123 -0
  96. data/test/test_excerpt.rb +11 -0
  97. data/test/test_filters.rb +28 -2
  98. data/test/test_generated_site.rb +1 -1
  99. data/test/test_log_adapter.rb +59 -0
  100. data/test/test_post.rb +77 -0
  101. data/test/test_site.rb +51 -0
  102. data/test/test_tags.rb +11 -114
  103. data/test/test_utils.rb +2 -2
  104. metadata +76 -39
  105. data/lib/jekyll/generators/pagination.rb +0 -217
  106. data/lib/jekyll/tags/gist.rb +0 -47
  107. data/test/test_pager.rb +0 -118
@@ -19,7 +19,7 @@ module Jekyll
19
19
  def self.no_subcommand(args)
20
20
  if args.size > 0 && args.first =~ /^--/ && !%w[--help --version].include?(args.first)
21
21
  Jekyll.logger.error "Deprecation:", "Jekyll now uses subcommands instead of just \
22
- switches. Run `jekyll help' to find out more."
22
+ switches. Run `jekyll --help' to find out more."
23
23
  end
24
24
  end
25
25
 
@@ -88,11 +88,19 @@ module Jekyll
88
88
  !(asset_file? || yaml_file?)
89
89
  end
90
90
 
91
+ # Determine whether the file should be placed into layouts.
92
+ #
93
+ # Returns false if the document is either an asset file or a yaml file,
94
+ # true otherwise.
95
+ def place_in_layout?
96
+ !(asset_file? || yaml_file?)
97
+ end
98
+
91
99
  # The URL template where the document would be accessible.
92
100
  #
93
101
  # Returns the URL template for the document.
94
102
  def url_template
95
- "/:collection/:path:output_ext"
103
+ collection.url_template
96
104
  end
97
105
 
98
106
  # Construct a Hash of key-value pairs which contain a mapping between
@@ -168,6 +176,8 @@ module Jekyll
168
176
  end
169
177
 
170
178
  # Read in the file and assign the content and data based on the file contents.
179
+ # Merge the frontmatter of the file with the frontmatter default
180
+ # values
171
181
  #
172
182
  # Returns nothing.
173
183
  def read(opts = {})
@@ -175,10 +185,17 @@ module Jekyll
175
185
  @data = SafeYAML.load_file(path)
176
186
  else
177
187
  begin
188
+ defaults = @site.frontmatter_defaults.all(url, collection.label.to_sym)
189
+ unless defaults.empty?
190
+ @data = defaults
191
+ end
178
192
  @content = File.read(path, merged_file_read_opts(opts))
179
193
  if content =~ /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
180
194
  @content = $POSTMATCH
181
- @data = SafeYAML.load($1)
195
+ data_file = SafeYAML.load($1)
196
+ unless data_file.nil?
197
+ @data = Utils.deep_merge_hashes(defaults, data_file)
198
+ end
182
199
  end
183
200
  rescue SyntaxError => e
184
201
  puts "YAML Exception reading #{path}: #{e.message}"
@@ -198,7 +215,8 @@ module Jekyll
198
215
  "content" => content,
199
216
  "path" => path,
200
217
  "relative_path" => relative_path,
201
- "url" => url
218
+ "url" => url,
219
+ "collection" => collection.label
202
220
  }
203
221
  else
204
222
  data
@@ -26,7 +26,7 @@ module Jekyll
26
26
  end
27
27
 
28
28
  def to_liquid
29
- post.to_liquid(Post::EXCERPT_ATTRIBUTES_FOR_LIQUID)
29
+ post.to_liquid(post.class::EXCERPT_ATTRIBUTES_FOR_LIQUID)
30
30
  end
31
31
 
32
32
  # Fetch YAML front-matter data from related post, without layout key
@@ -193,12 +193,12 @@ module Jekyll
193
193
  # Sort an array of objects
194
194
  #
195
195
  # input - the object array
196
- # key - key within each object to filter by
196
+ # property - property within each object to filter by
197
197
  # nils ('first' | 'last') - nils appear before or after non-nil values
198
198
  #
199
199
  # Returns the filtered array of objects
200
- def sort(input, key = nil, nils = "first")
201
- if key.nil?
200
+ def sort(input, property = nil, nils = "first")
201
+ if property.nil?
202
202
  input.sort
203
203
  else
204
204
  case
@@ -207,18 +207,20 @@ module Jekyll
207
207
  when nils == "last"
208
208
  order = + 1
209
209
  else
210
- Jekyll.logger.error "Invalid nils order:",
211
- "'#{nils}' is not a valid nils order. It must be 'first' or 'last'."
212
- exit(1)
210
+ raise ArgumentError.new("Invalid nils order: " +
211
+ "'#{nils}' is not a valid nils order. It must be 'first' or 'last'.")
213
212
  end
214
213
 
215
- input.sort { |a, b|
216
- if !a[key].nil? && b[key].nil?
214
+ input.sort { |apple, orange|
215
+ apple_property = item_property(apple, property)
216
+ orange_property = item_property(orange, property)
217
+
218
+ if !apple_property.nil? && orange_property.nil?
217
219
  - order
218
- elsif a[key].nil? && !b[key].nil?
220
+ elsif apple_property.nil? && !orange_property.nil?
219
221
  + order
220
222
  else
221
- a[key] <=> b[key]
223
+ apple_property <=> orange_property
222
224
  end
223
225
  }
224
226
  end
@@ -231,7 +233,7 @@ module Jekyll
231
233
  input
232
234
  when String
233
235
  Time.parse(input) rescue Time.at(input.to_i)
234
- when Number
236
+ when Numeric
235
237
  Time.at(input)
236
238
  else
237
239
  Jekyll.logger.error "Invalid Date:", "'#{input}' is not a valid datetime."
@@ -244,7 +246,9 @@ module Jekyll
244
246
  end
245
247
 
246
248
  def item_property(item, property)
247
- if item.respond_to?(:data)
249
+ if item.respond_to?(:to_liquid)
250
+ item.to_liquid[property.to_s]
251
+ elsif item.respond_to?(:data)
248
252
  item.data[property.to_s]
249
253
  else
250
254
  item[property.to_s]
@@ -41,10 +41,10 @@ module Jekyll
41
41
  old_scope = nil
42
42
  matching_sets(path, type).each do |set|
43
43
  if has_precedence?(old_scope, set['scope'])
44
- defaults.merge! set['values']
44
+ defaults = Utils.deep_merge_hashes(defaults, set['values'])
45
45
  old_scope = set['scope']
46
46
  else
47
- defaults = set['values'].merge(defaults)
47
+ defaults = Utils.deep_merge_hashes(set['values'], defaults)
48
48
  end
49
49
  end
50
50
  defaults
@@ -145,4 +145,4 @@ module Jekyll
145
145
  end
146
146
  end
147
147
  end
148
- end
148
+ end
@@ -0,0 +1,102 @@
1
+ module Jekyll
2
+ class LogAdapter
3
+ attr_reader :writer
4
+
5
+ LOG_LEVELS = {
6
+ :debug => ::Logger::DEBUG,
7
+ :info => ::Logger::INFO,
8
+ :warn => ::Logger::WARN,
9
+ :error => ::Logger::ERROR
10
+ }
11
+
12
+ # Public: Create a new instance of Jekyll's log writer
13
+ #
14
+ # writer - Logger compatible instance
15
+ # log_level - (optional, symbol) the log level
16
+ #
17
+ # Returns nothing
18
+ def initialize(writer, level = :info)
19
+ @writer = writer
20
+ self.log_level = level
21
+ end
22
+
23
+ # Public: Set the log level on the writer
24
+ #
25
+ # level - (symbol) the log level
26
+ #
27
+ # Returns nothing
28
+ def log_level=(level)
29
+ writer.level = LOG_LEVELS.fetch(level)
30
+ end
31
+
32
+ # Public: Print a jekyll debug message
33
+ #
34
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
35
+ # message - the message detail
36
+ #
37
+ # Returns nothing
38
+ def debug(topic, message = nil)
39
+ writer.debug(message(topic, message))
40
+ end
41
+
42
+ # Public: Print a jekyll message
43
+ #
44
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
45
+ # message - the message detail
46
+ #
47
+ # Returns nothing
48
+ def info(topic, message = nil)
49
+ writer.info(message(topic, message))
50
+ end
51
+
52
+ # Public: Print a jekyll message
53
+ #
54
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
55
+ # message - the message detail
56
+ #
57
+ # Returns nothing
58
+ def warn(topic, message = nil)
59
+ writer.warn(message(topic, message))
60
+ end
61
+
62
+ # Public: Print a jekyll error message
63
+ #
64
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
65
+ # message - the message detail
66
+ #
67
+ # Returns nothing
68
+ def error(topic, message = nil)
69
+ writer.error(message(topic, message))
70
+ end
71
+
72
+ # Public: Print a Jekyll error message and immediately abort the process
73
+ #
74
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
75
+ # message - the message detail (can be omitted)
76
+ #
77
+ # Returns nothing
78
+ def abort_with(topic, message = nil)
79
+ error(topic, message)
80
+ abort
81
+ end
82
+
83
+ # Internal: Build a Jekyll topic method
84
+ #
85
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
86
+ # message - the message detail
87
+ #
88
+ # Returns the formatted message
89
+ def message(topic, message)
90
+ formatted_topic(topic) + message.to_s.gsub(/\s+/, ' ')
91
+ end
92
+
93
+ # Internal: Format the topic
94
+ #
95
+ # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
96
+ #
97
+ # Returns the formatted topic statement
98
+ def formatted_topic(topic)
99
+ "#{topic} ".rjust(20)
100
+ end
101
+ end
102
+ end
@@ -77,10 +77,10 @@ module Jekyll
77
77
  end
78
78
 
79
79
  def populate_categories
80
- if categories.empty?
81
- self.categories = Utils.pluralized_array_from_hash(data, 'category', 'categories').map {|c| c.to_s.downcase}
82
- end
83
- categories.flatten!
80
+ categories_from_data = Utils.pluralized_array_from_hash(data, 'category', 'categories')
81
+ self.categories = (
82
+ Array(categories) + categories_from_data
83
+ ).map {|c| c.to_s.downcase}.flatten.uniq
84
84
  end
85
85
 
86
86
  def populate_tags
@@ -256,7 +256,7 @@ module Jekyll
256
256
  # construct payload
257
257
  payload = Utils.deep_merge_hashes({
258
258
  "site" => { "related_posts" => related_posts(site_payload["site"]["posts"]) },
259
- "page" => to_liquid(EXCERPT_ATTRIBUTES_FOR_LIQUID)
259
+ "page" => to_liquid(self.class::EXCERPT_ATTRIBUTES_FOR_LIQUID)
260
260
  }, site_payload)
261
261
 
262
262
  if generate_excerpt?
@@ -47,11 +47,15 @@ module Jekyll
47
47
  output = render_liquid(output, payload, info)
48
48
  end
49
49
 
50
- place_in_layouts(
51
- convert(output),
52
- payload,
53
- info
54
- )
50
+ if document.place_in_layout?
51
+ place_in_layouts(
52
+ convert(output),
53
+ payload,
54
+ info
55
+ )
56
+ else
57
+ convert(output)
58
+ end
55
59
  end
56
60
 
57
61
  # Convert the given content using the converters which match this renderer's document.
@@ -196,17 +196,33 @@ module Jekyll
196
196
  # Returns nothing
197
197
  def read_data(dir)
198
198
  base = File.join(source, dir)
199
- return unless File.directory?(base) && (!safe || !File.symlink?(base))
199
+ read_data_to(base, self.data)
200
+ end
200
201
 
201
- entries = Dir.chdir(base) { Dir['*.{yaml,yml}'] }
202
- entries.delete_if { |e| File.directory?(File.join(base, e)) }
202
+ # Read and parse all yaml files under <dir> and add them to the
203
+ # <data> variable.
204
+ #
205
+ # dir - The string absolute path of the directory to read.
206
+ # data - The variable to which data will be added.
207
+ #
208
+ # Returns nothing
209
+ def read_data_to(dir, data)
210
+ return unless File.directory?(dir) && (!safe || !File.symlink?(dir))
211
+
212
+ entries = Dir.chdir(dir) do
213
+ Dir['*.{yaml,yml,json}'] + Dir['*'].select { |fn| File.directory?(fn) }
214
+ end
203
215
 
204
216
  entries.each do |entry|
205
- path = File.join(source, dir, entry)
217
+ path = File.join(dir, entry)
206
218
  next if File.symlink?(path) && safe
207
219
 
208
220
  key = sanitize_filename(File.basename(entry, '.*'))
209
- self.data[key] = SafeYAML.load_file(path)
221
+ if File.directory?(path)
222
+ read_data_to(path, data[key] = {})
223
+ else
224
+ data[key] = SafeYAML.load_file(path)
225
+ end
210
226
  end
211
227
  end
212
228
 
@@ -314,19 +330,23 @@ module Jekyll
314
330
  # "tags" - The Hash of tag values and Posts.
315
331
  # See Site#post_attr_hash for type info.
316
332
  def site_payload
317
- {"jekyll" => { "version" => Jekyll::VERSION },
318
- "site" => Utils.deep_merge_hashes(config,
319
- Utils.deep_merge_hashes(Hash[collections.map{|label, coll| [label, coll.docs]}], {
320
- "time" => time,
321
- "posts" => posts.sort { |a, b| b <=> a },
322
- "pages" => pages,
323
- "static_files" => static_files.sort { |a, b| a.relative_path <=> b.relative_path },
324
- "html_pages" => pages.reject { |page| !page.html? },
325
- "categories" => post_attr_hash('categories'),
326
- "tags" => post_attr_hash('tags'),
327
- "collections" => collections,
328
- "documents" => documents,
329
- "data" => site_data
333
+ {
334
+ "jekyll" => {
335
+ "version" => Jekyll::VERSION,
336
+ "environment" => Jekyll.env
337
+ },
338
+ "site" => Utils.deep_merge_hashes(config,
339
+ Utils.deep_merge_hashes(Hash[collections.map{|label, coll| [label, coll.docs]}], {
340
+ "time" => time,
341
+ "posts" => posts.sort { |a, b| b <=> a },
342
+ "pages" => pages,
343
+ "static_files" => static_files.sort { |a, b| a.relative_path <=> b.relative_path },
344
+ "html_pages" => pages.select { |page| page.html? || page.url.end_with?("/") },
345
+ "categories" => post_attr_hash('categories'),
346
+ "tags" => post_attr_hash('tags'),
347
+ "collections" => collections,
348
+ "documents" => documents,
349
+ "data" => site_data
330
350
  }))
331
351
  }
332
352
  end
@@ -59,6 +59,7 @@ module Jekyll
59
59
  @@mtimes[path] = mtime
60
60
 
61
61
  FileUtils.mkdir_p(File.dirname(dest_path))
62
+ FileUtils.rm(dest_path) if File.exist?(dest_path)
62
63
  FileUtils.cp(path, dest_path)
63
64
 
64
65
  true
@@ -1,102 +1,58 @@
1
1
  module Jekyll
2
- class Stevenson
3
- attr_accessor :log_level
4
-
5
- LOG_LEVELS = {
6
- debug: 0,
7
- info: 1,
8
- warn: 2,
9
- error: 3
10
- }
11
-
12
- # Public: Create a new instance of Stevenson, Jekyll's logger
13
- #
14
- # level - (optional, symbol) the log level
15
- #
16
- # Returns nothing
17
- def initialize(level = :info)
18
- @log_level = level
19
- end
20
-
21
- # Public: Print a jekyll debug message to stdout
22
- #
23
- # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
24
- # message - the message detail
25
- #
26
- # Returns nothing
27
- def debug(topic, message = nil)
28
- $stdout.puts(message(topic, message)) if should_log(:debug)
29
- end
30
-
31
- # Public: Print a jekyll message to stdout
32
- #
33
- # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
34
- # message - the message detail
35
- #
36
- # Returns nothing
37
- def info(topic, message = nil)
38
- $stdout.puts(message(topic, message)) if should_log(:info)
39
- end
40
-
41
- # Public: Print a jekyll message to stderr
42
- #
43
- # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
44
- # message - the message detail
45
- #
46
- # Returns nothing
47
- def warn(topic, message = nil)
48
- $stderr.puts(message(topic, message).yellow) if should_log(:warn)
49
- end
50
-
51
- # Public: Print a jekyll error message to stderr
52
- #
53
- # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
54
- # message - the message detail
55
- #
56
- # Returns nothing
57
- def error(topic, message = nil)
58
- $stderr.puts(message(topic, message).red) if should_log(:error)
59
- end
60
-
61
- # Public: Print a Jekyll error message to stderr and immediately abort the process
62
- #
63
- # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
64
- # message - the message detail (can be omitted)
65
- #
66
- # Returns nothing
67
- def abort_with(topic, message = nil)
68
- error(topic, message)
69
- abort
70
- end
71
-
72
- # Public: Build a Jekyll topic method
73
- #
74
- # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
75
- # message - the message detail
76
- #
77
- # Returns the formatted message
78
- def message(topic, message)
79
- formatted_topic(topic) + message.to_s.gsub(/\s+/, ' ')
80
- end
81
-
82
- # Public: Format the topic
83
- #
84
- # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc.
85
- #
86
- # Returns the formatted topic statement
87
- def formatted_topic(topic)
88
- "#{topic} ".rjust(20)
89
- end
90
-
91
- # Public: Determine whether the current log level warrants logging at the
92
- # proposed level.
93
- #
94
- # level_of_message - the log level of the message (symbol)
95
- #
96
- # Returns true if the log level of the message is greater than or equal to
97
- # this logger's log level.
98
- def should_log(level_of_message)
99
- LOG_LEVELS.fetch(log_level) <= LOG_LEVELS.fetch(level_of_message)
2
+ class Stevenson < ::Logger
3
+ def initialize
4
+ @progname = nil
5
+ @level = DEBUG
6
+ @default_formatter = Formatter.new
7
+ @logdev = $stdout
8
+ @formatter = proc do |severity, datetime, progname, msg|
9
+ "#{msg}"
10
+ end
11
+ end
12
+
13
+ def add(severity, message = nil, progname = nil, &block)
14
+ severity ||= UNKNOWN
15
+ @logdev = set_logdevice(severity)
16
+
17
+ if @logdev.nil? or severity < @level
18
+ return true
19
+ end
20
+ progname ||= @progname
21
+ if message.nil?
22
+ if block_given?
23
+ message = yield
24
+ else
25
+ message = progname
26
+ progname = @progname
27
+ end
28
+ end
29
+ @logdev.puts(
30
+ format_message(format_severity(severity), Time.now, progname, message))
31
+ true
32
+ end
33
+
34
+ # Log a +WARN+ message
35
+ def warn(progname = nil, &block)
36
+ add(WARN, nil, progname.yellow, &block)
37
+ end
38
+
39
+ # Log an +ERROR+ message
40
+ def error(progname = nil, &block)
41
+ add(ERROR, nil, progname.red, &block)
42
+ end
43
+
44
+ def close
45
+ # No LogDevice in use
46
+ end
47
+
48
+ private
49
+
50
+ def set_logdevice(severity)
51
+ if severity > INFO
52
+ $stderr
53
+ else
54
+ $stdout
55
+ end
100
56
  end
101
57
  end
102
58
  end