jekyll 4.2.1 → 4.3.2

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +474 -350
  3. data/LICENSE +21 -21
  4. data/README.markdown +83 -86
  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 → base.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 +186 -190
  12. data/lib/jekyll/cleaner.rb +111 -111
  13. data/lib/jekyll/collection.rb +310 -309
  14. data/lib/jekyll/command.rb +105 -105
  15. data/lib/jekyll/commands/build.rb +82 -93
  16. data/lib/jekyll/commands/clean.rb +44 -45
  17. data/lib/jekyll/commands/doctor.rb +177 -177
  18. data/lib/jekyll/commands/help.rb +34 -34
  19. data/lib/jekyll/commands/new.rb +168 -169
  20. data/lib/jekyll/commands/new_theme.rb +39 -40
  21. data/lib/jekyll/commands/serve/live_reload_reactor.rb +119 -122
  22. data/lib/jekyll/commands/serve/livereload_assets/livereload.js +1183 -1183
  23. data/lib/jekyll/commands/serve/mime_types_charset.json +71 -0
  24. data/lib/jekyll/commands/serve/servlet.rb +206 -202
  25. data/lib/jekyll/commands/serve/websockets.rb +81 -81
  26. data/lib/jekyll/commands/serve.rb +367 -362
  27. data/lib/jekyll/configuration.rb +313 -313
  28. data/lib/jekyll/converter.rb +54 -54
  29. data/lib/jekyll/converters/identity.rb +41 -41
  30. data/lib/jekyll/converters/markdown/kramdown_parser.rb +197 -199
  31. data/lib/jekyll/converters/markdown.rb +113 -113
  32. data/lib/jekyll/converters/smartypants.rb +70 -70
  33. data/lib/jekyll/convertible.rb +257 -257
  34. data/lib/jekyll/deprecator.rb +50 -50
  35. data/lib/jekyll/document.rb +543 -544
  36. data/lib/jekyll/drops/collection_drop.rb +20 -20
  37. data/lib/jekyll/drops/document_drop.rb +74 -70
  38. data/lib/jekyll/drops/drop.rb +293 -293
  39. data/lib/jekyll/drops/excerpt_drop.rb +23 -19
  40. data/lib/jekyll/drops/jekyll_drop.rb +32 -32
  41. data/lib/jekyll/drops/site_drop.rb +66 -66
  42. data/lib/jekyll/drops/static_file_drop.rb +14 -14
  43. data/lib/jekyll/drops/theme_drop.rb +36 -0
  44. data/lib/jekyll/drops/unified_payload_drop.rb +30 -26
  45. data/lib/jekyll/drops/url_drop.rb +140 -140
  46. data/lib/jekyll/entry_filter.rb +117 -121
  47. data/lib/jekyll/errors.rb +20 -20
  48. data/lib/jekyll/excerpt.rb +200 -201
  49. data/lib/jekyll/external.rb +75 -79
  50. data/lib/jekyll/filters/date_filters.rb +110 -110
  51. data/lib/jekyll/filters/grouping_filters.rb +64 -64
  52. data/lib/jekyll/filters/url_filters.rb +98 -98
  53. data/lib/jekyll/filters.rb +532 -535
  54. data/lib/jekyll/frontmatter_defaults.rb +238 -240
  55. data/lib/jekyll/generator.rb +5 -5
  56. data/lib/jekyll/hooks.rb +107 -107
  57. data/lib/jekyll/inclusion.rb +32 -32
  58. data/lib/jekyll/layout.rb +55 -67
  59. data/lib/jekyll/liquid_extensions.rb +22 -22
  60. data/lib/jekyll/liquid_renderer/file.rb +77 -77
  61. data/lib/jekyll/liquid_renderer/table.rb +45 -55
  62. data/lib/jekyll/liquid_renderer.rb +80 -80
  63. data/lib/jekyll/log_adapter.rb +151 -151
  64. data/lib/jekyll/mime.types +939 -866
  65. data/lib/jekyll/page.rb +215 -217
  66. data/lib/jekyll/page_excerpt.rb +25 -25
  67. data/lib/jekyll/page_without_a_file.rb +14 -14
  68. data/lib/jekyll/path_manager.rb +74 -74
  69. data/lib/jekyll/plugin.rb +92 -92
  70. data/lib/jekyll/plugin_manager.rb +123 -115
  71. data/lib/jekyll/profiler.rb +51 -58
  72. data/lib/jekyll/publisher.rb +23 -23
  73. data/lib/jekyll/reader.rb +209 -192
  74. data/lib/jekyll/readers/collection_reader.rb +23 -23
  75. data/lib/jekyll/readers/data_reader.rb +113 -79
  76. data/lib/jekyll/readers/layout_reader.rb +62 -62
  77. data/lib/jekyll/readers/page_reader.rb +25 -25
  78. data/lib/jekyll/readers/post_reader.rb +85 -85
  79. data/lib/jekyll/readers/static_file_reader.rb +25 -25
  80. data/lib/jekyll/readers/theme_assets_reader.rb +52 -52
  81. data/lib/jekyll/regenerator.rb +195 -195
  82. data/lib/jekyll/related_posts.rb +52 -52
  83. data/lib/jekyll/renderer.rb +263 -265
  84. data/lib/jekyll/site.rb +576 -551
  85. data/lib/jekyll/static_file.rb +205 -208
  86. data/lib/jekyll/stevenson.rb +60 -60
  87. data/lib/jekyll/tags/highlight.rb +114 -110
  88. data/lib/jekyll/tags/include.rb +275 -275
  89. data/lib/jekyll/tags/link.rb +42 -42
  90. data/lib/jekyll/tags/post_url.rb +106 -106
  91. data/lib/jekyll/theme.rb +90 -86
  92. data/lib/jekyll/theme_builder.rb +121 -121
  93. data/lib/jekyll/url.rb +167 -167
  94. data/lib/jekyll/utils/ansi.rb +57 -57
  95. data/lib/jekyll/utils/exec.rb +26 -26
  96. data/lib/jekyll/utils/internet.rb +37 -37
  97. data/lib/jekyll/utils/platforms.rb +67 -67
  98. data/lib/jekyll/utils/thread_event.rb +31 -31
  99. data/lib/jekyll/utils/win_tz.rb +46 -75
  100. data/lib/jekyll/utils.rb +371 -367
  101. data/lib/jekyll/version.rb +5 -5
  102. data/lib/jekyll.rb +195 -195
  103. data/lib/site_template/.gitignore +5 -5
  104. data/lib/site_template/404.html +25 -25
  105. data/lib/site_template/_config.yml +55 -55
  106. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +29 -29
  107. data/lib/site_template/about.markdown +18 -18
  108. data/lib/site_template/index.markdown +6 -6
  109. data/lib/theme_template/CODE_OF_CONDUCT.md.erb +74 -74
  110. data/lib/theme_template/Gemfile +4 -4
  111. data/lib/theme_template/LICENSE.txt.erb +21 -21
  112. data/lib/theme_template/README.md.erb +50 -52
  113. data/lib/theme_template/_layouts/default.html +1 -1
  114. data/lib/theme_template/_layouts/page.html +5 -5
  115. data/lib/theme_template/_layouts/post.html +5 -5
  116. data/lib/theme_template/example/_config.yml.erb +1 -1
  117. data/lib/theme_template/example/_post.md +12 -12
  118. data/lib/theme_template/example/index.html +14 -14
  119. data/lib/theme_template/example/style.scss +7 -7
  120. data/lib/theme_template/gitignore.erb +6 -6
  121. data/lib/theme_template/theme.gemspec.erb +16 -16
  122. data/rubocop/jekyll/assert_equal_literal_actual.rb +149 -149
  123. data/rubocop/jekyll/no_p_allowed.rb +23 -23
  124. data/rubocop/jekyll/no_puts_allowed.rb +23 -23
  125. data/rubocop/jekyll.rb +5 -5
  126. metadata +64 -18
@@ -1,110 +1,110 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- module Filters
5
- module DateFilters
6
- # Format a date in short format e.g. "27 Jan 2011".
7
- # Ordinal format is also supported, in both the UK
8
- # (e.g. "27th Jan 2011") and US ("e.g. Jan 27th, 2011") formats.
9
- # UK format is the default.
10
- #
11
- # date - the Time to format.
12
- # type - if "ordinal" the returned String will be in ordinal format
13
- # style - if "US" the returned String will be in US format.
14
- # Otherwise it will be in UK format.
15
- #
16
- # Returns the formatting String.
17
- def date_to_string(date, type = nil, style = nil)
18
- stringify_date(date, "%b", type, style)
19
- end
20
-
21
- # Format a date in long format e.g. "27 January 2011".
22
- # Ordinal format is also supported, in both the UK
23
- # (e.g. "27th January 2011") and US ("e.g. January 27th, 2011") formats.
24
- # UK format is the default.
25
- #
26
- # date - the Time to format.
27
- # type - if "ordinal" the returned String will be in ordinal format
28
- # style - if "US" the returned String will be in US format.
29
- # Otherwise it will be in UK format.
30
- #
31
- # Returns the formatted String.
32
- def date_to_long_string(date, type = nil, style = nil)
33
- stringify_date(date, "%B", type, style)
34
- end
35
-
36
- # Format a date for use in XML.
37
- #
38
- # date - The Time to format.
39
- #
40
- # Examples
41
- #
42
- # date_to_xmlschema(Time.now)
43
- # # => "2011-04-24T20:34:46+08:00"
44
- #
45
- # Returns the formatted String.
46
- def date_to_xmlschema(date)
47
- return date if date.to_s.empty?
48
-
49
- time(date).xmlschema
50
- end
51
-
52
- # Format a date according to RFC-822
53
- #
54
- # date - The Time to format.
55
- #
56
- # Examples
57
- #
58
- # date_to_rfc822(Time.now)
59
- # # => "Sun, 24 Apr 2011 12:34:46 +0000"
60
- #
61
- # Returns the formatted String.
62
- def date_to_rfc822(date)
63
- return date if date.to_s.empty?
64
-
65
- time(date).rfc822
66
- end
67
-
68
- private
69
-
70
- # month_type: Notations that evaluate to 'Month' via `Time#strftime` ("%b", "%B")
71
- # type: nil (default) or "ordinal"
72
- # style: nil (default) or "US"
73
- #
74
- # Returns a stringified date or the empty input.
75
- def stringify_date(date, month_type, type = nil, style = nil)
76
- return date if date.to_s.empty?
77
-
78
- time = time(date)
79
- if type == "ordinal"
80
- day = time.day
81
- ordinal_day = "#{day}#{ordinal(day)}"
82
- return time.strftime("#{month_type} #{ordinal_day}, %Y") if style == "US"
83
-
84
- return time.strftime("#{ordinal_day} #{month_type} %Y")
85
- end
86
- time.strftime("%d #{month_type} %Y")
87
- end
88
-
89
- def ordinal(number)
90
- return "th" if (11..13).cover?(number)
91
-
92
- case number % 10
93
- when 1 then "st"
94
- when 2 then "nd"
95
- when 3 then "rd"
96
- else "th"
97
- end
98
- end
99
-
100
- def time(input)
101
- date = Liquid::Utils.to_date(input)
102
- unless date.respond_to?(:to_time)
103
- raise Errors::InvalidDateError,
104
- "Invalid Date: '#{input.inspect}' is not a valid datetime."
105
- end
106
- date.to_time.dup.localtime
107
- end
108
- end
109
- end
110
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Filters
5
+ module DateFilters
6
+ # Format a date in short format e.g. "27 Jan 2011".
7
+ # Ordinal format is also supported, in both the UK
8
+ # (e.g. "27th Jan 2011") and US ("e.g. Jan 27th, 2011") formats.
9
+ # UK format is the default.
10
+ #
11
+ # date - the Time to format.
12
+ # type - if "ordinal" the returned String will be in ordinal format
13
+ # style - if "US" the returned String will be in US format.
14
+ # Otherwise it will be in UK format.
15
+ #
16
+ # Returns the formatting String.
17
+ def date_to_string(date, type = nil, style = nil)
18
+ stringify_date(date, "%b", type, style)
19
+ end
20
+
21
+ # Format a date in long format e.g. "27 January 2011".
22
+ # Ordinal format is also supported, in both the UK
23
+ # (e.g. "27th January 2011") and US ("e.g. January 27th, 2011") formats.
24
+ # UK format is the default.
25
+ #
26
+ # date - the Time to format.
27
+ # type - if "ordinal" the returned String will be in ordinal format
28
+ # style - if "US" the returned String will be in US format.
29
+ # Otherwise it will be in UK format.
30
+ #
31
+ # Returns the formatted String.
32
+ def date_to_long_string(date, type = nil, style = nil)
33
+ stringify_date(date, "%B", type, style)
34
+ end
35
+
36
+ # Format a date for use in XML.
37
+ #
38
+ # date - The Time to format.
39
+ #
40
+ # Examples
41
+ #
42
+ # date_to_xmlschema(Time.now)
43
+ # # => "2011-04-24T20:34:46+08:00"
44
+ #
45
+ # Returns the formatted String.
46
+ def date_to_xmlschema(date)
47
+ return date if date.to_s.empty?
48
+
49
+ time(date).xmlschema
50
+ end
51
+
52
+ # Format a date according to RFC-822
53
+ #
54
+ # date - The Time to format.
55
+ #
56
+ # Examples
57
+ #
58
+ # date_to_rfc822(Time.now)
59
+ # # => "Sun, 24 Apr 2011 12:34:46 +0000"
60
+ #
61
+ # Returns the formatted String.
62
+ def date_to_rfc822(date)
63
+ return date if date.to_s.empty?
64
+
65
+ time(date).rfc822
66
+ end
67
+
68
+ private
69
+
70
+ # month_type: Notations that evaluate to 'Month' via `Time#strftime` ("%b", "%B")
71
+ # type: nil (default) or "ordinal"
72
+ # style: nil (default) or "US"
73
+ #
74
+ # Returns a stringified date or the empty input.
75
+ def stringify_date(date, month_type, type = nil, style = nil)
76
+ return date if date.to_s.empty?
77
+
78
+ time = time(date)
79
+ if type == "ordinal"
80
+ day = time.day
81
+ ordinal_day = "#{day}#{ordinal(day)}"
82
+ return time.strftime("#{month_type} #{ordinal_day}, %Y") if style == "US"
83
+
84
+ return time.strftime("#{ordinal_day} #{month_type} %Y")
85
+ end
86
+ time.strftime("%d #{month_type} %Y")
87
+ end
88
+
89
+ def ordinal(number)
90
+ return "th" if (11..13).cover?(number)
91
+
92
+ case number % 10
93
+ when 1 then "st"
94
+ when 2 then "nd"
95
+ when 3 then "rd"
96
+ else "th"
97
+ end
98
+ end
99
+
100
+ def time(input)
101
+ date = Liquid::Utils.to_date(input)
102
+ unless date.respond_to?(:to_time)
103
+ raise Errors::InvalidDateError,
104
+ "Invalid Date: '#{input.inspect}' is not a valid datetime."
105
+ end
106
+ date.to_time.dup.localtime
107
+ end
108
+ end
109
+ end
110
+ end
@@ -1,64 +1,64 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- module Filters
5
- module GroupingFilters
6
- # Group an array of items by a property
7
- #
8
- # input - the inputted Enumerable
9
- # property - the property
10
- #
11
- # Returns an array of Hashes, each looking something like this:
12
- # {"name" => "larry"
13
- # "items" => [...] } # all the items where `property` == "larry"
14
- def group_by(input, property)
15
- if groupable?(input)
16
- groups = input.group_by { |item| item_property(item, property).to_s }
17
- grouped_array(groups)
18
- else
19
- input
20
- end
21
- end
22
-
23
- # Group an array of items by an expression
24
- #
25
- # input - the object array
26
- # variable - the variable to assign each item to in the expression
27
- # expression -a Liquid comparison expression passed in as a string
28
- #
29
- # Returns the filtered array of objects
30
- def group_by_exp(input, variable, expression)
31
- return input unless groupable?(input)
32
-
33
- parsed_expr = parse_expression(expression)
34
- @context.stack do
35
- groups = input.group_by do |item|
36
- @context[variable] = item
37
- parsed_expr.render(@context)
38
- end
39
- grouped_array(groups)
40
- end
41
- end
42
-
43
- private
44
-
45
- def parse_expression(str)
46
- Liquid::Variable.new(str, Liquid::ParseContext.new)
47
- end
48
-
49
- def groupable?(element)
50
- element.respond_to?(:group_by)
51
- end
52
-
53
- def grouped_array(groups)
54
- groups.each_with_object([]) do |item, array|
55
- array << {
56
- "name" => item.first,
57
- "items" => item.last,
58
- "size" => item.last.size,
59
- }
60
- end
61
- end
62
- end
63
- end
64
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Filters
5
+ module GroupingFilters
6
+ # Group an array of items by a property
7
+ #
8
+ # input - the inputted Enumerable
9
+ # property - the property
10
+ #
11
+ # Returns an array of Hashes, each looking something like this:
12
+ # {"name" => "larry"
13
+ # "items" => [...] } # all the items where `property` == "larry"
14
+ def group_by(input, property)
15
+ if groupable?(input)
16
+ groups = input.group_by { |item| item_property(item, property).to_s }
17
+ grouped_array(groups)
18
+ else
19
+ input
20
+ end
21
+ end
22
+
23
+ # Group an array of items by an expression
24
+ #
25
+ # input - the object array
26
+ # variable - the variable to assign each item to in the expression
27
+ # expression -a Liquid comparison expression passed in as a string
28
+ #
29
+ # Returns the filtered array of objects
30
+ def group_by_exp(input, variable, expression)
31
+ return input unless groupable?(input)
32
+
33
+ parsed_expr = parse_expression(expression)
34
+ @context.stack do
35
+ groups = input.group_by do |item|
36
+ @context[variable] = item
37
+ parsed_expr.render(@context)
38
+ end
39
+ grouped_array(groups)
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def parse_expression(str)
46
+ Liquid::Variable.new(str, Liquid::ParseContext.new)
47
+ end
48
+
49
+ def groupable?(element)
50
+ element.respond_to?(:group_by)
51
+ end
52
+
53
+ def grouped_array(groups)
54
+ groups.each_with_object([]) do |item, array|
55
+ array << {
56
+ "name" => item.first,
57
+ "items" => item.last,
58
+ "size" => item.last.size,
59
+ }
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,98 +1,98 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- module Filters
5
- module URLFilters
6
- # Produces an absolute URL based on site.url and site.baseurl.
7
- #
8
- # input - the URL to make absolute.
9
- #
10
- # Returns the absolute URL as a String.
11
- def absolute_url(input)
12
- return if input.nil?
13
-
14
- cache = if input.is_a?(String)
15
- (@context.registers[:site].filter_cache[:absolute_url] ||= {})
16
- else
17
- (@context.registers[:cached_absolute_url] ||= {})
18
- end
19
- cache[input] ||= compute_absolute_url(input)
20
-
21
- # Duplicate cached string so that the cached value is never mutated by
22
- # a subsequent filter.
23
- cache[input].dup
24
- end
25
-
26
- # Produces a URL relative to the domain root based on site.baseurl
27
- # unless it is already an absolute url with an authority (host).
28
- #
29
- # input - the URL to make relative to the domain root
30
- #
31
- # Returns a URL relative to the domain root as a String.
32
- def relative_url(input)
33
- return if input.nil?
34
-
35
- cache = if input.is_a?(String)
36
- (@context.registers[:site].filter_cache[:relative_url] ||= {})
37
- else
38
- (@context.registers[:cached_relative_url] ||= {})
39
- end
40
- cache[input] ||= compute_relative_url(input)
41
-
42
- # Duplicate cached string so that the cached value is never mutated by
43
- # a subsequent filter.
44
- cache[input].dup
45
- end
46
-
47
- # Strips trailing `/index.html` from URLs to create pretty permalinks
48
- #
49
- # input - the URL with a possible `/index.html`
50
- #
51
- # Returns a URL with the trailing `/index.html` removed
52
- def strip_index(input)
53
- return if input.nil? || input.to_s.empty?
54
-
55
- input.sub(%r!/index\.html?$!, "/")
56
- end
57
-
58
- private
59
-
60
- def compute_absolute_url(input)
61
- input = input.url if input.respond_to?(:url)
62
- return input if Addressable::URI.parse(input.to_s).absolute?
63
-
64
- site = @context.registers[:site]
65
- site_url = site.config["url"]
66
- return relative_url(input) if site_url.nil? || site_url == ""
67
-
68
- Addressable::URI.parse(
69
- site_url.to_s + relative_url(input)
70
- ).normalize.to_s
71
- end
72
-
73
- def compute_relative_url(input)
74
- input = input.url if input.respond_to?(:url)
75
- return input if Addressable::URI.parse(input.to_s).absolute?
76
-
77
- parts = [sanitized_baseurl, input]
78
- Addressable::URI.parse(
79
- parts.map! { |part| ensure_leading_slash(part.to_s) }.join
80
- ).normalize.to_s
81
- end
82
-
83
- def sanitized_baseurl
84
- site = @context.registers[:site]
85
- baseurl = site.config["baseurl"]
86
- return "" if baseurl.nil?
87
-
88
- baseurl.to_s.chomp("/")
89
- end
90
-
91
- def ensure_leading_slash(input)
92
- return input if input.nil? || input.empty? || input.start_with?("/")
93
-
94
- "/#{input}"
95
- end
96
- end
97
- end
98
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Filters
5
+ module URLFilters
6
+ # Produces an absolute URL based on site.url and site.baseurl.
7
+ #
8
+ # input - the URL to make absolute.
9
+ #
10
+ # Returns the absolute URL as a String.
11
+ def absolute_url(input)
12
+ return if input.nil?
13
+
14
+ cache = if input.is_a?(String)
15
+ (@context.registers[:site].filter_cache[:absolute_url] ||= {})
16
+ else
17
+ (@context.registers[:cached_absolute_url] ||= {})
18
+ end
19
+ cache[input] ||= compute_absolute_url(input)
20
+
21
+ # Duplicate cached string so that the cached value is never mutated by
22
+ # a subsequent filter.
23
+ cache[input].dup
24
+ end
25
+
26
+ # Produces a URL relative to the domain root based on site.baseurl
27
+ # unless it is already an absolute url with an authority (host).
28
+ #
29
+ # input - the URL to make relative to the domain root
30
+ #
31
+ # Returns a URL relative to the domain root as a String.
32
+ def relative_url(input)
33
+ return if input.nil?
34
+
35
+ cache = if input.is_a?(String)
36
+ (@context.registers[:site].filter_cache[:relative_url] ||= {})
37
+ else
38
+ (@context.registers[:cached_relative_url] ||= {})
39
+ end
40
+ cache[input] ||= compute_relative_url(input)
41
+
42
+ # Duplicate cached string so that the cached value is never mutated by
43
+ # a subsequent filter.
44
+ cache[input].dup
45
+ end
46
+
47
+ # Strips trailing `/index.html` from URLs to create pretty permalinks
48
+ #
49
+ # input - the URL with a possible `/index.html`
50
+ #
51
+ # Returns a URL with the trailing `/index.html` removed
52
+ def strip_index(input)
53
+ return if input.nil? || input.to_s.empty?
54
+
55
+ input.sub(%r!/index\.html?$!, "/")
56
+ end
57
+
58
+ private
59
+
60
+ def compute_absolute_url(input)
61
+ input = input.url if input.respond_to?(:url)
62
+ return input if Addressable::URI.parse(input.to_s).absolute?
63
+
64
+ site = @context.registers[:site]
65
+ site_url = site.config["url"]
66
+ return relative_url(input) if site_url.nil? || site_url == ""
67
+
68
+ Addressable::URI.parse(
69
+ site_url.to_s + relative_url(input)
70
+ ).normalize.to_s
71
+ end
72
+
73
+ def compute_relative_url(input)
74
+ input = input.url if input.respond_to?(:url)
75
+ return input if Addressable::URI.parse(input.to_s).absolute?
76
+
77
+ parts = [sanitized_baseurl, input]
78
+ Addressable::URI.parse(
79
+ parts.map! { |part| ensure_leading_slash(part.to_s) }.join
80
+ ).normalize.to_s
81
+ end
82
+
83
+ def sanitized_baseurl
84
+ site = @context.registers[:site]
85
+ baseurl = site.config["baseurl"]
86
+ return "" if baseurl.nil?
87
+
88
+ baseurl.to_s.chomp("/")
89
+ end
90
+
91
+ def ensure_leading_slash(input)
92
+ return input if input.nil? || input.empty? || input.start_with?("/")
93
+
94
+ "/#{input}"
95
+ end
96
+ end
97
+ end
98
+ end