jekyll 4.0.0.pre.alpha1 → 4.0.0.pre.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -34,7 +34,6 @@ module Jekyll
34
34
  @config["syntax_highlighter_opts"]["guess_lang"] = @config["guess_lang"]
35
35
  @config["coderay"] ||= {} # XXX: Legacy.
36
36
  modernize_coderay_config
37
- make_accessible
38
37
  end
39
38
 
40
39
  def convert(content)
@@ -64,13 +63,6 @@ module Jekyll
64
63
  end
65
64
  end
66
65
 
67
- def make_accessible(hash = @config)
68
- hash.keys.each do |key|
69
- hash[key.to_sym] = hash[key]
70
- make_accessible(hash[key]) if hash[key].is_a?(Hash)
71
- end
72
- end
73
-
74
66
  # config[kramdown][syntax_higlighter] >
75
67
  # config[kramdown][enable_coderay] >
76
68
  # config[highlighter]
@@ -146,7 +146,7 @@ module Jekyll
146
146
  #
147
147
  # Returns true if extname == .sass or .scss, false otherwise.
148
148
  def sass_file?
149
- %w(.sass .scss).include?(ext)
149
+ Jekyll::Document::SASS_FILE_EXTS.include?(ext)
150
150
  end
151
151
 
152
152
  # Determine whether the document is a CoffeeScript file.
@@ -5,7 +5,7 @@ module Jekyll
5
5
  include Comparable
6
6
  extend Forwardable
7
7
 
8
- attr_reader :path, :site, :extname, :collection
8
+ attr_reader :path, :site, :extname, :collection, :type
9
9
  attr_accessor :content, :output
10
10
 
11
11
  def_delegator :self, :read_post_data, :post_read
@@ -14,6 +14,23 @@ module Jekyll
14
14
  DATELESS_FILENAME_MATCHER = %r!^(?:.+/)*(.*)(\.[^.]+)$!.freeze
15
15
  DATE_FILENAME_MATCHER = %r!^(?>.+/)*?(\d{2,4}-\d{1,2}-\d{1,2})-([^/]*)(\.[^.]+)$!.freeze
16
16
 
17
+ SASS_FILE_EXTS = %w(.sass .scss).freeze
18
+ YAML_FILE_EXTS = %w(.yaml .yml).freeze
19
+
20
+ #
21
+
22
+ # Class-wide cache to stash and retrieve regexp to detect "super-directories"
23
+ # of a particular Jekyll::Document object.
24
+ #
25
+ # dirname - The *special directory* for the Document.
26
+ # e.g. "_posts" or "_drafts" for Documents from the `site.posts` collection.
27
+ def self.superdirs_regex(dirname)
28
+ @superdirs_regex ||= {}
29
+ @superdirs_regex[dirname] ||= %r!#{dirname}.*!
30
+ end
31
+
32
+ #
33
+
17
34
  # Create a new Document.
18
35
  #
19
36
  # path - the path to the file
@@ -27,6 +44,8 @@ module Jekyll
27
44
  @path = path
28
45
  @extname = File.extname(path)
29
46
  @collection = relations[:collection]
47
+ @type = @collection.label.to_sym
48
+
30
49
  @has_yaml_header = nil
31
50
 
32
51
  if draft?
@@ -36,7 +55,7 @@ module Jekyll
36
55
  end
37
56
 
38
57
  data.default_proc = proc do |_, key|
39
- site.frontmatter_defaults.find(relative_path, collection.label, key)
58
+ site.frontmatter_defaults.find(relative_path, type, key)
40
59
  end
41
60
 
42
61
  trigger_hooks(:post_init)
@@ -138,7 +157,7 @@ module Jekyll
138
157
  #
139
158
  # Returns true if the extname is either .yml or .yaml, false otherwise.
140
159
  def yaml_file?
141
- %w(.yaml .yml).include?(extname)
160
+ YAML_FILE_EXTS.include?(extname)
142
161
  end
143
162
 
144
163
  # Determine whether the document is an asset file.
@@ -154,7 +173,7 @@ module Jekyll
154
173
  #
155
174
  # Returns true if extname == .sass or .scss, false otherwise.
156
175
  def sass_file?
157
- %w(.sass .scss).include?(extname)
176
+ SASS_FILE_EXTS.include?(extname)
158
177
  end
159
178
 
160
179
  # Determine whether the document is a CoffeeScript file.
@@ -373,12 +392,6 @@ module Jekyll
373
392
  @related_posts ||= Jekyll::RelatedPosts.new(self).build
374
393
  end
375
394
 
376
- # Override of normal respond_to? to match method_missing's logic for
377
- # looking in @data.
378
- def respond_to?(method, include_private = false)
379
- data.key?(method.to_s) || super
380
- end
381
-
382
395
  # Override of method_missing to check in @data for the key.
383
396
  def method_missing(method, *args, &blck)
384
397
  if data.key?(method.to_s)
@@ -401,28 +414,29 @@ module Jekyll
401
414
  #
402
415
  # Returns nothing.
403
416
  def categories_from_path(special_dir)
404
- superdirs = relative_path.sub(%r!#{special_dir}(.*)!, "")
405
- .split(File::SEPARATOR)
406
- .reject do |c|
407
- c.empty? || c == special_dir || c == basename
408
- end
417
+ superdirs = relative_path.sub(Document.superdirs_regex(special_dir), "")
418
+ superdirs = superdirs.split(File::SEPARATOR)
419
+ superdirs.reject! { |c| c.empty? || c == special_dir || c == basename }
420
+
409
421
  merge_data!({ "categories" => superdirs }, :source => "file path")
410
422
  end
411
423
 
412
424
  def populate_categories
413
- merge_data!(
414
- "categories" => (
415
- Array(data["categories"]) + Utils.pluralized_array_from_hash(
416
- data, "category", "categories"
417
- )
418
- ).map(&:to_s).flatten.uniq
425
+ categories = Array(data["categories"]) + Utils.pluralized_array_from_hash(
426
+ data, "category", "categories"
419
427
  )
428
+ categories.map!(&:to_s)
429
+ categories.flatten!
430
+ categories.uniq!
431
+
432
+ merge_data!("categories" => categories)
420
433
  end
421
434
 
422
435
  def populate_tags
423
- merge_data!(
424
- "tags" => Utils.pluralized_array_from_hash(data, "tag", "tags").flatten
425
- )
436
+ tags = Utils.pluralized_array_from_hash(data, "tag", "tags")
437
+ tags.flatten!
438
+
439
+ merge_data!("tags" => tags)
426
440
  end
427
441
 
428
442
  private
@@ -444,10 +458,7 @@ module Jekyll
444
458
  end
445
459
 
446
460
  def merge_defaults
447
- defaults = @site.frontmatter_defaults.all(
448
- relative_path,
449
- collection.label.to_sym
450
- )
461
+ defaults = @site.frontmatter_defaults.all(relative_path, type)
451
462
  merge_data!(defaults, :source => "front matter defaults") unless defaults.empty?
452
463
  end
453
464
 
@@ -30,7 +30,6 @@ module Jekyll
30
30
  # Returns nothing
31
31
  def initialize(obj)
32
32
  @obj = obj
33
- @mutations = {} # only if mutable: true
34
33
  end
35
34
 
36
35
  # Access a method in the Drop or a field in the underlying hash data.
@@ -42,8 +41,8 @@ module Jekyll
42
41
  #
43
42
  # Returns the value for the given key, or nil if none exists
44
43
  def [](key)
45
- if self.class.mutable? && @mutations.key?(key)
46
- @mutations[key]
44
+ if self.class.mutable? && mutations.key?(key)
45
+ mutations[key]
47
46
  elsif self.class.invokable? key
48
47
  public_send key
49
48
  else
@@ -66,11 +65,12 @@ module Jekyll
66
65
  # and the key matches a method in which case it raises a
67
66
  # DropMutationException.
68
67
  def []=(key, val)
69
- if respond_to?("#{key}=")
70
- public_send("#{key}=", val)
68
+ setter = "#{key}="
69
+ if respond_to?(setter)
70
+ public_send(setter, val)
71
71
  elsif respond_to?(key.to_s)
72
72
  if self.class.mutable?
73
- @mutations[key] = val
73
+ mutations[key] = val
74
74
  else
75
75
  raise Errors::DropMutationException, "Key #{key} cannot be set in the drop."
76
76
  end
@@ -100,7 +100,7 @@ module Jekyll
100
100
  # Returns true if the given key is present
101
101
  def key?(key)
102
102
  return false if key.nil?
103
- return true if self.class.mutable? && @mutations.key?(key)
103
+ return true if self.class.mutable? && mutations.key?(key)
104
104
 
105
105
  respond_to?(key) || fallback_data.key?(key)
106
106
  end
@@ -113,7 +113,7 @@ module Jekyll
113
113
  # Returns an Array of unique keys for content for the Drop.
114
114
  def keys
115
115
  (content_methods |
116
- @mutations.keys |
116
+ mutations.keys |
117
117
  fallback_data.keys).flatten
118
118
  end
119
119
 
@@ -204,6 +204,12 @@ module Jekyll
204
204
  return yield(key) unless block.nil?
205
205
  return default unless default.nil?
206
206
  end
207
+
208
+ private
209
+
210
+ def mutations
211
+ @mutations ||= {}
212
+ end
207
213
  end
208
214
  end
209
215
  end
@@ -8,7 +8,7 @@ module Jekyll
8
8
  mutable false
9
9
 
10
10
  def_delegator :@obj, :site_data, :data
11
- def_delegators :@obj, :time, :pages, :static_files, :documents, :tags, :categories
11
+ def_delegators :@obj, :time, :pages, :static_files, :tags, :categories
12
12
 
13
13
  private def_delegator :@obj, :config, :fallback_data
14
14
 
@@ -38,6 +38,16 @@ module Jekyll
38
38
  @site_collections ||= @obj.collections.values.sort_by(&:label).map(&:to_liquid)
39
39
  end
40
40
 
41
+ # `Site#documents` cannot be memoized so that `Site#docs_to_write` can access the
42
+ # latest state of the attribute.
43
+ #
44
+ # Since this method will be called after `Site#pre_render` hook, the `Site#documents`
45
+ # array shouldn't thereafter change and can therefore be safely memoized to prevent
46
+ # additional computation of `Site#documents`.
47
+ def documents
48
+ @documents ||= @obj.documents
49
+ end
50
+
41
51
  # `{{ site.related_posts }}` is how posts can get posts related to
42
52
  # them, either through LSI if it's enabled, or through the most
43
53
  # recent posts.
@@ -35,46 +35,89 @@ module Jekyll
35
35
  category_set.to_a.join("/")
36
36
  end
37
37
 
38
+ # CCYY
38
39
  def year
39
40
  @obj.date.strftime("%Y")
40
41
  end
41
42
 
43
+ # MM: 01..12
42
44
  def month
43
45
  @obj.date.strftime("%m")
44
46
  end
45
47
 
48
+ # DD: 01..31
46
49
  def day
47
50
  @obj.date.strftime("%d")
48
51
  end
49
52
 
53
+ # hh: 00..23
50
54
  def hour
51
55
  @obj.date.strftime("%H")
52
56
  end
53
57
 
58
+ # mm: 00..59
54
59
  def minute
55
60
  @obj.date.strftime("%M")
56
61
  end
57
62
 
63
+ # ss: 00..59
58
64
  def second
59
65
  @obj.date.strftime("%S")
60
66
  end
61
67
 
68
+ # D: 1..31
62
69
  def i_day
63
70
  @obj.date.strftime("%-d")
64
71
  end
65
72
 
73
+ # M: 1..12
66
74
  def i_month
67
75
  @obj.date.strftime("%-m")
68
76
  end
69
77
 
78
+ # MMM: Jan..Dec
70
79
  def short_month
71
80
  @obj.date.strftime("%b")
72
81
  end
73
82
 
83
+ # MMMM: January..December
84
+ def long_month
85
+ @obj.date.strftime("%B")
86
+ end
87
+
88
+ # YY: 00..99
74
89
  def short_year
75
90
  @obj.date.strftime("%y")
76
91
  end
77
92
 
93
+ # CCYYw, ISO week year
94
+ # may differ from CCYY for the first days of January and last days of December
95
+ def w_year
96
+ @obj.date.strftime("%G")
97
+ end
98
+
99
+ # WW: 01..53
100
+ # %W and %U do not comply with ISO 8601-1
101
+ def week
102
+ @obj.date.strftime("%V")
103
+ end
104
+
105
+ # d: 1..7 (Monday..Sunday)
106
+ def w_day
107
+ @obj.date.strftime("%u")
108
+ end
109
+
110
+ # dd: Mon..Sun
111
+ def short_day
112
+ @obj.date.strftime("%a")
113
+ end
114
+
115
+ # ddd: Monday..Sunday
116
+ def long_day
117
+ @obj.date.strftime("%A")
118
+ end
119
+
120
+ # DDD: 001..366
78
121
  def y_day
79
122
  @obj.date.strftime("%j")
80
123
  end
@@ -3,9 +3,7 @@
3
3
  module Jekyll
4
4
  class EntryFilter
5
5
  attr_reader :site
6
- SPECIAL_LEADING_CHARACTERS = [
7
- ".", "_", "#", "~",
8
- ].freeze
6
+ SPECIAL_LEADING_CHAR_REGEX = %r!\A#{Regexp.union([".", "_", "#", "~"])}!o.freeze
9
7
 
10
8
  def initialize(site, base_directory = nil)
11
9
  @site = site
@@ -31,6 +29,9 @@ module Jekyll
31
29
 
32
30
  def filter(entries)
33
31
  entries.reject do |e|
32
+ # Reject this entry if it is just a "dot" representation.
33
+ # e.g.: '.', '..', '_movies/.', 'music/..', etc
34
+ next true if e.end_with?(".")
34
35
  # Reject this entry if it is a symlink.
35
36
  next true if symlink?(e)
36
37
  # Do not reject this entry if it is included.
@@ -47,8 +48,8 @@ module Jekyll
47
48
  end
48
49
 
49
50
  def special?(entry)
50
- SPECIAL_LEADING_CHARACTERS.include?(entry[0..0]) ||
51
- SPECIAL_LEADING_CHARACTERS.include?(File.basename(entry)[0..0])
51
+ SPECIAL_LEADING_CHAR_REGEX.match?(entry) ||
52
+ SPECIAL_LEADING_CHAR_REGEX.match?(File.basename(entry))
52
53
  end
53
54
 
54
55
  def backup?(entry)
@@ -86,40 +87,22 @@ module Jekyll
86
87
  )
87
88
  end
88
89
 
89
- # --
90
- # Check if an entry matches a specific pattern and return true,false.
91
- # Returns true if path matches against any glob pattern.
92
- # --
93
- def glob_include?(enum, entry)
94
- entry_path = Pathutil.new(site.in_source_dir).join(entry)
95
- enum.any? do |exp|
96
- # Users who send a Regexp knows what they want to
97
- # exclude, so let them send a Regexp to exclude files,
98
- # we will not bother caring if it works or not, it's
99
- # on them at this point.
90
+ # Check if an entry matches a specific pattern.
91
+ # Returns true if path matches against any glob pattern, else false.
92
+ def glob_include?(enumerator, entry)
93
+ entry_with_source = PathManager.join(site.source, entry)
100
94
 
101
- if exp.is_a?(Regexp)
102
- entry_path =~ exp
95
+ enumerator.any? do |pattern|
96
+ case pattern
97
+ when String
98
+ pattern_with_source = PathManager.join(site.source, pattern)
103
99
 
100
+ File.fnmatch?(pattern_with_source, entry_with_source) ||
101
+ entry_with_source.start_with?(pattern_with_source)
102
+ when Regexp
103
+ pattern.match?(entry_with_source)
104
104
  else
105
- item = Pathutil.new(site.in_source_dir).join(exp)
106
-
107
- # If it's a directory they want to exclude, AKA
108
- # ends with a "/" then we will go on to check and
109
- # see if the entry falls within that path and
110
- # exclude it if that's the case.
111
-
112
- if entry.end_with?("/")
113
- entry_path.in_path?(
114
- item
115
- )
116
-
117
- else
118
- File.fnmatch?(item, entry_path) ||
119
- entry_path.to_path.start_with?(
120
- item
121
- )
122
- end
105
+ false
123
106
  end
124
107
  end
125
108
  end
@@ -10,7 +10,7 @@ module Jekyll
10
10
 
11
11
  def_delegators :@doc,
12
12
  :site, :name, :ext, :extname,
13
- :collection, :related_posts,
13
+ :collection, :related_posts, :type,
14
14
  :coffeescript_file?, :yaml_file?,
15
15
  :url, :next_doc, :previous_doc
16
16
 
@@ -155,7 +155,7 @@ module Jekyll
155
155
  tag_names.flatten!
156
156
  tag_names.reverse_each do |tag_name|
157
157
  next unless liquid_block?(tag_name)
158
- next if head =~ endtag_regex_stash(tag_name)
158
+ next if endtag_regex_stash(tag_name).match?(head)
159
159
 
160
160
  modified = true
161
161
  head << "\n{% end#{tag_name} %}"