forked from jekyll/jekyll
-
Notifications
You must be signed in to change notification settings - Fork 0
/
entry_filter.rb
111 lines (95 loc) · 3.05 KB
/
entry_filter.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# frozen_string_literal: true
module Jekyll
class EntryFilter
attr_reader :site
SPECIAL_LEADING_CHAR_REGEX = %r!\A#{Regexp.union([".", "_", "#", "~"])}!o.freeze
def initialize(site, base_directory = nil)
@site = site
@base_directory = derive_base_directory(
@site, base_directory.to_s.dup
)
end
def base_directory
@base_directory.to_s
end
def derive_base_directory(site, base_dir)
base_dir[site.source] = "" if base_dir.start_with?(site.source)
base_dir
end
def relative_to_source(entry)
File.join(
base_directory, entry
)
end
def filter(entries)
entries.reject do |e|
# Reject this entry if it is just a "dot" representation.
# e.g.: '.', '..', '_movies/.', 'music/..', etc
next true if e.end_with?(".")
# Reject this entry if it is a symlink.
next true if symlink?(e)
# Do not reject this entry if it is included.
next false if included?(e)
# Reject this entry if it is special, a backup file, or excluded.
special?(e) || backup?(e) || excluded?(e)
end
end
def included?(entry)
glob_include?(site.include, entry) ||
glob_include?(site.include, File.basename(entry))
end
def special?(entry)
SPECIAL_LEADING_CHAR_REGEX.match?(entry) ||
SPECIAL_LEADING_CHAR_REGEX.match?(File.basename(entry))
end
def backup?(entry)
entry.end_with?("~")
end
def excluded?(entry)
glob_include?(site.exclude - site.include, relative_to_source(entry)).tap do |excluded|
if excluded
Jekyll.logger.debug(
"EntryFilter:",
"excluded #{relative_to_source(entry)}"
)
end
end
end
# --
# Check if a file is a symlink.
# NOTE: This can be converted to allowing even in safe,
# since we use Pathutil#in_path? now.
# --
def symlink?(entry)
site.safe && File.symlink?(entry) && symlink_outside_site_source?(entry)
end
# --
# NOTE: Pathutil#in_path? gets the realpath.
# @param [<Anything>] entry the entry you want to validate.
# Check if a path is outside of our given root.
# --
def symlink_outside_site_source?(entry)
!Pathutil.new(entry).in_path?(
site.in_source_dir
)
end
# Check if an entry matches a specific pattern.
# Returns true if path matches against any glob pattern, else false.
def glob_include?(enumerator, entry)
entry_with_source = PathManager.join(site.source, entry)
enumerator.any? do |pattern|
case pattern
when String
pattern_with_source = PathManager.join(site.source, pattern)
File.fnmatch?(pattern_with_source, entry_with_source) ||
entry_with_source.start_with?(pattern_with_source) ||
(pattern_with_source == "#{entry_with_source}/" if File.directory?(entry_with_source))
when Regexp
pattern.match?(entry_with_source)
else
false
end
end
end
end
end