Class: Bridgetown::Collection

Inherits:
Object
  • Object
show all
Defined in:
lib/bridgetown-core/collection.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(site, label) ⇒ Collection

Create a new Collection.

Parameters:

  • site (Bridgetown::Site)

    the site to which this collection belongs

  • label (String)

    the name of the collection



16
17
18
19
20
# File 'lib/bridgetown-core/collection.rb', line 16

def initialize(site, label)
  @site     = site
  @label    = sanitize_label(label)
  @metadata = 
end

Instance Attribute Details

#labelObject (readonly)

Returns the value of attribute label.



8
9
10
# File 'lib/bridgetown-core/collection.rb', line 8

def label
  @label
end

#metadataObject (readonly)

Returns the value of attribute metadata.



8
9
10
# File 'lib/bridgetown-core/collection.rb', line 8

def 
  @metadata
end

#resourcesArray<Bridgetown::Resource::Base>

Fetch the Resources in this collection. Defaults to an empty array if no resources have been read in.

Returns:



34
35
36
# File 'lib/bridgetown-core/collection.rb', line 34

def resources
  @resources ||= []
end

#siteBridgetown::Site (readonly)

Returns:



6
7
8
# File 'lib/bridgetown-core/collection.rb', line 6

def site
  @site
end

Instance Method Details

#absolute_pathString Also known as: directory

The full path to the folder containing the collection.

Returns:

  • (String)

    full path where the collection is stored on the filesystem



143
144
145
# File 'lib/bridgetown-core/collection.rb', line 143

def absolute_path
  @absolute_path ||= site.in_source_dir(relative_path)
end

#add_resource_from_model(model) ⇒ Object Also known as: add_model_resource

Parameters:



300
301
302
303
304
# File 'lib/bridgetown-core/collection.rb', line 300

def add_resource_from_model(model)
  model.to_resource.read!.tap do |resource|
    resources << resource if resource.publishable?
  end
end

#builtin?Boolean

Returns:

  • (Boolean)


22
23
24
# File 'lib/bridgetown-core/collection.rb', line 22

def builtin?
  @is_builtin ||= label.in?(%w(posts pages data).freeze)
end

#collection_dir(*files) ⇒ String

The full path to the folder containing the collection, with optional subpaths.

Parameters:

  • *files (Array<String>)

    any other path pieces relative to the folder to append to the path

Returns:

  • (String)


154
155
156
157
158
# File 'lib/bridgetown-core/collection.rb', line 154

def collection_dir(*files)
  return absolute_path if files.empty?

  site.in_source_dir(relative_path, *files)
end

#data?Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/bridgetown-core/collection.rb', line 26

def data?
  @is_data ||= label == "data"
end

Used by Resource's permalink processor

Returns:

  • (String)


217
218
219
# File 'lib/bridgetown-core/collection.rb', line 217

def default_permalink
  .fetch("permalink", "/:locale/:collection/:path/")
end

#each(&block) ⇒ Object

Iterate over Resources



53
54
55
# File 'lib/bridgetown-core/collection.rb', line 53

def each(&block)
  resources.each(&block)
end

#entriesArray<String>

All the entries in this collection.

Returns:

  • (Array<String>)

    file paths to the resources in this collection relative to the collection's folder



97
98
99
100
101
102
103
104
105
106
# File 'lib/bridgetown-core/collection.rb', line 97

def entries
  return [] unless exists?

  @entries ||= begin
    collection_dir_slash = "#{collection_dir}/"
    Utils.safe_glob(collection_dir, ["**", "*"], File::FNM_DOTMATCH).map do |entry|
      entry.sub(collection_dir_slash, "")
    end
  end
end

#entry_filterBridgetown::EntryFilter

The entry filter for this collection. Creates an instance of Bridgetown::EntryFilter if needed.



171
172
173
174
175
176
177
# File 'lib/bridgetown-core/collection.rb', line 171

def entry_filter
  @entry_filter ||= Bridgetown::EntryFilter.new(
    site,
    base_directory: folder_name,
    include_underscores: true
  )
end

#exists?Boolean

Checks whether the folder "exists" for this collection.

Returns:

  • (Boolean)


163
164
165
# File 'lib/bridgetown-core/collection.rb', line 163

def exists?
  File.directory?(absolute_path)
end

#extract_metadataHashWithDotAccess::Hash

Extract options for this collection from the site configuration.



224
225
226
# File 'lib/bridgetown-core/collection.rb', line 224

def 
  site.config.collections[label] || HashWithDotAccess::Hash.new
end

#filesObject



65
66
67
68
# File 'lib/bridgetown-core/collection.rb', line 65

def files
  Bridgetown::Deprecator.deprecation_message "Collection#files is now Collection#static_files"
  static_files
end

#filtered_entriesArray<String>

Filtered version of the entries in this collection. See Bridgetown::EntryFilter#filter for more information.

Returns:

  • (Array<String>)

    list of filtered entry paths



112
113
114
115
116
117
118
119
120
121
122
# File 'lib/bridgetown-core/collection.rb', line 112

def filtered_entries
  return [] unless exists?

  @filtered_entries ||=
    Dir.chdir(absolute_path) do
      entry_filter.filter(entries).reject do |f|
        path = collection_dir(f)
        File.directory?(path)
      end
    end
end

#folder_nameString Also known as: relative_directory

The folder name of this Collection, e.g. _posts or _events

Returns:

  • (String)


127
128
129
# File 'lib/bridgetown-core/collection.rb', line 127

def folder_name
  @folder_name ||= "_#{label}"
end

#inspectString

An inspect string.

Returns:

  • (String)


182
183
184
# File 'lib/bridgetown-core/collection.rb', line 182

def inspect
  "#<#{self.class} @label=#{label} resources=#{resources}>"
end

#merge_data_resourcesObject

rubocop:todo Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/bridgetown-core/collection.rb', line 228

def merge_data_resources # rubocop:todo Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
  data_contents = {}

  sanitize_filename = ->(name) do
    name.gsub(%r![^\w\s-]+|(?<=^|\b\s)\s+(?=$|\s?\b)!, "")
      .gsub(%r!\s+!, "_")
  end

  resources.each do |data_resource|
    segments = data_resource.relative_path.each_filename.to_a[1..]
    nested = []
    segments.each_with_index do |segment, index|
      sanitized_segment = sanitize_filename.(File.basename(segment, ".*"))
      hsh = nested.empty? ? data_contents : data_contents.dig(*nested)
      if !hsh.is_a?(Hash)
        Bridgetown.logger.error(
          "Error:",
          "#{nested.join("/")} is not a Hash structure, #{segment} cannot be read"
        )
      elsif index == segments.length - 1
        hsh[sanitized_segment] = data_resource.data.rows || data_resource.data
      elsif !hsh.key?(sanitized_segment)
        hsh[sanitized_segment] = {}
      end
      nested << sanitized_segment
    end
  end

  (data_contents).with_dot_access
end

#merge_environment_specific_metadata(data_contents) ⇒ Object



259
260
261
262
263
264
265
266
267
268
269
# File 'lib/bridgetown-core/collection.rb', line 259

def (data_contents)
  if data_contents["site_metadata"]
    data_contents["site_metadata"][Bridgetown.environment]&.each_key do |k|
      data_contents["site_metadata"][k] =
        data_contents["site_metadata"][Bridgetown.environment][k]
    end
    data_contents["site_metadata"].delete(Bridgetown.environment)
  end

  data_contents
end

#readBridgetown::Collection

Read the allowed resources into the collection's array of resources.

Returns:



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/bridgetown-core/collection.rb', line 73

def read
  filtered_entries.each do |file_path|
    full_path = collection_dir(file_path)
    next if File.directory?(full_path)

    next if File.basename(file_path).starts_with?("_")

    if label == "data" || Utils.has_yaml_header?(full_path) ||
        Utils.has_rbfm_header?(full_path)
      read_resource(full_path)
    else
      read_static_file(file_path, full_path)
    end
  end
  site.static_files.concat(static_files)
  sort_resources!

  self
end

#read_resource(full_path, manifest: nil) ⇒ void

This method returns an undefined value.

Read in resource from repo path

Parameters:



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# File 'lib/bridgetown-core/collection.rb', line 275

def read_resource(full_path, manifest: nil)
  model_relative_path = relative_model_path_for(full_path, manifest: manifest)
  model = Bridgetown::Model::Base.find(
    model_id_from_relative_path(model_relative_path, manifest: manifest),
    site: site
  )

  if model_is_multi_locale?(model, model_relative_path)
    # If the model specifies a locales key, use that to determine the
    # the locale of each resource, otherwise fall back to `site.config.available_locales`
    locales = model.attributes[:locales] || site.config.available_locales

    locales.each do |locale|
      model.locale = locale.to_sym
      add_resource_from_model model
    end

    return
  end

  add_resource_from_model model
  nil
end

#relative_pathString

The relative path to the folder containing the collection.

Returns:

  • (String)

    folder where the collection is stored relative to the configured collections folder (usually the site source)



136
137
138
# File 'lib/bridgetown-core/collection.rb', line 136

def relative_path
  Pathname.new(container).join(folder_name).to_s
end

#resources_by_relative_urlHash<String, Bridgetown::Resource::Base>

Fetch the collection resources and arrange them by relative URL in a hash.

Returns:



48
49
50
# File 'lib/bridgetown-core/collection.rb', line 48

def resources_by_relative_url
  resources.group_by(&:relative_url).transform_values(&:first)
end

#resources_by_slugHash<String, Bridgetown::Resource::Base>

Fetch the collection resources and arrange them by slug in a hash.

Returns:



41
42
43
# File 'lib/bridgetown-core/collection.rb', line 41

def resources_by_slug
  resources.group_by { |item| item.data.slug }.transform_values(&:first)
end

#sanitize_label(label) ⇒ String

Produce a sanitized label name Label names may not contain anything but alphanumeric characters, underscores, and hyphens.

Parameters:

  • label (String)

    the possibly-unsafe label

Returns:

  • (String)

    sanitized version of the label.



192
193
194
# File 'lib/bridgetown-core/collection.rb', line 192

def sanitize_label(label)
  label.gsub(%r![^a-z0-9_\-.]!i, "")
end

#sort_resources!Object



307
308
309
310
311
312
313
314
# File 'lib/bridgetown-core/collection.rb', line 307

def sort_resources!
  if ["sort_by"].is_a?(String)
    sort_resources_by_key!
  else
    resources.sort!
  end
  resources.reverse! if .sort_direction == "descending"
end

#static_filesArray<Bridgetown::StaticFile>

Fetch the static files in this collection. Defaults to an empty array if no static files have been read in.

Returns:



61
62
63
# File 'lib/bridgetown-core/collection.rb', line 61

def static_files
  @static_files ||= []
end

#to_liquidBridgetown::Drops::CollectionDrop

Produce a representation of this Collection for use in Liquid. Exposes two attributes:

  • label
  • resources

Returns:



203
204
205
# File 'lib/bridgetown-core/collection.rb', line 203

def to_liquid
  Drops::CollectionDrop.new self
end

#write?Boolean

Whether the collection's resources ought to be written as individual files in the output.

Returns:

  • (Boolean)

    true if the 'write' metadata is true, false otherwise.



211
212
213
# File 'lib/bridgetown-core/collection.rb', line 211

def write?
  !!.fetch("output", false)
end