jekyll 4.0.1 → 4.2.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 (124) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +350 -163
  3. data/LICENSE +21 -21
  4. data/README.markdown +86 -90
  5. data/exe/jekyll +57 -57
  6. data/lib/blank_template/_config.yml +3 -3
  7. data/lib/blank_template/_layouts/default.html +12 -12
  8. data/lib/blank_template/_sass/main.scss +9 -9
  9. data/lib/blank_template/assets/css/main.scss +4 -4
  10. data/lib/blank_template/index.md +8 -8
  11. data/lib/jekyll/cache.rb +190 -190
  12. data/lib/jekyll/cleaner.rb +111 -111
  13. data/lib/jekyll/collection.rb +309 -309
  14. data/lib/jekyll/command.rb +105 -103
  15. data/lib/jekyll/commands/build.rb +93 -93
  16. data/lib/jekyll/commands/clean.rb +45 -45
  17. data/lib/jekyll/commands/doctor.rb +177 -173
  18. data/lib/jekyll/commands/help.rb +34 -34
  19. data/lib/jekyll/commands/new.rb +169 -169
  20. data/lib/jekyll/commands/new_theme.rb +40 -42
  21. data/lib/jekyll/commands/serve/live_reload_reactor.rb +122 -122
  22. data/lib/jekyll/commands/serve/livereload_assets/livereload.js +1183 -1183
  23. data/lib/jekyll/commands/serve/servlet.rb +202 -202
  24. data/lib/jekyll/commands/serve/websockets.rb +81 -81
  25. data/lib/jekyll/commands/serve.rb +362 -354
  26. data/lib/jekyll/configuration.rb +313 -316
  27. data/lib/jekyll/converter.rb +54 -54
  28. data/lib/jekyll/converters/identity.rb +41 -41
  29. data/lib/jekyll/converters/markdown/kramdown_parser.rb +199 -130
  30. data/lib/jekyll/converters/markdown.rb +113 -113
  31. data/lib/jekyll/converters/smartypants.rb +70 -70
  32. data/lib/jekyll/convertible.rb +257 -254
  33. data/lib/jekyll/deprecator.rb +50 -50
  34. data/lib/jekyll/document.rb +544 -522
  35. data/lib/jekyll/drops/collection_drop.rb +20 -20
  36. data/lib/jekyll/drops/document_drop.rb +70 -69
  37. data/lib/jekyll/drops/drop.rb +293 -215
  38. data/lib/jekyll/drops/excerpt_drop.rb +19 -19
  39. data/lib/jekyll/drops/jekyll_drop.rb +32 -32
  40. data/lib/jekyll/drops/site_drop.rb +66 -66
  41. data/lib/jekyll/drops/static_file_drop.rb +14 -14
  42. data/lib/jekyll/drops/unified_payload_drop.rb +26 -26
  43. data/lib/jekyll/drops/url_drop.rb +140 -132
  44. data/lib/jekyll/entry_filter.rb +121 -110
  45. data/lib/jekyll/errors.rb +20 -20
  46. data/lib/jekyll/excerpt.rb +201 -201
  47. data/lib/jekyll/external.rb +79 -79
  48. data/lib/jekyll/filters/date_filters.rb +110 -110
  49. data/lib/jekyll/filters/grouping_filters.rb +64 -64
  50. data/lib/jekyll/filters/url_filters.rb +98 -68
  51. data/lib/jekyll/filters.rb +535 -454
  52. data/lib/jekyll/frontmatter_defaults.rb +240 -245
  53. data/lib/jekyll/generator.rb +5 -5
  54. data/lib/jekyll/hooks.rb +107 -106
  55. data/lib/jekyll/inclusion.rb +32 -0
  56. data/lib/jekyll/layout.rb +67 -62
  57. data/lib/jekyll/liquid_extensions.rb +22 -22
  58. data/lib/jekyll/liquid_renderer/file.rb +77 -77
  59. data/lib/jekyll/liquid_renderer/table.rb +55 -75
  60. data/lib/jekyll/liquid_renderer.rb +80 -77
  61. data/lib/jekyll/log_adapter.rb +151 -151
  62. data/lib/jekyll/mime.types +866 -866
  63. data/lib/jekyll/page.rb +217 -186
  64. data/lib/jekyll/page_excerpt.rb +25 -0
  65. data/lib/jekyll/page_without_a_file.rb +14 -14
  66. data/lib/jekyll/path_manager.rb +74 -31
  67. data/lib/jekyll/plugin.rb +92 -92
  68. data/lib/jekyll/plugin_manager.rb +115 -115
  69. data/lib/jekyll/profiler.rb +58 -0
  70. data/lib/jekyll/publisher.rb +23 -23
  71. data/lib/jekyll/reader.rb +192 -187
  72. data/lib/jekyll/readers/collection_reader.rb +23 -22
  73. data/lib/jekyll/readers/data_reader.rb +79 -75
  74. data/lib/jekyll/readers/layout_reader.rb +62 -61
  75. data/lib/jekyll/readers/page_reader.rb +25 -24
  76. data/lib/jekyll/readers/post_reader.rb +85 -84
  77. data/lib/jekyll/readers/static_file_reader.rb +25 -24
  78. data/lib/jekyll/readers/theme_assets_reader.rb +52 -51
  79. data/lib/jekyll/regenerator.rb +195 -195
  80. data/lib/jekyll/related_posts.rb +52 -52
  81. data/lib/jekyll/renderer.rb +265 -267
  82. data/lib/jekyll/site.rb +551 -527
  83. data/lib/jekyll/static_file.rb +208 -203
  84. data/lib/jekyll/stevenson.rb +60 -60
  85. data/lib/jekyll/tags/highlight.rb +110 -110
  86. data/lib/jekyll/tags/include.rb +275 -221
  87. data/lib/jekyll/tags/link.rb +42 -41
  88. data/lib/jekyll/tags/post_url.rb +106 -107
  89. data/lib/jekyll/theme.rb +86 -80
  90. data/lib/jekyll/theme_builder.rb +121 -121
  91. data/lib/jekyll/url.rb +167 -164
  92. data/lib/jekyll/utils/ansi.rb +57 -57
  93. data/lib/jekyll/utils/exec.rb +26 -26
  94. data/lib/jekyll/utils/internet.rb +37 -37
  95. data/lib/jekyll/utils/platforms.rb +67 -82
  96. data/lib/jekyll/utils/thread_event.rb +31 -31
  97. data/lib/jekyll/utils/win_tz.rb +75 -75
  98. data/lib/jekyll/utils.rb +367 -367
  99. data/lib/jekyll/version.rb +5 -5
  100. data/lib/jekyll.rb +195 -206
  101. data/lib/site_template/.gitignore +5 -5
  102. data/lib/site_template/404.html +25 -25
  103. data/lib/site_template/_config.yml +55 -55
  104. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +29 -29
  105. data/lib/site_template/about.markdown +18 -18
  106. data/lib/site_template/index.markdown +6 -6
  107. data/lib/theme_template/CODE_OF_CONDUCT.md.erb +74 -74
  108. data/lib/theme_template/Gemfile +4 -4
  109. data/lib/theme_template/LICENSE.txt.erb +21 -21
  110. data/lib/theme_template/README.md.erb +52 -52
  111. data/lib/theme_template/_layouts/default.html +1 -1
  112. data/lib/theme_template/_layouts/page.html +5 -5
  113. data/lib/theme_template/_layouts/post.html +5 -5
  114. data/lib/theme_template/example/_config.yml.erb +1 -1
  115. data/lib/theme_template/example/_post.md +12 -12
  116. data/lib/theme_template/example/index.html +14 -14
  117. data/lib/theme_template/example/style.scss +7 -7
  118. data/lib/theme_template/gitignore.erb +6 -6
  119. data/lib/theme_template/theme.gemspec.erb +16 -19
  120. data/rubocop/jekyll/assert_equal_literal_actual.rb +149 -149
  121. data/rubocop/jekyll/no_p_allowed.rb +23 -23
  122. data/rubocop/jekyll/no_puts_allowed.rb +23 -23
  123. data/rubocop/jekyll.rb +5 -5
  124. metadata +20 -38
data/lib/jekyll/reader.rb CHANGED
@@ -1,187 +1,192 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- class Reader
5
- attr_reader :site
6
-
7
- def initialize(site)
8
- @site = site
9
- end
10
-
11
- # Read Site data from disk and load it into internal data structures.
12
- #
13
- # Returns nothing.
14
- def read
15
- @site.layouts = LayoutReader.new(site).read
16
- read_directories
17
- read_included_excludes
18
- sort_files!
19
- @site.data = DataReader.new(site).read(site.config["data_dir"])
20
- CollectionReader.new(site).read
21
- ThemeAssetsReader.new(site).read
22
- end
23
-
24
- # Sorts posts, pages, and static files.
25
- def sort_files!
26
- site.collections.each_value { |c| c.docs.sort! }
27
- site.pages.sort_by!(&:name)
28
- site.static_files.sort_by!(&:relative_path)
29
- end
30
-
31
- # Recursively traverse directories to find pages and static files
32
- # that will become part of the site according to the rules in
33
- # filter_entries.
34
- #
35
- # dir - The String relative path of the directory to read. Default: ''.
36
- #
37
- # Returns nothing.
38
- def read_directories(dir = "")
39
- base = site.in_source_dir(dir)
40
-
41
- return unless File.directory?(base)
42
-
43
- dot_dirs = []
44
- dot_pages = []
45
- dot_static_files = []
46
-
47
- dot = Dir.chdir(base) { filter_entries(Dir.entries("."), base) }
48
- dot.each do |entry|
49
- file_path = @site.in_source_dir(base, entry)
50
- if File.directory?(file_path)
51
- dot_dirs << entry
52
- elsif Utils.has_yaml_header?(file_path)
53
- dot_pages << entry
54
- else
55
- dot_static_files << entry
56
- end
57
- end
58
-
59
- retrieve_posts(dir)
60
- retrieve_dirs(base, dir, dot_dirs)
61
- retrieve_pages(dir, dot_pages)
62
- retrieve_static_files(dir, dot_static_files)
63
- end
64
-
65
- # Retrieves all the posts(posts/drafts) from the given directory
66
- # and add them to the site and sort them.
67
- #
68
- # dir - The String representing the directory to retrieve the posts from.
69
- #
70
- # Returns nothing.
71
- def retrieve_posts(dir)
72
- return if outside_configured_directory?(dir)
73
-
74
- site.posts.docs.concat(post_reader.read_posts(dir))
75
- site.posts.docs.concat(post_reader.read_drafts(dir)) if site.show_drafts
76
- end
77
-
78
- # Recursively traverse directories with the read_directories function.
79
- #
80
- # base - The String representing the site's base directory.
81
- # dir - The String representing the directory to traverse down.
82
- # dot_dirs - The Array of subdirectories in the dir.
83
- #
84
- # Returns nothing.
85
- def retrieve_dirs(_base, dir, dot_dirs)
86
- dot_dirs.each do |file|
87
- dir_path = site.in_source_dir(dir, file)
88
- rel_path = PathManager.join(dir, file)
89
- @site.reader.read_directories(rel_path) unless @site.dest.chomp("/") == dir_path
90
- end
91
- end
92
-
93
- # Retrieve all the pages from the current directory,
94
- # add them to the site and sort them.
95
- #
96
- # dir - The String representing the directory retrieve the pages from.
97
- # dot_pages - The Array of pages in the dir.
98
- #
99
- # Returns nothing.
100
- def retrieve_pages(dir, dot_pages)
101
- site.pages.concat(PageReader.new(site, dir).read(dot_pages))
102
- end
103
-
104
- # Retrieve all the static files from the current directory,
105
- # add them to the site and sort them.
106
- #
107
- # dir - The directory retrieve the static files from.
108
- # dot_static_files - The static files in the dir.
109
- #
110
- # Returns nothing.
111
- def retrieve_static_files(dir, dot_static_files)
112
- site.static_files.concat(StaticFileReader.new(site, dir).read(dot_static_files))
113
- end
114
-
115
- # Filter out any files/directories that are hidden or backup files (start
116
- # with "." or "#" or end with "~"), or contain site content (start with "_"),
117
- # or are excluded in the site configuration, unless they are web server
118
- # files such as '.htaccess'.
119
- #
120
- # entries - The Array of String file/directory entries to filter.
121
- # base_directory - The string representing the optional base directory.
122
- #
123
- # Returns the Array of filtered entries.
124
- def filter_entries(entries, base_directory = nil)
125
- EntryFilter.new(site, base_directory).filter(entries)
126
- end
127
-
128
- # Read the entries from a particular directory for processing
129
- #
130
- # dir - The String representing the relative path of the directory to read.
131
- # subfolder - The String representing the directory to read.
132
- #
133
- # Returns the list of entries to process
134
- def get_entries(dir, subfolder)
135
- base = site.in_source_dir(dir, subfolder)
136
- return [] unless File.exist?(base)
137
-
138
- entries = Dir.chdir(base) { filter_entries(Dir["**/*"], base) }
139
- entries.delete_if { |e| File.directory?(site.in_source_dir(base, e)) }
140
- end
141
-
142
- private
143
-
144
- # Internal
145
- #
146
- # Determine if the directory is supposed to contain posts and drafts.
147
- # If the user has defined a custom collections_dir, then attempt to read
148
- # posts and drafts only from within that directory.
149
- #
150
- # Returns true if a custom collections_dir has been set but current directory lies
151
- # outside that directory.
152
- def outside_configured_directory?(dir)
153
- collections_dir = site.config["collections_dir"]
154
- !collections_dir.empty? && !dir.start_with?("/#{collections_dir}")
155
- end
156
-
157
- # Create a single PostReader instance to retrieve drafts and posts from all valid
158
- # directories in current site.
159
- def post_reader
160
- @post_reader ||= PostReader.new(site)
161
- end
162
-
163
- def read_included_excludes
164
- entry_filter = EntryFilter.new(site)
165
-
166
- site.include.each do |entry|
167
- next if entry == ".htaccess"
168
-
169
- entry_path = site.in_source_dir(entry)
170
- next if File.directory?(entry_path)
171
- next if entry_filter.symlink?(entry_path)
172
-
173
- read_included_file(entry_path) if File.file?(entry_path)
174
- end
175
- end
176
-
177
- def read_included_file(entry_path)
178
- dir = File.dirname(entry_path).sub(site.source, "")
179
- file = Array(File.basename(entry_path))
180
- if Utils.has_yaml_header?(entry_path)
181
- site.pages.concat(PageReader.new(site, dir).read(file))
182
- else
183
- site.static_files.concat(StaticFileReader.new(site, dir).read(file))
184
- end
185
- end
186
- end
187
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class Reader
5
+ attr_reader :site
6
+
7
+ def initialize(site)
8
+ @site = site
9
+ end
10
+
11
+ # Read Site data from disk and load it into internal data structures.
12
+ #
13
+ # Returns nothing.
14
+ def read
15
+ @site.layouts = LayoutReader.new(site).read
16
+ read_directories
17
+ read_included_excludes
18
+ sort_files!
19
+ @site.data = DataReader.new(site).read(site.config["data_dir"])
20
+ CollectionReader.new(site).read
21
+ ThemeAssetsReader.new(site).read
22
+ end
23
+
24
+ # Sorts posts, pages, and static files.
25
+ def sort_files!
26
+ site.collections.each_value { |c| c.docs.sort! }
27
+ site.pages.sort_by!(&:name)
28
+ site.static_files.sort_by!(&:relative_path)
29
+ end
30
+
31
+ # Recursively traverse directories to find pages and static files
32
+ # that will become part of the site according to the rules in
33
+ # filter_entries.
34
+ #
35
+ # dir - The String relative path of the directory to read. Default: ''.
36
+ #
37
+ # Returns nothing.
38
+ def read_directories(dir = "")
39
+ base = site.in_source_dir(dir)
40
+
41
+ return unless File.directory?(base)
42
+
43
+ dot_dirs = []
44
+ dot_pages = []
45
+ dot_static_files = []
46
+
47
+ dot = Dir.chdir(base) { filter_entries(Dir.entries("."), base) }
48
+ dot.each do |entry|
49
+ file_path = @site.in_source_dir(base, entry)
50
+ if File.directory?(file_path)
51
+ dot_dirs << entry
52
+ elsif Utils.has_yaml_header?(file_path)
53
+ dot_pages << entry
54
+ else
55
+ dot_static_files << entry
56
+ end
57
+ end
58
+
59
+ retrieve_posts(dir)
60
+ retrieve_dirs(base, dir, dot_dirs)
61
+ retrieve_pages(dir, dot_pages)
62
+ retrieve_static_files(dir, dot_static_files)
63
+ end
64
+
65
+ # Retrieves all the posts(posts/drafts) from the given directory
66
+ # and add them to the site and sort them.
67
+ #
68
+ # dir - The String representing the directory to retrieve the posts from.
69
+ #
70
+ # Returns nothing.
71
+ def retrieve_posts(dir)
72
+ return if outside_configured_directory?(dir)
73
+
74
+ site.posts.docs.concat(post_reader.read_posts(dir))
75
+ site.posts.docs.concat(post_reader.read_drafts(dir)) if site.show_drafts
76
+ end
77
+
78
+ # Recursively traverse directories with the read_directories function.
79
+ #
80
+ # base - The String representing the site's base directory.
81
+ # dir - The String representing the directory to traverse down.
82
+ # dot_dirs - The Array of subdirectories in the dir.
83
+ #
84
+ # Returns nothing.
85
+ def retrieve_dirs(_base, dir, dot_dirs)
86
+ dot_dirs.each do |file|
87
+ dir_path = site.in_source_dir(dir, file)
88
+ rel_path = PathManager.join(dir, file)
89
+ @site.reader.read_directories(rel_path) unless @site.dest.chomp("/") == dir_path
90
+ end
91
+ end
92
+
93
+ # Retrieve all the pages from the current directory,
94
+ # add them to the site and sort them.
95
+ #
96
+ # dir - The String representing the directory retrieve the pages from.
97
+ # dot_pages - The Array of pages in the dir.
98
+ #
99
+ # Returns nothing.
100
+ def retrieve_pages(dir, dot_pages)
101
+ site.pages.concat(PageReader.new(site, dir).read(dot_pages))
102
+ end
103
+
104
+ # Retrieve all the static files from the current directory,
105
+ # add them to the site and sort them.
106
+ #
107
+ # dir - The directory retrieve the static files from.
108
+ # dot_static_files - The static files in the dir.
109
+ #
110
+ # Returns nothing.
111
+ def retrieve_static_files(dir, dot_static_files)
112
+ site.static_files.concat(StaticFileReader.new(site, dir).read(dot_static_files))
113
+ end
114
+
115
+ # Filter out any files/directories that are hidden or backup files (start
116
+ # with "." or "#" or end with "~"), or contain site content (start with "_"),
117
+ # or are excluded in the site configuration, unless they are web server
118
+ # files such as '.htaccess'.
119
+ #
120
+ # entries - The Array of String file/directory entries to filter.
121
+ # base_directory - The string representing the optional base directory.
122
+ #
123
+ # Returns the Array of filtered entries.
124
+ def filter_entries(entries, base_directory = nil)
125
+ EntryFilter.new(site, base_directory).filter(entries)
126
+ end
127
+
128
+ # Read the entries from a particular directory for processing
129
+ #
130
+ # dir - The String representing the relative path of the directory to read.
131
+ # subfolder - The String representing the directory to read.
132
+ #
133
+ # Returns the list of entries to process
134
+ def get_entries(dir, subfolder)
135
+ base = site.in_source_dir(dir, subfolder)
136
+ return [] unless File.exist?(base)
137
+
138
+ entries = Dir.chdir(base) { filter_entries(Dir["**/*"], base) }
139
+ entries.delete_if { |e| File.directory?(site.in_source_dir(base, e)) }
140
+ end
141
+
142
+ private
143
+
144
+ # Internal
145
+ #
146
+ # Determine if the directory is supposed to contain posts and drafts.
147
+ # If the user has defined a custom collections_dir, then attempt to read
148
+ # posts and drafts only from within that directory.
149
+ #
150
+ # Returns true if a custom collections_dir has been set but current directory lies
151
+ # outside that directory.
152
+ def outside_configured_directory?(dir)
153
+ collections_dir = site.config["collections_dir"]
154
+ !collections_dir.empty? && !dir.start_with?("/#{collections_dir}")
155
+ end
156
+
157
+ # Create a single PostReader instance to retrieve drafts and posts from all valid
158
+ # directories in current site.
159
+ def post_reader
160
+ @post_reader ||= PostReader.new(site)
161
+ end
162
+
163
+ def read_included_excludes
164
+ entry_filter = EntryFilter.new(site)
165
+
166
+ site.include.each do |entry|
167
+ entry_path = site.in_source_dir(entry)
168
+ next if File.directory?(entry_path)
169
+ next if entry_filter.symlink?(entry_path)
170
+
171
+ read_included_file(entry_path) if File.file?(entry_path)
172
+ end
173
+ end
174
+
175
+ def read_included_file(entry_path)
176
+ if Utils.has_yaml_header?(entry_path)
177
+ conditionally_generate_entry(entry_path, site.pages, PageReader)
178
+ else
179
+ conditionally_generate_entry(entry_path, site.static_files, StaticFileReader)
180
+ end
181
+ end
182
+
183
+ def conditionally_generate_entry(entry_path, container, reader)
184
+ return if container.find { |item| site.in_source_dir(item.relative_path) == entry_path }
185
+
186
+ dir, files = File.split(entry_path)
187
+ dir.sub!(site.source, "")
188
+ files = Array(files)
189
+ container.concat(reader.new(site, dir).read(files))
190
+ end
191
+ end
192
+ end
@@ -1,22 +1,23 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- class CollectionReader
5
- SPECIAL_COLLECTIONS = %w(posts data).freeze
6
-
7
- attr_reader :site, :content
8
- def initialize(site)
9
- @site = site
10
- @content = {}
11
- end
12
-
13
- # Read in all collections specified in the configuration
14
- #
15
- # Returns nothing.
16
- def read
17
- site.collections.each_value do |collection|
18
- collection.read unless SPECIAL_COLLECTIONS.include?(collection.label)
19
- end
20
- end
21
- end
22
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class CollectionReader
5
+ SPECIAL_COLLECTIONS = %w(posts data).freeze
6
+
7
+ attr_reader :site, :content
8
+
9
+ def initialize(site)
10
+ @site = site
11
+ @content = {}
12
+ end
13
+
14
+ # Read in all collections specified in the configuration
15
+ #
16
+ # Returns nothing.
17
+ def read
18
+ site.collections.each_value do |collection|
19
+ collection.read unless SPECIAL_COLLECTIONS.include?(collection.label)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,75 +1,79 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- class DataReader
5
- attr_reader :site, :content
6
- def initialize(site)
7
- @site = site
8
- @content = {}
9
- @entry_filter = EntryFilter.new(site)
10
- end
11
-
12
- # Read all the files in <dir> and adds them to @content
13
- #
14
- # dir - The String relative path of the directory to read.
15
- #
16
- # Returns @content, a Hash of the .yaml, .yml,
17
- # .json, and .csv files in the base directory
18
- def read(dir)
19
- base = site.in_source_dir(dir)
20
- read_data_to(base, @content)
21
- @content
22
- end
23
-
24
- # Read and parse all .yaml, .yml, .json, .csv and .tsv
25
- # files under <dir> and add them to the <data> variable.
26
- #
27
- # dir - The string absolute path of the directory to read.
28
- # data - The variable to which data will be added.
29
- #
30
- # Returns nothing
31
- def read_data_to(dir, data)
32
- return unless File.directory?(dir) && !@entry_filter.symlink?(dir)
33
-
34
- entries = Dir.chdir(dir) do
35
- Dir["*.{yaml,yml,json,csv,tsv}"] + Dir["*"].select { |fn| File.directory?(fn) }
36
- end
37
-
38
- entries.each do |entry|
39
- path = @site.in_source_dir(dir, entry)
40
- next if @entry_filter.symlink?(path)
41
-
42
- if File.directory?(path)
43
- read_data_to(path, data[sanitize_filename(entry)] = {})
44
- else
45
- key = sanitize_filename(File.basename(entry, ".*"))
46
- data[key] = read_data_file(path)
47
- end
48
- end
49
- end
50
-
51
- # Determines how to read a data file.
52
- #
53
- # Returns the contents of the data file.
54
- def read_data_file(path)
55
- case File.extname(path).downcase
56
- when ".csv"
57
- CSV.read(path,
58
- :headers => true,
59
- :encoding => site.config["encoding"]).map(&:to_hash)
60
- when ".tsv"
61
- CSV.read(path,
62
- :col_sep => "\t",
63
- :headers => true,
64
- :encoding => site.config["encoding"]).map(&:to_hash)
65
- else
66
- SafeYAML.load_file(path)
67
- end
68
- end
69
-
70
- def sanitize_filename(name)
71
- name.gsub(%r![^\w\s-]+|(?<=^|\b\s)\s+(?=$|\s?\b)!, "")
72
- .gsub(%r!\s+!, "_")
73
- end
74
- end
75
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class DataReader
5
+ attr_reader :site, :content
6
+
7
+ def initialize(site)
8
+ @site = site
9
+ @content = {}
10
+ @entry_filter = EntryFilter.new(site)
11
+ @source_dir = site.in_source_dir("/")
12
+ end
13
+
14
+ # Read all the files in <dir> and adds them to @content
15
+ #
16
+ # dir - The String relative path of the directory to read.
17
+ #
18
+ # Returns @content, a Hash of the .yaml, .yml,
19
+ # .json, and .csv files in the base directory
20
+ def read(dir)
21
+ base = site.in_source_dir(dir)
22
+ read_data_to(base, @content)
23
+ @content
24
+ end
25
+
26
+ # Read and parse all .yaml, .yml, .json, .csv and .tsv
27
+ # files under <dir> and add them to the <data> variable.
28
+ #
29
+ # dir - The string absolute path of the directory to read.
30
+ # data - The variable to which data will be added.
31
+ #
32
+ # Returns nothing
33
+ def read_data_to(dir, data)
34
+ return unless File.directory?(dir) && !@entry_filter.symlink?(dir)
35
+
36
+ entries = Dir.chdir(dir) do
37
+ Dir["*.{yaml,yml,json,csv,tsv}"] + Dir["*"].select { |fn| File.directory?(fn) }
38
+ end
39
+
40
+ entries.each do |entry|
41
+ path = @site.in_source_dir(dir, entry)
42
+ next if @entry_filter.symlink?(path)
43
+
44
+ if File.directory?(path)
45
+ read_data_to(path, data[sanitize_filename(entry)] = {})
46
+ else
47
+ key = sanitize_filename(File.basename(entry, ".*"))
48
+ data[key] = read_data_file(path)
49
+ end
50
+ end
51
+ end
52
+
53
+ # Determines how to read a data file.
54
+ #
55
+ # Returns the contents of the data file.
56
+ def read_data_file(path)
57
+ Jekyll.logger.debug "Reading:", path.sub(@source_dir, "")
58
+
59
+ case File.extname(path).downcase
60
+ when ".csv"
61
+ CSV.read(path,
62
+ :headers => true,
63
+ :encoding => site.config["encoding"]).map(&:to_hash)
64
+ when ".tsv"
65
+ CSV.read(path,
66
+ :col_sep => "\t",
67
+ :headers => true,
68
+ :encoding => site.config["encoding"]).map(&:to_hash)
69
+ else
70
+ SafeYAML.load_file(path)
71
+ end
72
+ end
73
+
74
+ def sanitize_filename(name)
75
+ name.gsub(%r![^\w\s-]+|(?<=^|\b\s)\s+(?=$|\s?\b)!, "")
76
+ .gsub(%r!\s+!, "_")
77
+ end
78
+ end
79
+ end