Class: Lifer::Entry
- Inherits:
-
Object
- Object
- Lifer::Entry
- Defined in:
- lib/lifer/entry.rb
Overview
An entry is a Lifer file that will be built into the output directory. There are more than one subclass of entry: Markdown entries are the most traditional, but HTML and text files are also very valid entries.
This class provides a baseline of the functionality that all entry subclasses should implement. It also provides the entry generator for all entry subclasses.
Defined Under Namespace
Constant Summary collapse
- ASSET_DELIMITER_REGEX =
If assets are represented in YAML frontmatter as a string, they’re split on commas and/or spaces.
/[,\s]+/- DEFAULT_DATE =
We provide a default date for entries that have no date and entry types that otherwise could not have a date due to no real way of getting that metadata.
Time.new(1900, 01, 01, 0, 0, 0, "+00:00")
- FILENAME_DATE_FORMAT =
If a filename contains a date, we should expect it to be in the following format.
/^(\d{4}-\d{1,2}-\d{1,2})-/- TAG_DELIMITER_REGEX =
If tags are represented in YAML frontmatter as a string, they’re split on commas and/or spaces.
/[,\s]+/- TRUNCATION_THRESHOLD =
We truncate anything that needs to be truncated (summaries, meta descriptions) at the following character count.
120
Class Attribute Summary collapse
-
.include_in_feeds ⇒ Object
Returns the value of attribute include_in_feeds.
-
.input_extensions ⇒ Object
Returns the value of attribute input_extensions.
-
.output_extension ⇒ Object
Returns the value of attribute output_extension.
Instance Attribute Summary collapse
-
#collection ⇒ Object
readonly
Returns the value of attribute collection.
-
#file ⇒ Object
readonly
Returns the value of attribute file.
Class Method Summary collapse
-
.generate(file:, collection:, dependencies: [:assets, :authors, :tags]) ⇒ Lifer::Entry
The entrypoint for generating entry objects.
-
.manifest ⇒ Array<Lifer::Entry>
Whenever an entry is generated it should be added to the entry manifest.
-
.supported?(filename, file_extensions = supported_file_extensions) ⇒ Boolean
Checks whether the given filename is supported entry type (using only its file extension).
Instance Method Summary collapse
-
#assets ⇒ Array<Lifer::Asset>
Locates and returns all assets defined in the entry.
-
#authors ⇒ Array<String>
Given the entry’s frontmatter, we should be able to get a list of authors.
-
#body ⇒ String
This method returns the full text of the entry, only removing the frontmatter.
- #feedable? ⇒ Boolean
-
#frontmatter ⇒ Hash
Frontmatter is a widely supported YAML metadata block found at the top of text–often Markdown–files.
-
#full_text ⇒ String
The full text of the entry.
-
#initialize(file:, collection:) ⇒ Lifer::Entry
constructor
When a new entry is initialized we expect the file to already exist, and we expect to know which ‘Lifer::Collection` it belongs to.
-
#path ⇒ String
The expected, absolute URI path to the entry.
-
#permalink(host: Lifer.setting(:global, :host)) ⇒ String
Using the current Lifer configuration, we can calculate the expected permalink for the entry.
-
#published_at ⇒ Time
The entry’s publication date.
-
#summary ⇒ String
If given a summary in the frontmatter of the entry, we can use this to provide a summary.
-
#tags ⇒ Array<Lifer::Tag>
Locates and returns all tags defined in the entry.
-
#title ⇒ String
Returns the title of the entry.
- #to_html ⇒ Object
-
#updated_at(fallback: nil) ⇒ Time
The entry’s last updated date.
Constructor Details
#initialize(file:, collection:) ⇒ Lifer::Entry
When a new entry is initialized we expect the file to already exist, and we expect to know which ‘Lifer::Collection` it belongs to.
130 131 132 133 |
# File 'lib/lifer/entry.rb', line 130 def initialize(file:, collection:) @file = Pathname file @collection = collection end |
Class Attribute Details
.include_in_feeds ⇒ Object
Returns the value of attribute include_in_feeds.
19 20 21 |
# File 'lib/lifer/entry.rb', line 19 def include_in_feeds @include_in_feeds end |
.input_extensions ⇒ Object
Returns the value of attribute input_extensions.
20 21 22 |
# File 'lib/lifer/entry.rb', line 20 def input_extensions @input_extensions end |
.output_extension ⇒ Object
Returns the value of attribute output_extension.
21 22 23 |
# File 'lib/lifer/entry.rb', line 21 def output_extension @output_extension end |
Instance Attribute Details
#collection ⇒ Object (readonly)
Returns the value of attribute collection.
57 58 59 |
# File 'lib/lifer/entry.rb', line 57 def collection @collection end |
#file ⇒ Object (readonly)
Returns the value of attribute file.
57 58 59 |
# File 'lib/lifer/entry.rb', line 57 def file @file end |
Class Method Details
.generate(file:, collection:, dependencies: [:assets, :authors, :tags]) ⇒ Lifer::Entry
The entrypoint for generating entry objects. We should never end up with ‘Lifer::Entry` records: only subclasses.
66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/lifer/entry.rb', line 66 def generate(file:, collection:, dependencies: [:assets, :authors, :tags]) error!(file) unless File.exist?(file) if (new_entry = subclass_for(file)&.new(file:, collection:)) Lifer.entry_manifest << new_entry dependencies.each do |dependency| new_entry.public_send dependency end end new_entry end |
.manifest ⇒ Array<Lifer::Entry>
Whenever an entry is generated it should be added to the entry manifest. This lets us get a list of all generated entries.
84 85 86 87 88 |
# File 'lib/lifer/entry.rb', line 84 def manifest return Lifer.entry_manifest if self == Lifer::Entry Lifer.entry_manifest.select { |entry| entry.class == self } end |
.supported?(filename, file_extensions = supported_file_extensions) ⇒ Boolean
Checks whether the given filename is supported entry type (using only its file extension).
97 98 99 |
# File 'lib/lifer/entry.rb', line 97 def supported?(filename, file_extensions= supported_file_extensions) file_extensions.any? { |ext| filename.end_with? ext } end |
Instance Method Details
#assets ⇒ Array<Lifer::Asset>
Locates and returns all assets defined in the entry.
138 139 140 141 |
# File 'lib/lifer/entry.rb', line 138 def assets @assets ||= candidate_asset_names .map { Lifer::Asset.build_or_update(url: _1, entries: [self]) } end |
#authors ⇒ Array<String>
Given the entry’s frontmatter, we should be able to get a list of authors. We always prefer authors (as opposed to a singular author) because it makes handling both cases easier in the long run.
The return value here is likely an author’s name. Whether that’s a full name, a first name, or a handle is up to the end user.
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/lifer/entry.rb', line 151 def list = Array(frontmatter[:author] || frontmatter[:authors]).compact if list.any? && list.all? { _1.is_a? Array } list = [list.to_h] end list.map { attributes = Lifer::Utilities.symbolize_keys( case _1 when Hash then _1 when String then {name: _1} end ) Lifer::Author.build_or_update **attributes.merge(entries: [self]) } end |
#body ⇒ String
This method returns the full text of the entry, only removing the frontmatter. It should not parse anything other than frontmatter.
172 173 174 175 176 |
# File 'lib/lifer/entry.rb', line 172 def body return full_text.strip unless frontmatter? full_text.sub(Lifer::FRONTMATTER_REGEX, "").strip end |
#feedable? ⇒ Boolean
178 179 180 181 182 183 184 185 |
# File 'lib/lifer/entry.rb', line 178 def feedable? if (setting = self.class.include_in_feeds).nil? raise NotImplementedError, I18n.t("entry.feedable_error", entry_class: self.class) end setting end |
#frontmatter ⇒ Hash
Frontmatter is a widely supported YAML metadata block found at the top of text–often Markdown–files. We attempt to parse all entries for frontmatter.
192 193 194 195 196 197 198 199 |
# File 'lib/lifer/entry.rb', line 192 def frontmatter return {} unless frontmatter? Lifer::Utilities.symbolize_keys( YAML.load full_text[Lifer::FRONTMATTER_REGEX, 1], permitted_classes: [Time] ) end |
#full_text ⇒ String
The full text of the entry.
204 205 206 |
# File 'lib/lifer/entry.rb', line 204 def full_text @full_text ||= File.readlines(file).join if file end |
#path ⇒ String
The expected, absolute URI path to the entry. For example:
/index.html
/blog/my-trip-to-toronto.html
240 |
# File 'lib/lifer/entry.rb', line 240 def path = permalink(host: "/") |
#permalink(host: Lifer.setting(:global, :host)) ⇒ String
Using the current Lifer configuration, we can calculate the expected permalink for the entry. For example:
https://example.com/index.html
https://example.com/blog/my-trip-to-toronto.html
This would be useful for indexes and feeds and so on.
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/lifer/entry.rb', line 217 def permalink(host: Lifer.setting(:global, :host)) cached_permalink_variable = "@entry_permalink_" + Digest::SHA1.hexdigest(host) instance_variable_get(cached_permalink_variable) || instance_variable_set( cached_permalink_variable, File.join( host, Lifer::URIStrategy .find(collection.setting :uri_strategy) .new(root: Lifer.root) .permalink(self) ) ) end |
#published_at ⇒ Time
The entry’s publication date. The published date can be inferred in a few ways. The priority is:
1. the frontmatter's `published_at` field
2. the frontmatter's `published` field
3. the frontamtter's `date` field
4. The date in the filename.
Since text files would only store dates as simple strings, it’s nice to attempt to convert those into Ruby date or datetime objects.
255 256 257 258 259 260 261 |
# File 'lib/lifer/entry.rb', line 255 def published_at date_for frontmatter[:published_at], frontmatter[:published], frontmatter[:date], filename_date, missing_metadata_translation_key: "entry.no_published_at_metadata" end |
#summary ⇒ String
If given a summary in the frontmatter of the entry, we can use this to provide a summary.
Since subclasses may have more sophisticated access to the document, they may override this method with their own distinct implementations.
270 271 272 |
# File 'lib/lifer/entry.rb', line 270 def summary return frontmatter[:summary] if frontmatter[:summary] end |
#tags ⇒ Array<Lifer::Tag>
Locates and returns all tags defined in the entry.
277 278 279 280 |
# File 'lib/lifer/entry.rb', line 277 def @tags ||= candidate_tag_names .map { Lifer::Tag.build_or_update(name: _1, entries: [self]) } end |
#title ⇒ String
Returns the title of the entry. Every entry subclass must implement this method so that builders have access to some kind of title for each entry.
286 287 288 |
# File 'lib/lifer/entry.rb', line 286 def title raise NotImplementedError, I18n.t("shared.not_implemented_method") end |
#to_html ⇒ Object
290 291 292 |
# File 'lib/lifer/entry.rb', line 290 def to_html raise NotImplementedError, I18n.t("shared.not_implemented_method") end |
#updated_at(fallback: nil) ⇒ Time
The entry’s last updated date. In the frontmatter, the last updated date can be specified using one of two fields. In priority order:
1. the `updated_at` field
2. the `updated` field
The developer could set a fallback value as a fallback. For example, when building RSS feeds one might want the value of ‘#published_at` if there is no last updated date.
308 309 310 311 312 |
# File 'lib/lifer/entry.rb', line 308 def updated_at(fallback: nil) date_for frontmatter[:updated_at], frontmatter[:updated], default_date: fallback end |