Class: Bridgetown::Collection

Inherits:
Object
  • Object
show all
Includes:
Enumerable
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



19
20
21
22
23
# File 'lib/bridgetown-core/collection.rb', line 19

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

Instance Attribute Details

#labelObject (readonly)

Returns the value of attribute label.



11
12
13
# File 'lib/bridgetown-core/collection.rb', line 11

def label
  @label
end

#metadataObject (readonly)

Returns the value of attribute metadata.



11
12
13
# File 'lib/bridgetown-core/collection.rb', line 11

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:



37
38
39
# File 'lib/bridgetown-core/collection.rb', line 37

def resources
  @resources ||= []
end

#siteBridgetown::Site (readonly)

Returns:



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

def site
  @site
end

Instance Method Details

#[]Object

Delgates to resources[]



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

def [](...) = resources.[](...)

#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



147
148
149
# File 'lib/bridgetown-core/collection.rb', line 147

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:



319
320
321
322
323
# File 'lib/bridgetown-core/collection.rb', line 319

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

#builtin?Boolean

Returns:

  • (Boolean)


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

def builtin?
  @is_builtin ||= label.within?(%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)


158
159
160
161
162
# File 'lib/bridgetown-core/collection.rb', line 158

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

  site.in_source_dir(relative_path, *files)
end

#data?Boolean

Returns:

  • (Boolean)


29
30
31
# File 'lib/bridgetown-core/collection.rb', line 29

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

#deconstructObject

Delgates to resources.deconstruct



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

def deconstruct = resources.deconstruct

What the configured permalink should be absent of user overrides

Returns:

  • (String)


227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/bridgetown-core/collection.rb', line 227

def default_configured_permalink
  @default_configured_permalink ||= case label
                                    when "data"
                                      nil
                                    when "posts"
                                      site.config.permalink
                                    when "pages"
                                      "/:locale/:path/"
                                    else
                                      "/:locale/:collection/:path/"
                                    end
end

Used by Resources permalink processors

Returns:

  • (String)


221
222
223
# File 'lib/bridgetown-core/collection.rb', line 221

def default_permalink
  .fetch("permalink", default_configured_permalink)
end

#eachObject

Iterate over Resources by delegating to resources.each (supports Enumerable)



56
# File 'lib/bridgetown-core/collection.rb', line 56

def each(...) = resources.each(...)

#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



101
102
103
104
105
106
107
108
109
110
# File 'lib/bridgetown-core/collection.rb', line 101

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.



175
176
177
178
179
180
181
# File 'lib/bridgetown-core/collection.rb', line 175

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)


167
168
169
# File 'lib/bridgetown-core/collection.rb', line 167

def exists?
  File.directory?(absolute_path)
end

#extract_metadataHashWithDotAccess::Hash

Extract options for this collection from the site configuration.



243
244
245
# File 'lib/bridgetown-core/collection.rb', line 243

def 
  site.config.collections[label] || HashWithDotAccess::Hash.new
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



116
117
118
119
120
121
122
123
124
125
126
# File 'lib/bridgetown-core/collection.rb', line 116

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)


131
132
133
# File 'lib/bridgetown-core/collection.rb', line 131

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

#inspectString

An inspect string.

Returns:

  • (String)


186
187
188
# File 'lib/bridgetown-core/collection.rb', line 186

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

#lastObject

Delgates to resources.last



59
# File 'lib/bridgetown-core/collection.rb', line 59

def last(...) = resources.last(...)

#merge_data_resourcesObject

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



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/bridgetown-core/collection.rb', line 247

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).as_dots
end

#merge_environment_specific_metadata(data_contents) ⇒ Object



278
279
280
281
282
283
284
285
286
287
288
# File 'lib/bridgetown-core/collection.rb', line 278

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:



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/bridgetown-core/collection.rb', line 78

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" || FrontMatter::Loaders.front_matter?(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:



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/bridgetown-core/collection.rb', line 294

def read_resource(full_path, manifest: nil)
  model_relative_path = relative_model_path_for(full_path, manifest:)
  model = Bridgetown::Model::Base.find(
    model_id_from_relative_path(model_relative_path, manifest:),
    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)



140
141
142
# File 'lib/bridgetown-core/collection.rb', line 140

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:



51
52
53
# File 'lib/bridgetown-core/collection.rb', line 51

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:



44
45
46
# File 'lib/bridgetown-core/collection.rb', line 44

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.



196
197
198
# File 'lib/bridgetown-core/collection.rb', line 196

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

#sort_resources!Object



326
327
328
329
330
331
332
333
# File 'lib/bridgetown-core/collection.rb', line 326

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:



71
72
73
# File 'lib/bridgetown-core/collection.rb', line 71

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:



207
208
209
# File 'lib/bridgetown-core/collection.rb', line 207

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.



215
216
217
# File 'lib/bridgetown-core/collection.rb', line 215

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