Module: Jekyll::Plugins::PaginateV3::Utils
- Defined in:
- lib/jekyll-paginate-v3/utils/core.rb,
lib/jekyll-paginate-v3/utils/items.rb,
lib/jekyll-paginate-v3/utils/paths.rb,
lib/jekyll-paginate-v3/utils/logger.rb,
lib/jekyll-paginate-v3/utils/formatting.rb,
lib/jekyll-paginate-v3/utils/nested_data.rb
Overview
Nested frontmatter lookup helpers with equivalent-key support.
Used by filtering, sorting, and index grouping for nested key reads.
Defined Under Namespace
Classes: Logger
Class Method Summary collapse
-
.arrayify(value, split_commas: false, split_delimiter: nil) ⇒ Object
Converts a value into an array.
-
.build_equivalent_lookup(raw_equivalents, split_delimiter: ',') ⇒ Object
Builds lookup table used for equivalent key resolution.
-
.build_pagination_windows(total_items, per_page) ⇒ Object
Builds page windows for a total item count and per-page definition.
-
.build_synthetic_filename(extension:, signature:, source_path: nil, source_stem: nil, role:, page_number: nil) ⇒ Object
Builds one readable synthetic filename from source identity plus a deterministic safety suffix.
-
.build_synthetic_source_path(site:, extension:, signature:, collection: nil, source_path: nil, source_stem: nil, role:, page_number: nil) ⇒ Object
Builds one deterministic synthetic source path for in-memory pages and documents.
-
.calculate_number_of_pages(items, per_page) ⇒ Object
Calculates page count for a list and one per-page definition.
-
.canonical_signature(value) ⇒ Object
Canonicalises nested signature data so hashes with identical meaning yield the same suffix regardless of insertion order.
-
.comma_delimited_array(value) ⇒ Object
Backwards-compatible alias for comma-delimited list parsing.
-
.deep_copy(value) ⇒ Object
Deep copy helper for plain Ruby hashes/arrays used in config merging.
-
.delimited_array(value, delimiter: ',') ⇒ Object
Converts scalars/arrays into a flat array and applies delimited-string expansion for all string entries.
-
.derive_synthetic_source_stem(source_path: nil, source_stem: nil, fallback: 'generated') ⇒ Object
Derives one human-readable synthetic stem from an original source path or fallback label.
-
.derive_synthetic_source_stem_from_frontmatter(frontmatter, fallback: 'generated') ⇒ Object
Derives one readable stem from frontmatter when no real source path exists, preferring permalink and then title.
-
.ensure_full_path(path, default_index_name, default_extension) ⇒ Object
Normalises a full path by appending a default filename and extension when needed.
-
.ensure_leading_dot(extension) ⇒ Object
Ensures a filename extension has a leading dot.
-
.ensure_leading_slash(path) ⇒ Object
Ensures a path-like string has a leading slash.
-
.ensure_trailing_slash(path) ⇒ Object
Ensures a path-like string has a trailing slash.
-
.extract_permalink_stem(permalink) ⇒ Object
Extracts one final path segment from a permalink-like value.
-
.extract_source_filename_stem(source_path) ⇒ Object
Extracts one source-style stem from a real path-like value.
-
.fetch_nested_values(data, key_path, separator, equivalent_lookup) ⇒ Object
Retrieves all possible values from a nested key path.
-
.format_page_number(pattern, current_page, max_pages = nil) ⇒ Object
Replaces
:numand optionally:maxplaceholders. -
.format_page_title(pattern, title, current_page = nil, max_pages = nil) ⇒ Object
Replaces
:titleand numeric placeholders in title patterns. -
.generated_index?(item) ⇒ Boolean
Returns true when the object appears to be a generated index page.
-
.item_collection_label(item) ⇒ Object
Collection label helper that treats pages as nil collection.
-
.merge_generated_template_pagination(generated_pagination, layout_pagination, compatibility_mode) ⇒ Object
Merges generated-template pagination config with layout pagination.
-
.normalise_layouts(config, split_delimiter: ',') ⇒ Object
Expands
layout+layoutsconfig into a unique array of layout names. -
.normalise_per_page_pattern(per_page) ⇒ Object
Normalises a per-page definition into an integer array.
-
.normalise_split_delimiter(raw_delimiter, default_delimiter = ',') ⇒ Object
Normalises a configurable delimiter.
-
.page_size_for_number(per_page, page_number) ⇒ Object
Resolves configured page size for one 1-based page number.
-
.pagination_template?(item) ⇒ Boolean
Returns true when the object looks like a pagination template.
-
.read_hash(hash, key) ⇒ Object
Reads a value from hash by either string or symbol key.
-
.relative_item_path(item) ⇒ Object
Safe relative path for pages and documents.
-
.remove_leading_slash(path) ⇒ Object
Removes one leading slash from a path-like string.
-
.replace_tokens(template, token_map) ⇒ Object
Replaces placeholders in a string where keys are in
token_map. -
.resolve_hash_key(hash, requested_key_path, equivalent_lookup, separator: '.') ⇒ Object
Resolves the effective hash key for one requested nested key path.
-
.safe_hash(value) ⇒ Object
Returns a hash from any input object, or an empty hash for unsupported values.
-
.sanitise_filename_component(value, fallback: 'generated') ⇒ Object
Sanitises one filename component while preserving source readability where the original stem is already filesystem-safe.
-
.scalar_values(value) ⇒ Object
Converts a mixed scalar/array value into a flat array of scalar values.
-
.split_delimited_string(value, delimiter) ⇒ Object
Splits one string using the configured delimiter, trims entries, and rejects blank strings.
-
.split_nested_key(key, separator) ⇒ Object
Splits a nested key according to configured separator.
-
.stringify_keys(value) ⇒ Object
Normalises hash keys recursively to strings.
Class Method Details
.arrayify(value, split_commas: false, split_delimiter: nil) ⇒ Object
Converts a value into an array. Strings can be treated as delimiter-defined lists.
42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/jekyll-paginate-v3/utils/core.rb', line 42 def self.arrayify(value, split_commas: false, split_delimiter: nil) delimiter = split_delimiter delimiter = ',' if delimiter.nil? && split_commas Jekyll::Plugins::PaginateV3::Support::StringArray.new(delimiter: delimiter || ',').interpret( value, split: delimiter.nil? ? false : 0, flatten: true, delimiter: delimiter.nil? ? Jekyll::Plugins::PaginateV3::Support::StringArray::UNSET : delimiter ) end |
.build_equivalent_lookup(raw_equivalents, split_delimiter: ',') ⇒ Object
Builds lookup table used for equivalent key resolution.
Each entry is keyed by full key-path string (for example
product.tag), which allows equivalent mappings to be scoped to one
nested level only.
21 22 23 |
# File 'lib/jekyll-paginate-v3/utils/nested_data.rb', line 21 def self.build_equivalent_lookup(raw_equivalents, split_delimiter: ',') Jekyll::Plugins::PaginateV3::Support::FrontmatterPath.build_equivalent_lookup(raw_equivalents, split_delimiter: split_delimiter) end |
.build_pagination_windows(total_items, per_page) ⇒ Object
Builds page windows for a total item count and per-page definition.
Each returned window has:
num: page numberpage_size: configured capacity for this pagecount: actual number of items on this pageoffset_start/offset_end: zero-based slice boundsstart/end: 1-based item positions (or nil when empty)
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 |
# File 'lib/jekyll-paginate-v3/utils/items.rb', line 52 def self.build_pagination_windows(total_items, per_page) safe_total_items = [total_items.to_i, 0].max if safe_total_items.zero? first_page_size = page_size_for_number(per_page, 1) return [ { 'num' => 1, 'page_size' => first_page_size, 'count' => 0, 'offset_start' => 0, 'offset_end' => 0, 'start' => nil, 'end' => nil } ] end windows = [] page_number = 1 offset = 0 while offset < safe_total_items page_size = page_size_for_number(per_page, page_number) count = [page_size, safe_total_items - offset].min start_item_index = offset + 1 end_item_index = offset + count windows << { 'num' => page_number, 'page_size' => page_size, 'count' => count, 'offset_start' => offset, 'offset_end' => offset + count, 'start' => start_item_index, 'end' => end_item_index } offset += count page_number += 1 end windows end |
.build_synthetic_filename(extension:, signature:, source_path: nil, source_stem: nil, role:, page_number: nil) ⇒ Object
Builds one readable synthetic filename from source identity plus a deterministic safety suffix.
75 76 77 78 79 80 81 |
# File 'lib/jekyll-paginate-v3/utils/paths.rb', line 75 def self.build_synthetic_filename(extension:, signature:, source_path: nil, source_stem: nil, role:, page_number: nil) stem = derive_synthetic_source_stem(source_path: source_path, source_stem: source_stem, fallback: role) filename_segments = [stem, role.to_s.strip] filename_segments << page_number.to_i.to_s unless page_number.nil? filename_segments << Digest::MD5.hexdigest(canonical_signature(signature).inspect) "#{filename_segments.reject(&:empty?).join('-')}#{ensure_leading_dot(extension)}" end |
.build_synthetic_source_path(site:, extension:, signature:, collection: nil, source_path: nil, source_stem: nil, role:, page_number: nil) ⇒ Object
Builds one deterministic synthetic source path for in-memory pages and documents. Filenames remain readable for debugging while a hash suffix preserves practical uniqueness across templates and variants.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/jekyll-paginate-v3/utils/paths.rb', line 58 def self.build_synthetic_source_path(site:, extension:, signature:, collection: nil, source_path: nil, source_stem: nil, role:, page_number: nil) directory = collection.nil? ? site.source : File.join(site.source, collection.relative_directory) File.join( directory, build_synthetic_filename( extension: extension, signature: signature, source_path: source_path, source_stem: source_stem, role: role, page_number: page_number ) ) end |
.calculate_number_of_pages(items, per_page) ⇒ Object
Calculates page count for a list and one per-page definition.
per_page can be either:
- Integer: fixed page size.
- Array: nth entry is used for page n, with the final entry reused.
17 18 19 |
# File 'lib/jekyll-paginate-v3/utils/items.rb', line 17 def self.calculate_number_of_pages(items, per_page) build_pagination_windows(items.size, per_page).length end |
.canonical_signature(value) ⇒ Object
Canonicalises nested signature data so hashes with identical meaning yield the same suffix regardless of insertion order.
135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/jekyll-paginate-v3/utils/paths.rb', line 135 def self.canonical_signature(value) case value when Hash value.each_with_object({}) do |(key, nested_value), canonical| canonical[key.to_s] = canonical_signature(nested_value) end.sort_by { |key, _| key }.to_h when Array value.map { |entry| canonical_signature(entry) } else value end end |
.comma_delimited_array(value) ⇒ Object
Backwards-compatible alias for comma-delimited list parsing.
69 70 71 |
# File 'lib/jekyll-paginate-v3/utils/core.rb', line 69 def self.comma_delimited_array(value) delimited_array(value, delimiter: ',').map { |entry| entry.to_s.strip }.reject(&:empty?) end |
.deep_copy(value) ⇒ Object
Deep copy helper for plain Ruby hashes/arrays used in config merging.
13 14 15 16 17 18 19 20 21 |
# File 'lib/jekyll-paginate-v3/utils/core.rb', line 13 def self.deep_copy(value) if value.is_a?(Hash) value.each_with_object({}) { |(key, child), copy| copy[key] = deep_copy(child) } elsif value.is_a?(Array) value.map { |child| deep_copy(child) } else value end end |
.delimited_array(value, delimiter: ',') ⇒ Object
Converts scalars/arrays into a flat array and applies delimited-string expansion for all string entries.
37 38 39 |
# File 'lib/jekyll-paginate-v3/utils/core.rb', line 37 def self.delimited_array(value, delimiter: ',') Jekyll::Plugins::PaginateV3::Support::StringArray.new(delimiter: delimiter).interpret(value, split: -1, flatten: true) end |
.derive_synthetic_source_stem(source_path: nil, source_stem: nil, fallback: 'generated') ⇒ Object
Derives one human-readable synthetic stem from an original source path or fallback label.
85 86 87 88 89 90 |
# File 'lib/jekyll-paginate-v3/utils/paths.rb', line 85 def self.derive_synthetic_source_stem(source_path: nil, source_stem: nil, fallback: 'generated') candidate = extract_source_filename_stem(source_path) candidate = source_stem.to_s if candidate.empty? candidate = fallback.to_s if candidate.to_s.strip.empty? sanitise_filename_component(candidate, fallback: fallback) end |
.derive_synthetic_source_stem_from_frontmatter(frontmatter, fallback: 'generated') ⇒ Object
Derives one readable stem from frontmatter when no real source path exists, preferring permalink and then title.
94 95 96 97 98 99 100 |
# File 'lib/jekyll-paginate-v3/utils/paths.rb', line 94 def self.derive_synthetic_source_stem_from_frontmatter(frontmatter, fallback: 'generated') frontmatter_hash = safe_hash(frontmatter) permalink_stem = extract_permalink_stem(frontmatter_hash['permalink']) return derive_synthetic_source_stem(source_stem: permalink_stem, fallback: fallback) unless permalink_stem.empty? derive_synthetic_source_stem(source_stem: frontmatter_hash['title'], fallback: fallback) end |
.ensure_full_path(path, default_index_name, default_extension) ⇒ Object
Normalises a full path by appending a default filename and extension when needed.
41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/jekyll-paginate-v3/utils/paths.rb', line 41 def self.ensure_full_path(path, default_index_name, default_extension) url = path.to_s extension = ensure_leading_dot(default_extension) index_name = default_index_name.to_s if url.end_with?('/') return "#{url}#{index_name}#{extension}" end return "#{url}#{extension}" if File.extname(url).empty? url end |
.ensure_leading_dot(extension) ⇒ Object
Ensures a filename extension has a leading dot.
33 34 35 36 37 38 |
# File 'lib/jekyll-paginate-v3/utils/paths.rb', line 33 def self.ensure_leading_dot(extension) string_extension = extension.to_s return '' if string_extension.empty? string_extension.start_with?('.') ? string_extension : ".#{string_extension}" end |
.ensure_leading_slash(path) ⇒ Object
Ensures a path-like string has a leading slash.
21 22 23 24 |
# File 'lib/jekyll-paginate-v3/utils/paths.rb', line 21 def self.ensure_leading_slash(path) string_path = path.to_s string_path.start_with?('/') ? string_path : "/#{string_path}" end |
.ensure_trailing_slash(path) ⇒ Object
Ensures a path-like string has a trailing slash.
27 28 29 30 |
# File 'lib/jekyll-paginate-v3/utils/paths.rb', line 27 def self.ensure_trailing_slash(path) string_path = path.to_s string_path.end_with?('/') ? string_path : "#{string_path}/" end |
.extract_permalink_stem(permalink) ⇒ Object
Extracts one final path segment from a permalink-like value.
111 112 113 114 115 116 117 118 119 |
# File 'lib/jekyll-paginate-v3/utils/paths.rb', line 111 def self.extract_permalink_stem(permalink) path = permalink.to_s.strip return '' if path.empty? segments = path.split('/').reject(&:empty?) return '' if segments.empty? File.basename(segments.last, File.extname(segments.last)) end |
.extract_source_filename_stem(source_path) ⇒ Object
Extracts one source-style stem from a real path-like value.
103 104 105 106 107 108 |
# File 'lib/jekyll-paginate-v3/utils/paths.rb', line 103 def self.extract_source_filename_stem(source_path) path = source_path.to_s return '' if path.strip.empty? File.basename(path, File.extname(path)) end |
.fetch_nested_values(data, key_path, separator, equivalent_lookup) ⇒ Object
Retrieves all possible values from a nested key path.
39 40 41 42 43 44 45 |
# File 'lib/jekyll-paginate-v3/utils/nested_data.rb', line 39 def self.fetch_nested_values(data, key_path, separator, equivalent_lookup) path_reader = Jekyll::Plugins::PaginateV3::Support::FrontmatterPath.new( separator: separator, equivalent_lookup: equivalent_lookup ) scalar_values(path_reader.traverse(data, key_path)) end |
.format_page_number(pattern, current_page, max_pages = nil) ⇒ Object
Replaces :num and optionally :max placeholders.
14 15 16 17 18 |
# File 'lib/jekyll-paginate-v3/utils/formatting.rb', line 14 def self.format_page_number(pattern, current_page, max_pages = nil) output = pattern.to_s.sub(':num', current_page.to_i.to_s) output = output.sub(':max', max_pages.to_i.to_s) unless max_pages.nil? output end |
.format_page_title(pattern, title, current_page = nil, max_pages = nil) ⇒ Object
Replaces :title and numeric placeholders in title patterns.
21 22 23 |
# File 'lib/jekyll-paginate-v3/utils/formatting.rb', line 21 def self.format_page_title(pattern, title, current_page = nil, max_pages = nil) format_page_number(pattern.to_s.sub(':title', title.to_s), current_page, max_pages) end |
.generated_index?(item) ⇒ Boolean
Returns true when the object appears to be a generated index page.
98 99 100 101 102 103 104 105 |
# File 'lib/jekyll-paginate-v3/utils/items.rb', line 98 def self.generated_index?(item) return false unless item.respond_to?(:data) return false unless item.data.is_a?(Hash) return true if item.data.dig('pagination', 'generated') && item.data.dig('pagination', 'index') %w[jekyll-paginate-v2 jekyll-paginate-v3].include?(item.data['autogen']) end |
.item_collection_label(item) ⇒ Object
Collection label helper that treats pages as nil collection.
133 134 135 136 137 138 |
# File 'lib/jekyll-paginate-v3/utils/items.rb', line 133 def self.item_collection_label(item) return nil unless item.respond_to?(:collection) return nil if item.collection.nil? item.collection.respond_to?(:label) ? item.collection.label.to_s : nil end |
.merge_generated_template_pagination(generated_pagination, layout_pagination, compatibility_mode) ⇒ Object
Merges generated-template pagination config with layout pagination.
Default behaviour matches normal Jekyll precedence semantics: generated template config overrides layout defaults.
In v2 compatibility mode we retain legacy override order, but strip layout enabled so generated templates cannot be disabled by layout frontmatter.
87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/jekyll-paginate-v3/utils/core.rb', line 87 def self.merge_generated_template_pagination(generated_pagination, layout_pagination, compatibility_mode) generated_hash = safe_hash(generated_pagination) layout_hash = safe_hash(layout_pagination) if compatibility_mode == 'v2' layout_hash.delete('enabled') return Jekyll::Utils.deep_merge_hashes(generated_hash, layout_hash) end Jekyll::Utils.deep_merge_hashes(layout_hash, generated_hash) end |
.normalise_layouts(config, split_delimiter: ',') ⇒ Object
Expands layout + layouts config into a unique array of layout names.
74 75 76 77 78 79 80 |
# File 'lib/jekyll-paginate-v3/utils/core.rb', line 74 def self.normalise_layouts(config, split_delimiter: ',') source = safe_hash(config) layouts = [] layouts.concat(arrayify(source['layouts'], split_delimiter: split_delimiter)) if source.key?('layouts') layouts.concat(arrayify(source['layout'], split_delimiter: split_delimiter)) if source.key?('layout') layouts.map { |entry| entry.to_s.strip }.reject(&:empty?).uniq end |
.normalise_per_page_pattern(per_page) ⇒ Object
Normalises a per-page definition into an integer array.
Invalid or non-positive entries are coerced to 1 so pagination
remains valid and cannot produce zero-sized pages.
25 26 27 28 29 30 |
# File 'lib/jekyll-paginate-v3/utils/items.rb', line 25 def self.normalise_per_page_pattern(per_page) raw_entries = per_page.is_a?(Array) ? per_page.flatten.compact : [per_page] pattern = raw_entries.map { |entry| [entry.to_i, 1].max } pattern.empty? ? [1] : pattern end |
.normalise_split_delimiter(raw_delimiter, default_delimiter = ',') ⇒ Object
Normalises a configurable delimiter.
Returns default_delimiter when the input is blank or unsupported.
false disables delimited splitting globally.
27 28 29 |
# File 'lib/jekyll-paginate-v3/utils/core.rb', line 27 def self.normalise_split_delimiter(raw_delimiter, default_delimiter = ',') Jekyll::Plugins::PaginateV3::Support::StringArray.normalise_delimiter(raw_delimiter, default_delimiter) end |
.page_size_for_number(per_page, page_number) ⇒ Object
Resolves configured page size for one 1-based page number.
When the page number exceeds the per-page pattern length, the final pattern entry is reused indefinitely.
36 37 38 39 40 41 42 |
# File 'lib/jekyll-paginate-v3/utils/items.rb', line 36 def self.page_size_for_number(per_page, page_number) pattern = normalise_per_page_pattern(per_page) index = [page_number.to_i - 1, pattern.length - 1].min index = 0 if index.negative? pattern[index] end |
.pagination_template?(item) ⇒ Boolean
Returns true when the object looks like a pagination template.
108 109 110 111 112 113 114 115 116 |
# File 'lib/jekyll-paginate-v3/utils/items.rb', line 108 def self.pagination_template?(item) return false unless item.respond_to?(:data) return false unless item.data.is_a?(Hash) pagination = safe_hash(item.data['pagination']) return false if pagination.empty? pagination['template'] || pagination['enabled'] end |
.read_hash(hash, key) ⇒ Object
Reads a value from hash by either string or symbol key.
34 35 36 |
# File 'lib/jekyll-paginate-v3/utils/nested_data.rb', line 34 def self.read_hash(hash, key) Jekyll::Plugins::PaginateV3::Support::FrontmatterPath.read_hash(hash, key) end |
.relative_item_path(item) ⇒ Object
Safe relative path for pages and documents.
119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/jekyll-paginate-v3/utils/items.rb', line 119 def self.relative_item_path(item) if item.respond_to?(:cleaned_relative_path) ext = item.respond_to?(:extname) ? item.extname.to_s : '' remove_leading_slash("#{item.cleaned_relative_path}#{ext}") elsif item.respond_to?(:relative_path) remove_leading_slash(item.relative_path.to_s) elsif item.respond_to?(:path) remove_leading_slash(item.path.to_s) else '' end end |
.remove_leading_slash(path) ⇒ Object
Removes one leading slash from a path-like string.
15 16 17 18 |
# File 'lib/jekyll-paginate-v3/utils/paths.rb', line 15 def self.remove_leading_slash(path) string_path = path.to_s string_path.start_with?('/') ? string_path[1..-1] : string_path end |
.replace_tokens(template, token_map) ⇒ Object
Replaces placeholders in a string where keys are in token_map.
Replacement is done in one pass using a longest-key-first matcher so
overlapping placeholders stay deterministic, for example :foob
always wins over :foo in :foobar.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/jekyll-paginate-v3/utils/formatting.rb', line 30 def self.replace_tokens(template, token_map) output = template.to_s token_source = token_map.is_a?(Hash) ? token_map : {} normalised_token_map = token_source.each_with_object({}) do |(raw_key, value), memo| key = raw_key.to_s next if key.empty? memo[key] = value.to_s end return output if normalised_token_map.empty? sorted_keys = normalised_token_map.keys.sort_by { |key| [-key.length, key] } token_pattern = /:(#{sorted_keys.map { |key| Regexp.escape(key) }.join('|')})/ output.gsub(token_pattern) do normalised_token_map[Regexp.last_match(1)] end end |
.resolve_hash_key(hash, requested_key_path, equivalent_lookup, separator: '.') ⇒ Object
Resolves the effective hash key for one requested nested key path. Equivalent lookups are performed using the full requested path; only terminal segments from that matched group are candidates for hash access at this level.
29 30 31 |
# File 'lib/jekyll-paginate-v3/utils/nested_data.rb', line 29 def self.resolve_hash_key(hash, requested_key_path, equivalent_lookup, separator: '.') Jekyll::Plugins::PaginateV3::Support::FrontmatterPath.resolve_hash_key(hash, requested_key_path, equivalent_lookup, separator: separator) end |
.safe_hash(value) ⇒ Object
Returns a hash from any input object, or an empty hash for unsupported values.
64 65 66 |
# File 'lib/jekyll-paginate-v3/utils/core.rb', line 64 def self.safe_hash(value) value.is_a?(Hash) ? stringify_keys(value) : {} end |
.sanitise_filename_component(value, fallback: 'generated') ⇒ Object
Sanitises one filename component while preserving source readability where the original stem is already filesystem-safe.
123 124 125 126 127 128 129 130 131 |
# File 'lib/jekyll-paginate-v3/utils/paths.rb', line 123 def self.sanitise_filename_component(value, fallback: 'generated') component = value.to_s.strip component = component.gsub(%r{[\\/]}, '-') component = component.gsub(/[<>:"|?*\x00-\x1f]/, '-') component = component.gsub(/^-+/, '') component = component.gsub(/[. ]+$/, '') component = fallback.to_s if component.empty? component end |
.scalar_values(value) ⇒ Object
Converts a mixed scalar/array value into a flat array of scalar values.
48 49 50 51 52 53 54 55 56 |
# File 'lib/jekyll-paginate-v3/utils/nested_data.rb', line 48 def self.scalar_values(value) if value.is_a?(Array) value.flatten.compact elsif value.nil? [] else [value] end end |
.split_delimited_string(value, delimiter) ⇒ Object
Splits one string using the configured delimiter, trims entries, and rejects blank strings.
32 33 34 |
# File 'lib/jekyll-paginate-v3/utils/core.rb', line 32 def self.split_delimited_string(value, delimiter) Jekyll::Plugins::PaginateV3::Support::StringArray.new(delimiter: delimiter).interpret(value, split: 0, flatten: true) end |
.split_nested_key(key, separator) ⇒ Object
Splits a nested key according to configured separator.
13 14 15 |
# File 'lib/jekyll-paginate-v3/utils/nested_data.rb', line 13 def self.split_nested_key(key, separator) Jekyll::Plugins::PaginateV3::Support::FrontmatterPath.split_path(key, separator) end |
.stringify_keys(value) ⇒ Object
Normalises hash keys recursively to strings.
55 56 57 58 59 60 61 |
# File 'lib/jekyll-paginate-v3/utils/core.rb', line 55 def self.stringify_keys(value) return value unless value.is_a?(Hash) value.each_with_object({}) do |(key, child), copy| copy[key.to_s] = child.is_a?(Hash) ? stringify_keys(child) : child end end |