jekyll 3.9.3 → 4.0.0.pre.alpha1

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +27 -50
  3. data/LICENSE +1 -1
  4. data/README.markdown +46 -17
  5. data/lib/blank_template/_config.yml +3 -0
  6. data/lib/blank_template/_layouts/default.html +12 -0
  7. data/lib/blank_template/_sass/main.scss +9 -0
  8. data/lib/blank_template/assets/css/main.scss +4 -0
  9. data/lib/blank_template/index.md +8 -0
  10. data/lib/jekyll/cache.rb +183 -0
  11. data/lib/jekyll/cleaner.rb +2 -1
  12. data/lib/jekyll/collection.rb +78 -8
  13. data/lib/jekyll/command.rb +31 -6
  14. data/lib/jekyll/commands/build.rb +11 -20
  15. data/lib/jekyll/commands/clean.rb +2 -0
  16. data/lib/jekyll/commands/doctor.rb +15 -8
  17. data/lib/jekyll/commands/help.rb +1 -1
  18. data/lib/jekyll/commands/new.rb +37 -42
  19. data/lib/jekyll/commands/new_theme.rb +30 -28
  20. data/lib/jekyll/commands/serve/live_reload_reactor.rb +6 -10
  21. data/lib/jekyll/commands/serve/servlet.rb +15 -19
  22. data/lib/jekyll/commands/serve.rb +46 -86
  23. data/lib/jekyll/configuration.rb +26 -26
  24. data/lib/jekyll/converters/identity.rb +18 -0
  25. data/lib/jekyll/converters/markdown/kramdown_parser.rb +1 -10
  26. data/lib/jekyll/converters/markdown.rb +49 -40
  27. data/lib/jekyll/converters/smartypants.rb +34 -14
  28. data/lib/jekyll/convertible.rb +11 -13
  29. data/lib/jekyll/deprecator.rb +1 -3
  30. data/lib/jekyll/document.rb +44 -41
  31. data/lib/jekyll/drops/collection_drop.rb +2 -3
  32. data/lib/jekyll/drops/document_drop.rb +2 -1
  33. data/lib/jekyll/drops/drop.rb +3 -6
  34. data/lib/jekyll/drops/excerpt_drop.rb +4 -0
  35. data/lib/jekyll/drops/site_drop.rb +4 -13
  36. data/lib/jekyll/drops/unified_payload_drop.rb +1 -0
  37. data/lib/jekyll/drops/url_drop.rb +1 -0
  38. data/lib/jekyll/entry_filter.rb +2 -1
  39. data/lib/jekyll/excerpt.rb +45 -34
  40. data/lib/jekyll/external.rb +10 -5
  41. data/lib/jekyll/filters/date_filters.rb +6 -3
  42. data/lib/jekyll/filters/grouping_filters.rb +1 -2
  43. data/lib/jekyll/filters/url_filters.rb +6 -1
  44. data/lib/jekyll/filters.rb +72 -31
  45. data/lib/jekyll/frontmatter_defaults.rb +35 -19
  46. data/lib/jekyll/hooks.rb +2 -3
  47. data/lib/jekyll/liquid_extensions.rb +0 -2
  48. data/lib/jekyll/liquid_renderer/file.rb +14 -3
  49. data/lib/jekyll/liquid_renderer/table.rb +67 -65
  50. data/lib/jekyll/liquid_renderer.rb +13 -1
  51. data/lib/jekyll/log_adapter.rb +5 -1
  52. data/lib/jekyll/mime.types +80 -195
  53. data/lib/jekyll/page.rb +10 -11
  54. data/lib/jekyll/page_without_a_file.rb +0 -4
  55. data/lib/jekyll/plugin.rb +5 -11
  56. data/lib/jekyll/plugin_manager.rb +2 -0
  57. data/lib/jekyll/reader.rb +38 -8
  58. data/lib/jekyll/readers/data_reader.rb +5 -5
  59. data/lib/jekyll/readers/layout_reader.rb +2 -12
  60. data/lib/jekyll/readers/post_reader.rb +29 -17
  61. data/lib/jekyll/readers/static_file_reader.rb +1 -1
  62. data/lib/jekyll/readers/theme_assets_reader.rb +7 -5
  63. data/lib/jekyll/regenerator.rb +4 -12
  64. data/lib/jekyll/renderer.rb +14 -25
  65. data/lib/jekyll/site.rb +78 -34
  66. data/lib/jekyll/static_file.rb +47 -11
  67. data/lib/jekyll/stevenson.rb +2 -3
  68. data/lib/jekyll/tags/highlight.rb +22 -52
  69. data/lib/jekyll/tags/include.rb +27 -48
  70. data/lib/jekyll/tags/link.rb +11 -7
  71. data/lib/jekyll/tags/post_url.rb +17 -16
  72. data/lib/jekyll/theme.rb +12 -23
  73. data/lib/jekyll/theme_builder.rb +91 -89
  74. data/lib/jekyll/url.rb +3 -2
  75. data/lib/jekyll/utils/ansi.rb +1 -1
  76. data/lib/jekyll/utils/exec.rb +0 -1
  77. data/lib/jekyll/utils/internet.rb +2 -4
  78. data/lib/jekyll/utils/platforms.rb +8 -8
  79. data/lib/jekyll/utils/thread_event.rb +1 -5
  80. data/lib/jekyll/utils/win_tz.rb +47 -18
  81. data/lib/jekyll/utils.rb +5 -4
  82. data/lib/jekyll/version.rb +1 -1
  83. data/lib/jekyll.rb +5 -0
  84. data/lib/site_template/.gitignore +2 -0
  85. data/lib/site_template/404.html +1 -0
  86. data/lib/site_template/_config.yml +17 -5
  87. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +5 -1
  88. data/lib/site_template/{about.md → about.markdown} +0 -0
  89. data/lib/site_template/{index.md → index.markdown} +0 -0
  90. data/lib/theme_template/gitignore.erb +1 -0
  91. data/rubocop/jekyll/assert_equal_literal_actual.rb +149 -0
  92. metadata +75 -48
  93. data/lib/jekyll/commands/serve/mime_types_charset.json +0 -71
  94. data/lib/jekyll/converters/markdown/rdiscount_parser.rb +0 -37
  95. data/lib/jekyll/converters/markdown/redcarpet_parser.rb +0 -112
  96. data/lib/jekyll/utils/rouge.rb +0 -22
@@ -3,9 +3,11 @@
3
3
  module Jekyll
4
4
  module Tags
5
5
  class Link < Liquid::Tag
6
+ include Jekyll::Filters::URLFilters
7
+
6
8
  class << self
7
9
  def tag_name
8
- self.name.split("::").last.downcase
10
+ name.split("::").last.downcase
9
11
  end
10
12
  end
11
13
 
@@ -16,19 +18,21 @@ module Jekyll
16
18
  end
17
19
 
18
20
  def render(context)
21
+ @context = context
19
22
  site = context.registers[:site]
23
+ relative_path = Liquid::Template.parse(@relative_path).render(context)
20
24
 
21
25
  site.each_site_file do |item|
22
- return item.url if item.relative_path == @relative_path
26
+ return relative_url(item) if item.relative_path == relative_path
23
27
  # This takes care of the case for static files that have a leading /
24
- return item.url if item.relative_path == "/#{@relative_path}"
28
+ return relative_url(item) if item.relative_path == "/#{relative_path}"
25
29
  end
26
30
 
27
- raise ArgumentError, <<-MSG
28
- Could not find document '#{@relative_path}' in tag '#{self.class.tag_name}'.
31
+ raise ArgumentError, <<~MSG
32
+ Could not find document '#{relative_path}' in tag '#{self.class.tag_name}'.
29
33
 
30
- Make sure the document exists and the path is correct.
31
- MSG
34
+ Make sure the document exists and the path is correct.
35
+ MSG
32
36
  end
33
37
  end
34
38
  end
@@ -3,7 +3,7 @@
3
3
  module Jekyll
4
4
  module Tags
5
5
  class PostComparer
6
- MATCHER = %r!^(.+/)*(\d+-\d+-\d+)-(.*)$!
6
+ MATCHER = %r!^(.+/)*(\d+-\d+-\d+)-(.*)$!.freeze
7
7
 
8
8
  attr_reader :path, :date, :slug, :name
9
9
 
@@ -13,7 +13,7 @@ module Jekyll
13
13
  all, @path, @date, @slug = *name.sub(%r!^/!, "").match(MATCHER)
14
14
  unless all
15
15
  raise Jekyll::Errors::InvalidPostNameError,
16
- "'#{name}' does not contain valid date and/or title."
16
+ "'#{name}' does not contain valid date and/or title."
17
17
  end
18
18
 
19
19
  escaped_slug = Regexp.escape(slug)
@@ -22,8 +22,10 @@ module Jekyll
22
22
  end
23
23
 
24
24
  def post_date
25
- @post_date ||= Utils.parse_date(date,
26
- "\"#{date}\" does not contain valid date and/or title.")
25
+ @post_date ||= Utils.parse_date(
26
+ date,
27
+ "'#{date}' does not contain valid date and/or title."
28
+ )
27
29
  end
28
30
 
29
31
  def ==(other)
@@ -38,6 +40,7 @@ module Jekyll
38
40
  end
39
41
 
40
42
  private
43
+
41
44
  # Construct the directory-aware post slug for a Jekyll::Post
42
45
  #
43
46
  # other - the Jekyll::Post
@@ -60,13 +63,11 @@ module Jekyll
60
63
  begin
61
64
  @post = PostComparer.new(@orig_post)
62
65
  rescue StandardError => e
63
- raise Jekyll::Errors::PostURLError, <<-MSG
64
- Could not parse name of post "#{@orig_post}" in tag 'post_url'.
65
-
66
- Make sure the post exists and the name is correct.
67
-
68
- #{e.class}: #{e.message}
69
- MSG
66
+ raise Jekyll::Errors::PostURLError, <<~MSG
67
+ Could not parse name of post "#{@orig_post}" in tag 'post_url'.
68
+ Make sure the post exists and the name is correct.
69
+ #{e.class}: #{e.message}
70
+ MSG
70
71
  end
71
72
  end
72
73
 
@@ -82,6 +83,7 @@ MSG
82
83
 
83
84
  site.posts.docs.each do |p|
84
85
  next unless @post.deprecated_equality p
86
+
85
87
  Jekyll::Deprecator.deprecation_message "A call to "\
86
88
  "'{% post_url #{@post.name} %}' did not match " \
87
89
  "a post using the new matching method of checking name " \
@@ -90,11 +92,10 @@ MSG
90
92
  return p.url
91
93
  end
92
94
 
93
- raise Jekyll::Errors::PostURLError, <<-MSG
94
- Could not find post "#{@orig_post}" in tag 'post_url'.
95
-
96
- Make sure the post exists and the name is correct.
97
- MSG
95
+ raise Jekyll::Errors::PostURLError, <<~MSG
96
+ Could not find post "#{@orig_post}" in tag 'post_url'.
97
+ Make sure the post exists and the name is correct.
98
+ MSG
98
99
  end
99
100
  end
100
101
  end
data/lib/jekyll/theme.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Jekyll
4
4
  class Theme
5
5
  extend Forwardable
6
- attr_reader :name
6
+ attr_reader :name
7
7
  def_delegator :gemspec, :version, :version
8
8
 
9
9
  def initialize(name)
@@ -23,23 +23,24 @@ module Jekyll
23
23
  end
24
24
 
25
25
  def includes_path
26
- @includes_path ||= path_for "_includes".freeze
26
+ @includes_path ||= path_for "_includes"
27
27
  end
28
28
 
29
29
  def layouts_path
30
- @layouts_path ||= path_for "_layouts".freeze
30
+ @layouts_path ||= path_for "_layouts"
31
31
  end
32
32
 
33
33
  def sass_path
34
- @sass_path ||= path_for "_sass".freeze
34
+ @sass_path ||= path_for "_sass"
35
35
  end
36
36
 
37
37
  def assets_path
38
- @assets_path ||= path_for "assets".freeze
38
+ @assets_path ||= path_for "assets"
39
39
  end
40
40
 
41
41
  def configure_sass
42
42
  return unless sass_path
43
+
43
44
  External.require_with_graceful_fail("sass") unless defined?(Sass)
44
45
  Sass.load_paths << sass_path
45
46
  end
@@ -56,33 +57,21 @@ module Jekyll
56
57
  end
57
58
 
58
59
  def realpath_for(folder)
59
- # This resolves all symlinks for the theme subfolder and then ensures
60
- # that the directory remains inside the theme root. This prevents the
61
- # use of symlinks for theme subfolders to escape the theme root.
60
+ # This resolves all symlinks for the theme subfolder and then ensures that the directory
61
+ # remains inside the theme root. This prevents the use of symlinks for theme subfolders to
62
+ # escape the theme root.
62
63
  # However, symlinks are allowed to point to other directories within the theme.
63
64
  Jekyll.sanitized_path(root, File.realpath(Jekyll.sanitized_path(root, folder.to_s)))
64
- rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP => e
65
- log_realpath_exception(e, folder)
65
+ rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP
66
+ Jekyll.logger.warn "Invalid theme folder:", folder
66
67
  nil
67
68
  end
68
69
 
69
- def log_realpath_exception(err, folder)
70
- return if err.is_a?(Errno::ENOENT)
71
-
72
- case err
73
- when Errno::EACCES
74
- Jekyll.logger.error "Theme error:", "Directory '#{folder}' is not accessible."
75
- when Errno::ELOOP
76
- Jekyll.logger.error "Theme error:",
77
- "Directory '#{folder}' includes a symbolic link loop."
78
- end
79
- end
80
-
81
70
  def gemspec
82
71
  @gemspec ||= Gem::Specification.find_by_name(name)
83
72
  rescue Gem::LoadError
84
73
  raise Jekyll::Errors::MissingDependencyException,
85
- "The #{name} theme could not be found."
74
+ "The #{name} theme could not be found."
86
75
  end
87
76
  end
88
77
  end
@@ -1,119 +1,121 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Jekyll::ThemeBuilder
4
- SCAFFOLD_DIRECTORIES = %w(
5
- assets _layouts _includes _sass
6
- ).freeze
7
-
8
- attr_reader :name, :path, :code_of_conduct
3
+ module Jekyll
4
+ class ThemeBuilder
5
+ SCAFFOLD_DIRECTORIES = %w(
6
+ assets _layouts _includes _sass
7
+ ).freeze
8
+
9
+ attr_reader :name, :path, :code_of_conduct
10
+
11
+ def initialize(theme_name, opts)
12
+ @name = theme_name.to_s.tr(" ", "_").squeeze("_")
13
+ @path = Pathname.new(File.expand_path(name, Dir.pwd))
14
+ @code_of_conduct = !!opts["code_of_conduct"]
15
+ end
9
16
 
10
- def initialize(theme_name, opts)
11
- @name = theme_name.to_s.tr(" ", "_").squeeze("_")
12
- @path = Pathname.new(File.expand_path(name, Dir.pwd))
13
- @code_of_conduct = !!opts["code_of_conduct"]
14
- end
17
+ def create!
18
+ create_directories
19
+ create_starter_files
20
+ create_gemspec
21
+ create_accessories
22
+ initialize_git_repo
23
+ end
15
24
 
16
- def create!
17
- create_directories
18
- create_starter_files
19
- create_gemspec
20
- create_accessories
21
- initialize_git_repo
22
- end
25
+ def user_name
26
+ @user_name ||= `git config user.name`.chomp
27
+ end
23
28
 
24
- def user_name
25
- @user_name ||= `git config user.name`.chomp
26
- end
29
+ def user_email
30
+ @user_email ||= `git config user.email`.chomp
31
+ end
27
32
 
28
- def user_email
29
- @user_email ||= `git config user.email`.chomp
30
- end
33
+ private
31
34
 
32
- private
35
+ def root
36
+ @root ||= Pathname.new(File.expand_path("../", __dir__))
37
+ end
33
38
 
34
- def root
35
- @root ||= Pathname.new(File.expand_path("../", __dir__))
36
- end
39
+ def template_file(filename)
40
+ [
41
+ root.join("theme_template", "#{filename}.erb"),
42
+ root.join("theme_template", filename.to_s),
43
+ ].find(&:exist?)
44
+ end
37
45
 
38
- def template_file(filename)
39
- [
40
- root.join("theme_template", "#{filename}.erb"),
41
- root.join("theme_template", filename.to_s),
42
- ].find(&:exist?)
43
- end
46
+ def template(filename)
47
+ erb.render(template_file(filename).read)
48
+ end
44
49
 
45
- def template(filename)
46
- erb.render(template_file(filename).read)
47
- end
50
+ def erb
51
+ @erb ||= ERBRenderer.new(self)
52
+ end
48
53
 
49
- def erb
50
- @erb ||= ERBRenderer.new(self)
51
- end
54
+ def mkdir_p(directories)
55
+ Array(directories).each do |directory|
56
+ full_path = path.join(directory)
57
+ Jekyll.logger.info "create", full_path.to_s
58
+ FileUtils.mkdir_p(full_path)
59
+ end
60
+ end
52
61
 
53
- def mkdir_p(directories)
54
- Array(directories).each do |directory|
55
- full_path = path.join(directory)
62
+ def write_file(filename, contents)
63
+ full_path = path.join(filename)
56
64
  Jekyll.logger.info "create", full_path.to_s
57
- FileUtils.mkdir_p(full_path)
65
+ File.write(full_path, contents)
58
66
  end
59
- end
60
-
61
- def write_file(filename, contents)
62
- full_path = path.join(filename)
63
- Jekyll.logger.info "create", full_path.to_s
64
- File.write(full_path, contents)
65
- end
66
67
 
67
- def create_directories
68
- mkdir_p(SCAFFOLD_DIRECTORIES)
69
- end
68
+ def create_directories
69
+ mkdir_p(SCAFFOLD_DIRECTORIES)
70
+ end
70
71
 
71
- def create_starter_files
72
- %w(page post default).each do |layout|
73
- write_file("_layouts/#{layout}.html", template("_layouts/#{layout}.html"))
72
+ def create_starter_files
73
+ %w(page post default).each do |layout|
74
+ write_file("_layouts/#{layout}.html", template("_layouts/#{layout}.html"))
75
+ end
74
76
  end
75
- end
76
77
 
77
- def create_gemspec
78
- write_file("Gemfile", template("Gemfile"))
79
- write_file("#{name}.gemspec", template("theme.gemspec"))
80
- end
78
+ def create_gemspec
79
+ write_file("Gemfile", template("Gemfile"))
80
+ write_file("#{name}.gemspec", template("theme.gemspec"))
81
+ end
81
82
 
82
- def create_accessories
83
- accessories = %w(README.md LICENSE.txt)
84
- accessories << "CODE_OF_CONDUCT.md" if code_of_conduct
85
- accessories.each do |filename|
86
- write_file(filename, template(filename))
83
+ def create_accessories
84
+ accessories = %w(README.md LICENSE.txt)
85
+ accessories << "CODE_OF_CONDUCT.md" if code_of_conduct
86
+ accessories.each do |filename|
87
+ write_file(filename, template(filename))
88
+ end
87
89
  end
88
- end
89
90
 
90
- def initialize_git_repo
91
- Jekyll.logger.info "initialize", path.join(".git").to_s
92
- Dir.chdir(path.to_s) { `git init` }
93
- write_file(".gitignore", template("gitignore"))
94
- end
91
+ def initialize_git_repo
92
+ Jekyll.logger.info "initialize", path.join(".git").to_s
93
+ Dir.chdir(path.to_s) { `git init` }
94
+ write_file(".gitignore", template("gitignore"))
95
+ end
95
96
 
96
- class ERBRenderer
97
- extend Forwardable
97
+ class ERBRenderer
98
+ extend Forwardable
98
99
 
99
- def_delegator :@theme_builder, :name, :theme_name
100
- def_delegator :@theme_builder, :user_name, :user_name
101
- def_delegator :@theme_builder, :user_email, :user_email
100
+ def_delegator :@theme_builder, :name, :theme_name
101
+ def_delegator :@theme_builder, :user_name, :user_name
102
+ def_delegator :@theme_builder, :user_email, :user_email
102
103
 
103
- def initialize(theme_builder)
104
- @theme_builder = theme_builder
105
- end
104
+ def initialize(theme_builder)
105
+ @theme_builder = theme_builder
106
+ end
106
107
 
107
- def jekyll_version_with_minor
108
- Jekyll::VERSION.split(".").take(2).join(".")
109
- end
108
+ def jekyll_version_with_minor
109
+ Jekyll::VERSION.split(".").take(2).join(".")
110
+ end
110
111
 
111
- def theme_directories
112
- SCAFFOLD_DIRECTORIES
113
- end
112
+ def theme_directories
113
+ SCAFFOLD_DIRECTORIES
114
+ end
114
115
 
115
- def render(contents)
116
- ERB.new(contents).result binding
116
+ def render(contents)
117
+ ERB.new(contents).result binding
118
+ end
117
119
  end
118
120
  end
119
121
  end
data/lib/jekyll/url.rb CHANGED
@@ -68,6 +68,7 @@ module Jekyll
68
68
  def generate_url_from_hash(template)
69
69
  @placeholders.inject(template) do |result, token|
70
70
  break result if result.index(":").nil?
71
+
71
72
  if token.last.nil?
72
73
  # Remove leading "/" to avoid generating urls with `//`
73
74
  result.gsub("/:#{token.first}", "")
@@ -98,8 +99,8 @@ module Jekyll
98
99
  winner = pool.find { |key| @placeholders.key?(key) }
99
100
  if winner.nil?
100
101
  raise NoMethodError,
101
- "The URL template doesn't have #{pool.join(" or ")} keys. "\
102
- "Check your permalink template!"
102
+ "The URL template doesn't have #{pool.join(" or ")} keys. "\
103
+ "Check your permalink template!"
103
104
  end
104
105
 
105
106
  value = @placeholders[winner]
@@ -6,7 +6,7 @@ module Jekyll
6
6
  extend self
7
7
 
8
8
  ESCAPE = format("%c", 27)
9
- MATCH = %r!#{ESCAPE}\[(?:\d+)(?:;\d+)*(j|k|m|s|u|A|B|G)|\e\(B\e\[m!ix
9
+ MATCH = %r!#{ESCAPE}\[(?:\d+)(?:;\d+)*(j|k|m|s|u|A|B|G)|\e\(B\e\[m!ix.freeze
10
10
  COLORS = {
11
11
  :red => 31,
12
12
  :green => 32,
@@ -21,7 +21,6 @@ module Jekyll
21
21
  [stdin, stdout, stderr].each(&:close)
22
22
  [process.value, out + err]
23
23
  end
24
-
25
24
  end
26
25
  end
27
26
  end
@@ -3,7 +3,6 @@
3
3
  module Jekyll
4
4
  module Utils
5
5
  module Internet
6
-
7
6
  # Public: Determine whether the present device has a connection to
8
7
  # the Internet. This allows plugin writers which require the outside
9
8
  # world to have a neat fallback mechanism for offline building.
@@ -18,13 +17,13 @@ module Jekyll
18
17
  # end
19
18
  #
20
19
  # Returns true if a DNS call can successfully be made, or false if not.
20
+
21
21
  module_function
22
+
22
23
  def connected?
23
24
  !dns("example.com").nil?
24
25
  end
25
26
 
26
- private
27
- module_function
28
27
  def dns(domain)
29
28
  require "resolv"
30
29
  Resolv::DNS.open do |resolver|
@@ -33,7 +32,6 @@ module Jekyll
33
32
  rescue Resolv::ResolvError, Resolv::ResolvTimeout
34
33
  nil
35
34
  end
36
-
37
35
  end
38
36
  end
39
37
  end
@@ -31,7 +31,7 @@ module Jekyll
31
31
  # --
32
32
 
33
33
  alias_method :really_windows?, \
34
- :vanilla_windows?
34
+ :vanilla_windows?
35
35
 
36
36
  #
37
37
 
@@ -68,14 +68,14 @@ module Jekyll
68
68
  #
69
69
 
70
70
  private
71
+
71
72
  def proc_version
72
- @proc_version ||= begin
73
- File.read(
74
- "/proc/version"
75
- ).downcase
76
- rescue Errno::ENOENT
77
- nil
78
- end
73
+ @proc_version ||=
74
+ begin
75
+ Pathutil.new("/proc/version").read
76
+ rescue Errno::ENOENT, Errno::EACCES
77
+ nil
78
+ end
79
79
  end
80
80
  end
81
81
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "thread"
4
-
5
3
  module Jekyll
6
4
  module Utils
7
5
  # Based on the pattern and code from
@@ -25,9 +23,7 @@ module Jekyll
25
23
 
26
24
  def wait
27
25
  @lock.synchronize do
28
- unless @flag
29
- @cond.wait(@lock)
30
- end
26
+ @cond.wait(@lock) unless @flag
31
27
  end
32
28
  end
33
29
  end
@@ -11,35 +11,64 @@ module Jekyll
11
11
  # timezone - the IANA Time Zone specified in "_config.yml"
12
12
  #
13
13
  # Returns a string that ultimately re-defines ENV["TZ"] in Windows
14
- def calculate(timezone, now = Time.now)
14
+ def calculate(timezone)
15
15
  External.require_with_graceful_fail("tzinfo") unless defined?(TZInfo)
16
16
  tz = TZInfo::Timezone.get(timezone)
17
-
18
- #
19
- # Use period_for_utc and utc_total_offset instead of
20
- # period_for and observed_utc_offset for compatibility with tzinfo v1.
21
- offset = tz.period_for_utc(now.getutc).utc_total_offset
22
-
17
+ difference = Time.now.to_i - tz.now.to_i
23
18
  #
24
19
  # POSIX style definition reverses the offset sign.
25
20
  # e.g. Eastern Standard Time (EST) that is 5Hrs. to the 'west' of Prime Meridian
26
21
  # is denoted as:
27
22
  # EST+5 (or) EST+05:00
28
- # Reference: https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
29
- sign = offset.positive? ? "-" : "+"
30
-
31
- rational_hours = offset.abs.to_r / 3600
32
- hours = rational_hours.to_i
33
- minutes = ((rational_hours - hours) * 60).to_i
34
-
23
+ # Reference: http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
24
+ sign = difference.negative? ? "-" : "+"
25
+ offset = sign == "-" ? "+" : "-" unless difference.zero?
35
26
  #
36
- # Format the hours and minutes as two-digit numbers.
37
- time = format("%<hours>02d:%<minutes>02d", :hours => hours, :minutes => minutes)
27
+ # convert the difference (in seconds) to hours, as a rational number, and perform
28
+ # a modulo operation on it.
29
+ modulo = modulo_of(rational_hour(difference))
30
+ #
31
+ # Format the hour as a two-digit number.
32
+ # Establish the minutes based on modulo expression.
33
+ hh = format("%02d", absolute_hour(difference).ceil)
34
+ mm = modulo.zero? ? "00" : "30"
38
35
 
39
- Jekyll.logger.debug "Timezone:", "#{timezone} #{sign}#{time}"
36
+ Jekyll.logger.debug "Timezone:", "#{timezone} #{offset}#{hh}:#{mm}"
40
37
  #
41
38
  # Note: The 3-letter-word below doesn't have a particular significance.
42
- "WTZ#{sign}#{time}"
39
+ "WTZ#{sign}#{hh}:#{mm}"
40
+ end
41
+
42
+ private
43
+
44
+ # Private: Convert given seconds to an hour as a rational number.
45
+ #
46
+ # seconds - supplied as an integer, it is converted to a rational number.
47
+ # 3600 - no. of seconds in an hour.
48
+ #
49
+ # Returns a rational number.
50
+ def rational_hour(seconds)
51
+ seconds.to_r / 3600
52
+ end
53
+
54
+ # Private: Convert given seconds to an hour as an absolute number.
55
+ #
56
+ # seconds - supplied as an integer, it is converted to its absolute.
57
+ # 3600 - no. of seconds in an hour.
58
+ #
59
+ # Returns an integer.
60
+ def absolute_hour(seconds)
61
+ seconds.abs / 3600
62
+ end
63
+
64
+ # Private: Perform a modulo operation on a given fraction.
65
+ #
66
+ # fraction - supplied as a rational number, its numerator is divided
67
+ # by its denominator and the remainder returned.
68
+ #
69
+ # Returns an integer.
70
+ def modulo_of(fraction)
71
+ fraction.numerator % fraction.denominator
43
72
  end
44
73
  end
45
74
  end
data/lib/jekyll/utils.rb CHANGED
@@ -7,7 +7,6 @@ module Jekyll
7
7
  autoload :Exec, "jekyll/utils/exec"
8
8
  autoload :Internet, "jekyll/utils/internet"
9
9
  autoload :Platforms, "jekyll/utils/platforms"
10
- autoload :Rouge, "jekyll/utils/rouge"
11
10
  autoload :ThreadEvent, "jekyll/utils/thread_event"
12
11
  autoload :WinTZ, "jekyll/utils/win_tz"
13
12
 
@@ -153,6 +152,7 @@ module Jekyll
153
152
  # Returns true is the string contains sequences of `{%` or `{{`
154
153
  def has_liquid_construct?(content)
155
154
  return false if content.nil? || content.empty?
155
+
156
156
  content.include?("{%") || content.include?("{{")
157
157
  end
158
158
  # rubocop: enable PredicateName
@@ -222,6 +222,7 @@ module Jekyll
222
222
  slug.gsub!(%r!^\-|\-$!i, "")
223
223
 
224
224
  slug.downcase! unless cased
225
+ Jekyll.logger.warn("Warning:", "Empty `slug` generated for '#{string}'.") if slug.empty?
225
226
  slug
226
227
  end
227
228
 
@@ -293,8 +294,10 @@ module Jekyll
293
294
  # Returns matched pathes
294
295
  def safe_glob(dir, patterns, flags = 0)
295
296
  return [] unless Dir.exist?(dir)
297
+
296
298
  pattern = File.join(Array(patterns))
297
299
  return [dir] if pattern.empty?
300
+
298
301
  Dir.chdir(dir) do
299
302
  Dir.glob(pattern, flags).map { |f| File.join(dir, f) }
300
303
  end
@@ -314,6 +317,7 @@ module Jekyll
314
317
  end
315
318
 
316
319
  private
320
+
317
321
  def merge_values(target, overwrite)
318
322
  target.merge!(overwrite) do |_key, old_val, new_val|
319
323
  if new_val.nil?
@@ -326,14 +330,12 @@ module Jekyll
326
330
  end
327
331
  end
328
332
 
329
- private
330
333
  def merge_default_proc(target, overwrite)
331
334
  if target.is_a?(Hash) && overwrite.is_a?(Hash) && target.default_proc.nil?
332
335
  target.default_proc = overwrite.default_proc
333
336
  end
334
337
  end
335
338
 
336
- private
337
339
  def duplicate_frozen_values(target)
338
340
  target.each do |key, val|
339
341
  target[key] = val.dup if val.frozen? && duplicable?(val)
@@ -344,7 +346,6 @@ module Jekyll
344
346
  #
345
347
  # See Utils#slugify for a description of the character sequence specified
346
348
  # by each mode.
347
- private
348
349
  def replace_character_sequence_with_hyphen(string, mode: "default")
349
350
  replaceable_char =
350
351
  case mode