lifer 0.8.0 → 0.10.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea41a2cd1a058f5a103121b6b7641ce5857ec74300ecad4bb36ec33578170650
4
- data.tar.gz: f752dc7498a0457945d895fc591eefc7a27a296e01a5b547264a13fd8113c3b5
3
+ metadata.gz: f1d33c1f633f27b80005a2e2e7c1919f43d86a5fdba9f12523dd4dcdb4e47422
4
+ data.tar.gz: 37927e9a39b49363ee0de3f34294c4e8ccf82b83a7a73b8d86ebc1bae8243947
5
5
  SHA512:
6
- metadata.gz: 4665579521538df261c0839f6c1a7ee6b24362ca75c03cc6d8fbf42dfffa028ad0bc39c1fe01ef2407459cb1be6bdf9d08e60cd5abacd1e233b0819bbcab6186
7
- data.tar.gz: e1bfbd9fa63bd2de10022f2b5810cfcf518acc5112f51bb843c19c936bc269436807a606c335ab90693bafac53569315b0bfcbe245b9c8570a56ff6ab60af6f0
6
+ metadata.gz: db511f0ace1e617851b7e4de0fd12f9a615c283db318d3c05013cdadbae40ab89cd6be06bc429f4c443caf5d1c67f1d385276f4596788eadbfe3d22916e9c20d
7
+ data.tar.gz: 917d189530c40b4c15fb57a9d1bfce28a809b00fd07267b5a2485997adcb8c3e557dcf242def3a515297b908a5000902a1e7fcbe4bff29240791a88681b2fa1f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,42 @@
1
1
  ## Next
2
2
 
3
+ ## v0.10.0
4
+
5
+ These commits collect work to let all layout files (either Liquid or ERB files)
6
+ provide a reference to parent, or "root", layout files that should wrap the via
7
+ frontmatter.
8
+
9
+ Previously, we did this for Liquid layouts using the custom `layout` tag. But
10
+ because there was no equivalent tag for ERB files, I realized it would be less
11
+ work to just provide the value via frontmatter. The same way for every type of
12
+ layout file.
13
+
14
+ End users (just me?) must update their Lifer project Liquid layouts accordingly:
15
+
16
+ ```diff
17
+ - {% layout "layouts/root_layout.html.liquid" %}
18
+ + ---
19
+ + layout: layouts/root_layout.html.liquid
20
+ + ---
21
+
22
+ Layout content.
23
+ ```
24
+
25
+ ## v0.9.0
26
+
27
+ Atom feeds now support entries with both `#published_at` and `#updated_at`
28
+ timestamp. There is no standard equivalent way to provide this functonality for
29
+ RSS-format feeds, unfortunately. As part of this change, we removed all
30
+ `Entry#date` methods in favour of `Entry#published_at` onces. In Atom feeds, if
31
+ an article has no last updated date, the publication date is used instead.
32
+
33
+ Additionally, this release includes a new environment variable:
34
+ `LIFER_UNPARALLELIZED`. You can use this environment variable to run `lifer
35
+ build` or `lifer serve` without any parallelization turned on. This could be
36
+ useful for reproducing bugs and so on. Example usage:
37
+
38
+ LIFER_UNPARALLELIZED=1 lifer build
39
+
3
40
  ## v0.8.0
4
41
 
5
42
  ### Tags
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lifer (0.8.0)
4
+ lifer (0.10.0)
5
5
  i18n (< 2)
6
6
  kramdown (~> 2.4)
7
7
  liquid (~> 5.6, < 6)
@@ -32,9 +32,9 @@ GEM
32
32
  irb (~> 1.10)
33
33
  reline (>= 0.3.8)
34
34
  diff-lcs (1.5.1)
35
- ffi (1.17.1-arm64-darwin)
36
- ffi (1.17.1-x86_64-darwin)
37
- ffi (1.17.1-x86_64-linux-gnu)
35
+ ffi (1.17.2-arm64-darwin)
36
+ ffi (1.17.2-x86_64-darwin)
37
+ ffi (1.17.2-x86_64-linux-gnu)
38
38
  i18n (1.14.7)
39
39
  concurrent-ruby (~> 1.0)
40
40
  io-console (0.7.2)
@@ -44,7 +44,7 @@ GEM
44
44
  kramdown (2.5.1)
45
45
  rexml (>= 3.3.9)
46
46
  language_server-protocol (3.17.0.3)
47
- liquid (5.8.1)
47
+ liquid (5.8.6)
48
48
  bigdecimal
49
49
  strscan (>= 3.1.1)
50
50
  listen (3.9.0)
@@ -107,7 +107,7 @@ GEM
107
107
  sorbet-runtime (>= 0.5.10782)
108
108
  sorbet-runtime (0.5.11558)
109
109
  stringio (3.1.1)
110
- strscan (3.1.2)
110
+ strscan (3.1.5)
111
111
  xpath (3.2.0)
112
112
  nokogiri (~> 1.8)
113
113
  yard (0.9.37)
@@ -0,0 +1,66 @@
1
+ class Lifer::Builder
2
+ class HTML
3
+ # A base class for all HTML builder adapters. The methods provided by this
4
+ # class are either required or reusable by builder subclasses. See the
5
+ # committed HTML builder adapter classes for example implementations.
6
+ class FromAny
7
+ class << self
8
+ # Build and render an entry.
9
+ #
10
+ # @param entry [Lifer::Entry] The entry to be rendered.
11
+ # @return [String] The rendered entry.
12
+ def build(entry:)
13
+ new(entry: entry).render
14
+ end
15
+ end
16
+
17
+ # The base class does not provide a render method, but any subclass
18
+ # should be expected to.
19
+ #
20
+ # @raise [NotImplementedError]
21
+ def render
22
+ raise NotImplementedError,
23
+ "subclasses must implement a custom `#render` method"
24
+ end
25
+
26
+ private
27
+
28
+ # The frontmatter provided by the layout file.
29
+ #
30
+ # @return [Hash] The frontmatter represented as a hash.
31
+ def frontmatter
32
+ return {} unless frontmatter?
33
+
34
+ Lifer::Utilities.symbolize_keys(
35
+ YAML.load layout_file_contents(raw: true)[Lifer::FRONTMATTER_REGEX, 1],
36
+ permitted_classes: [Time]
37
+ )
38
+ end
39
+
40
+ # Checks whether frontmatter is present in the layout file.
41
+ #
42
+ # @return [boolean]
43
+ def frontmatter?
44
+ @frontmatter ||=
45
+ layout_file_contents(raw: true).match?(Lifer::FRONTMATTER_REGEX)
46
+ end
47
+
48
+ # The contents of the layout file.
49
+ #
50
+ # @param raw [boolean] Whether to include or exclude frontmatter from
51
+ # the contents.
52
+ # @return [String] The contents of the layout file.
53
+ def layout_file_contents(raw: false)
54
+ cache_variable = "@layout_file_contents_#{raw}"
55
+ cached_value = instance_variable_get cache_variable
56
+
57
+ return cached_value if cached_value
58
+
59
+ contents = File.read layout_file
60
+ contents = contents.gsub(Lifer::FRONTMATTER_REGEX, "") unless raw
61
+
62
+ instance_variable_set cache_variable, contents
63
+ end
64
+ end
65
+ end
66
+ end
@@ -23,23 +23,21 @@ class Lifer::Builder::HTML
23
23
  # </body>
24
24
  # </html>
25
25
  #
26
- class FromERB
27
- class << self
28
- # Build and render an entry.
29
- #
30
- # @param entry [Lifer::Entry] The entry to be rendered.
31
- # @return [String] The rendered entry.
32
- def build(entry:)
33
- new(entry: entry).render
34
- end
35
- end
36
-
26
+ class FromERB < FromAny
37
27
  # Reads the entry as ERB, given our renderer context (see the documentation
38
28
  # for `#build_binding_context`) and renders the production-ready entry.
39
29
  #
40
30
  # @return [String] The rendered entry.
41
31
  def render
42
- ERB.new(File.read layout_file).result context
32
+ document = ERB.new(layout_file_contents).result context
33
+
34
+ return document unless (relative_layout_path = frontmatter[:layout])
35
+
36
+ document_binding = binding.tap { |binding|
37
+ binding.local_variable_set :content, document
38
+ }
39
+ layout_path = "%s/%s" % [Lifer.root, relative_layout_path]
40
+ ERB.new(File.read layout_path).result(document_binding)
43
41
  end
44
42
 
45
43
  private
@@ -4,7 +4,9 @@ module Lifer::Builder::HTML::FromLiquid::Drops
4
4
  #
5
5
  # @example Usage
6
6
  # <h1>{{ entry.title }}</h1>
7
- # <small>Published on <datetime>{{ entry.date }}</datetime></small>
7
+ # <small>
8
+ # Published on <datetime>{{ entry.published_at }}</datetime>
9
+ # </small>
8
10
  #
9
11
  class EntryDrop < Liquid::Drop
10
12
  attr_accessor :lifer_entry, :collection
@@ -30,11 +32,6 @@ module Lifer::Builder::HTML::FromLiquid::Drops
30
32
  # @return [String]
31
33
  def content = (@content ||= lifer_entry.to_html)
32
34
 
33
- # The entry date (as a string).
34
- #
35
- # @return [String]
36
- def date = (@date ||= lifer_entry.date)
37
-
38
35
  # The entry frontmatter data.
39
36
  #
40
37
  # @return [FrontmatterDrop]
@@ -50,6 +47,11 @@ module Lifer::Builder::HTML::FromLiquid::Drops
50
47
  # @return [String] The entry permalink.
51
48
  def permalink = (@permalink ||= lifer_entry.permalink)
52
49
 
50
+ # The entry publication date (as a string).
51
+ #
52
+ # @return [String]
53
+ def published_at = (@published_at ||= lifer_entry.published_at)
54
+
53
55
  # The summary of the entry.
54
56
  #
55
57
  # @return [String] The summary of the entry.
@@ -59,5 +61,10 @@ module Lifer::Builder::HTML::FromLiquid::Drops
59
61
  #
60
62
  # @return [String] The entry title.
61
63
  def title = (@title ||= lifer_entry.title)
64
+
65
+ # The entry's last updated date (as a string).
66
+ #
67
+ # @return [String]
68
+ def updated_at = (@updated_at ||= lifer_entry.updated_at)
62
69
  end
63
70
  end
@@ -2,7 +2,7 @@
2
2
  # In many cases these utilities exist to be pseudo-compatible with Jekyll.
3
3
  #
4
4
  # @example A filter in a Liquid template.
5
- # {{ entry.date | date_to_xmlschema }}
5
+ # {{ entry.published_at | date_to_xmlschema }}
6
6
  #
7
7
  module Lifer::Builder::HTML::FromLiquid::Filters
8
8
  # @!visibility private
@@ -22,8 +22,6 @@ class Lifer::Builder::HTML::FromLiquid
22
22
  Liquid::LocalFileSystem.new(Lifer.root, "%s.html.liquid")
23
23
 
24
24
  environment.register_filter Lifer::Builder::HTML::FromLiquid::Filters
25
- environment.register_tag "layout",
26
- Lifer::Builder::HTML::FromLiquid::LayoutTag
27
25
  end
28
26
  end
29
27
  end
@@ -1,10 +1,5 @@
1
1
  require "liquid"
2
2
 
3
- require_relative "from_liquid/drops"
4
- require_relative "from_liquid/filters"
5
- require_relative "from_liquid/layout_tag"
6
- require_relative "from_liquid/liquid_env"
7
-
8
3
  class Lifer::Builder::HTML
9
4
  # If the HTML builder is given a Liquid template, it uses this class to parse
10
5
  # the Liquid into HTML. Lifer project metadata is provided as context. For
@@ -28,16 +23,10 @@ class Lifer::Builder::HTML
28
23
  # </body>
29
24
  # </html>
30
25
  #
31
- class FromLiquid
32
- class << self
33
- # Render and build a Lifer entry.
34
- #
35
- # @param entry [Lifer::Entry] The entry to render.
36
- # @return [String] The rendered entry, ready for output.
37
- def build(entry:) = new(entry:).render
38
- end
39
-
40
- attr_accessor :entry, :layout_file
26
+ class FromLiquid < FromAny
27
+ require_relative "from_liquid/drops"
28
+ require_relative "from_liquid/filters"
29
+ require_relative "from_liquid/liquid_env"
41
30
 
42
31
  # Reads the entry as Liquid, given our document context, and renders
43
32
  # an entry.
@@ -49,13 +38,23 @@ class Lifer::Builder::HTML
49
38
  .parse(entry.to_html, **parse_options)
50
39
  .render(context, **render_options)
51
40
  )
41
+ document = Liquid::Template
42
+ .parse(layout_file_contents, **parse_options)
43
+ .render(document_context, **render_options)
44
+
45
+ return document unless (relative_layout_path = frontmatter[:layout])
46
+
47
+ layout_path = "%s/%s" % [Lifer.root, relative_layout_path]
48
+ document_context = context.merge! "content" => document
52
49
  Liquid::Template
53
- .parse(layout, **parse_options)
50
+ .parse(File.read layout_path, **parse_options)
54
51
  .render(document_context, **render_options)
55
52
  end
56
53
 
57
54
  private
58
55
 
56
+ attr_accessor :entry, :layout_file
57
+
59
58
  def initialize(entry:)
60
59
  @entry = entry
61
60
  @layout_file = entry.collection.layout_file
@@ -79,19 +78,6 @@ class Lifer::Builder::HTML
79
78
  }
80
79
  end
81
80
 
82
- # @private
83
- # It's possible for the provided layout to request a parent layout, which
84
- # makes this method a bit complicated.
85
- #
86
- # @return [String] A Liquid layout document, ready for parsing.
87
- def layout
88
- contents = File.read layout_file
89
-
90
- return contents unless contents.match?(/\{%\s*#{LayoutTag::NAME}.*%\}/)
91
-
92
- contents + "\n{% #{LayoutTag::ENDNAME} %}"
93
- end
94
-
95
81
  def liquid_environment = (@liquid_environment ||= LiquidEnv.global)
96
82
 
97
83
  def parse_options
@@ -103,6 +89,7 @@ class Lifer::Builder::HTML
103
89
 
104
90
  def render_options
105
91
  {
92
+ registers: {file_system: liquid_environment.file_system},
106
93
  strict_variables: true,
107
94
  strict_filters: true
108
95
  }
@@ -33,6 +33,7 @@ require "fileutils"
33
33
  class Lifer::Builder::HTML < Lifer::Builder
34
34
  self.name = :html
35
35
 
36
+ require_relative "html/from_any"
36
37
  require_relative "html/from_erb"
37
38
  require_relative "html/from_liquid"
38
39
 
@@ -65,8 +65,7 @@ class Lifer::Builder::RSS < Lifer::Builder
65
65
  # The name of the format type, as needed by `RSS::Maker`, used by default by
66
66
  # this feed builder.
67
67
  #
68
- DEFAULT_MAkER_FORMAT_NAME = FORMATS[:rss]
69
-
68
+ DEFAULT_MAKER_FORMAT_NAME = FORMATS[:rss]
70
69
 
71
70
  self.name = :rss
72
71
  self.settings = [
@@ -96,7 +95,7 @@ class Lifer::Builder::RSS < Lifer::Builder
96
95
 
97
96
  return FORMATS[format] if FORMATS.keys.include? format
98
97
 
99
- DEFAULT_MAkER_FORMAT_NAME
98
+ DEFAULT_MAKER_FORMAT_NAME
100
99
  end
101
100
 
102
101
  # Traverses and renders an RSS feed for feedable collection.
@@ -220,8 +219,21 @@ class Lifer::Builder::RSS < Lifer::Builder
220
219
  rss_feed_item.link = lifer_entry.permalink
221
220
  rss_feed_item.title = lifer_entry.title
222
221
  rss_feed_item.summary = lifer_entry.summary
223
- rss_feed_item.updated = Time.now.to_s
224
- rss_feed_item.content_encoded = lifer_entry.to_html
222
+
223
+ if feed_format(lifer_entry.collection) == "atom"
224
+ rss_feed_item.content.content = lifer_entry.to_html
225
+ rss_feed_item.published = lifer_entry.published_at
226
+
227
+ # Note: RSS does not provide a standard way to share last updated
228
+ # timestamps at all, while Atom does. This is the reason there is no
229
+ # equivalent call in the condition for RSS feeds.
230
+ #
231
+ rss_feed_item.updated =
232
+ lifer_entry.updated_at(fallback: lifer_entry.published_at)
233
+ else
234
+ rss_feed_item.content_encoded = lifer_entry.to_html
235
+ rss_feed_item.pubDate = lifer_entry.published_at.to_time.rfc2822
236
+ end
225
237
  end
226
238
  end
227
239
 
@@ -57,9 +57,9 @@ class Lifer::Collection
57
57
  cached_entries_variable,
58
58
  case order
59
59
  when :latest
60
- @entries_collection.sort_by { |entry| entry.date }.reverse
60
+ @entries_collection.sort_by { |entry| entry.published_at }.reverse
61
61
  when :oldest
62
- @entries_collection.sort_by { |entry| entry.date }
62
+ @entries_collection.sort_by { |entry| entry.published_at }
63
63
  end
64
64
  )
65
65
  end
data/lib/lifer/entry.rb CHANGED
@@ -39,10 +39,6 @@ module Lifer
39
39
  #
40
40
  FILENAME_DATE_FORMAT = /^(\d{4}-\d{1,2}-\d{1,2})-/
41
41
 
42
- # We expect frontmatter to be provided in the following format.
43
- #
44
- FRONTMATTER_REGEX = /^---\n(.*)---\n/m
45
-
46
42
  # If tags are represented in YAML frontmatter as a string, they're split on
47
43
  # commas and/or spaces.
48
44
  #
@@ -147,27 +143,7 @@ module Lifer
147
143
  def body
148
144
  return full_text.strip unless frontmatter?
149
145
 
150
- full_text.gsub(FRONTMATTER_REGEX, "").strip
151
- end
152
-
153
- # Since text files would only store dates as simple strings, it's nice to
154
- # attempt to convert those into Ruby date or datetime objects.
155
- #
156
- # @return [Time] A Ruby representation of the date and time provided by the
157
- # entry frontmatter or filename.
158
- def date
159
- date_data = frontmatter[:date] || filename_date
160
-
161
- case date_data
162
- when Time then date_data
163
- when String then DateTime.parse(date_data).to_time
164
- else
165
- Lifer::Message.log("entry.no_date_metadata", filename: file)
166
- Lifer::Entry::DEFAULT_DATE
167
- end
168
- rescue ArgumentError => error
169
- Lifer::Message.error("entry.date_error", filename: file, error:)
170
- Lifer::Entry::DEFAULT_DATE
146
+ full_text.gsub(Lifer::FRONTMATTER_REGEX, "").strip
171
147
  end
172
148
 
173
149
  def feedable?
@@ -188,7 +164,8 @@ module Lifer
188
164
  return {} unless frontmatter?
189
165
 
190
166
  Lifer::Utilities.symbolize_keys(
191
- YAML.load(full_text[FRONTMATTER_REGEX, 1], permitted_classes: [Time])
167
+ YAML.load full_text[Lifer::FRONTMATTER_REGEX, 1],
168
+ permitted_classes: [Time]
192
169
  )
193
170
  end
194
171
 
@@ -232,6 +209,27 @@ module Lifer
232
209
  # @return [String] The absolute URI path to the entry.
233
210
  def path = permalink(host: "/")
234
211
 
212
+ # The entry's publication date. The published date can be inferred in a few
213
+ # ways. The priority is:
214
+ #
215
+ # 1. the frontmatter's `published_at` field
216
+ # 2. the frontmatter's `published` field
217
+ # 3. the frontamtter's `date` field
218
+ # 4. The date in the filename.
219
+ #
220
+ # Since text files would only store dates as simple strings, it's nice to
221
+ # attempt to convert those into Ruby date or datetime objects.
222
+ #
223
+ # @return [Time] A Ruby representation of the date and time provided by the
224
+ # entry frontmatter or filename.
225
+ def published_at
226
+ date_for frontmatter[:published_at],
227
+ frontmatter[:published],
228
+ frontmatter[:date],
229
+ filename_date,
230
+ missing_metadata_translation_key: "entry.no_published_at_metadata"
231
+ end
232
+
235
233
  # If given a summary in the frontmatter of the entry, we can use this to
236
234
  # provide a summary.
237
235
  #
@@ -263,6 +261,26 @@ module Lifer
263
261
  raise NotImplementedError, I18n.t("shared.not_implemented_method")
264
262
  end
265
263
 
264
+ # The entry's last updated date. In the frontmatter, the last updated date
265
+ # can be specified using one of two fields. In priority order:
266
+ #
267
+ # 1. the `updated_at` field
268
+ # 2. the `updated` field
269
+ #
270
+ # The developer could set a fallback value as a fallback. For example, when
271
+ # building RSS feeds one might want the value of `#published_at` if there is
272
+ # no last updated date.
273
+ #
274
+ # @param fallback [Time, String, NilClass] Provide datetime data, a string
275
+ # that parses to a datetime object, or nil.
276
+ # @return [Time] A Ruby representation of the date and time provided by the
277
+ # entry frontmatter.
278
+ def updated_at(fallback: nil)
279
+ date_for frontmatter[:updated_at],
280
+ frontmatter[:updated],
281
+ default_date: fallback
282
+ end
283
+
266
284
  private
267
285
 
268
286
  # It is conventional for users to use spaces or commas to delimit tags in
@@ -278,12 +296,33 @@ module Lifer
278
296
  end.uniq
279
297
  end
280
298
 
299
+ def date_for(
300
+ *candidate_date_fields,
301
+ default_date: Lifer::Entry::DEFAULT_DATE,
302
+ missing_metadata_translation_key: nil
303
+ )
304
+ date_data = candidate_date_fields.detect(&:itself)
305
+
306
+ case date_data
307
+ when Time then date_data
308
+ when String then DateTime.parse(date_data).to_time
309
+ else
310
+ if (translation_string = missing_metadata_translation_key)
311
+ Lifer::Message.log(translation_string, filename: file)
312
+ end
313
+ default_date
314
+ end
315
+ rescue ArgumentError => error
316
+ Lifer::Message.error("entry.date_error", filename: file, error:)
317
+ default_date
318
+ end
319
+
281
320
  def filename_date
282
321
  return unless file && File.basename(file).match?(FILENAME_DATE_FORMAT)
283
322
 
284
323
  File.basename(file).match(FILENAME_DATE_FORMAT)[1]
285
324
  end
286
325
 
287
- def frontmatter? = (full_text && full_text.match?(FRONTMATTER_REGEX))
326
+ def frontmatter? = (full_text && full_text.match?(Lifer::FRONTMATTER_REGEX))
288
327
  end
289
328
  end
@@ -76,7 +76,10 @@ module Lifer::Utilities
76
76
  # @raise [Exception] Any exception thrown by a child process.
77
77
  # @return [Array] The mapped results of the operation.
78
78
  def parallelized(collection, &block)
79
- results = Parallel.map(collection) do |collection_item|
79
+ options = {}
80
+ options[:in_threads] = 0 if Lifer.parallelism_disabled?
81
+
82
+ results = Parallel.map(collection, **options) do |collection_item|
80
83
  begin
81
84
  yield collection_item
82
85
  rescue => error
data/lib/lifer/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lifer
2
- VERSION = "0.8.0"
2
+ VERSION = "0.10.0"
3
3
  end
data/lib/lifer.rb CHANGED
@@ -24,6 +24,10 @@ module Lifer
24
24
  "(\\/\\.)+" # Contains a dot directory.
25
25
  ] | IGNORE_DIRECTORIES.map { |d| "^(#{d})" }
26
26
 
27
+ # We expect frontmatter in any file to be provided in the following format.
28
+ #
29
+ FRONTMATTER_REGEX = /^---\n(.*)---\n/m
30
+
27
31
  class << self
28
32
  # The first time `Lifer.brain` is referenced, we build a new `Lifer::Brain`
29
33
  # object that is used and reused until the current process has ended.
@@ -96,6 +100,16 @@ module Lifer
96
100
  # project would be built to.
97
101
  def output_directory = brain.output_directory
98
102
 
103
+ # Returns false if the Lifer project will be built with parallelism. This
104
+ # should return false almost always--unless you've explicitly set the
105
+ # `LIFER_UNPARALLELIZED` environment variable before running the program.
106
+ #
107
+ # This method is used internally by Lifer to determine whether features that
108
+ # would normally run in parallel should *not* run in parallel for some reason.
109
+ #
110
+ # @return [boolean] Returns whether parallelism is disabled.
111
+ def parallelism_disabled? = ENV["LIFER_UNPARALLELIZED"].is_a?(String)
112
+
99
113
  # Register new settings so that they are "safe" and can be read from a Lifer
100
114
  # configuration file. Unregistered settings are ignored.
101
115
  #
data/locales/en.yml CHANGED
@@ -33,7 +33,7 @@ en:
33
33
  date_error: "[%{filename}]: %{error}"
34
34
  feedable_error: >
35
35
  please set `%{entry_class}.include_in_feeds` to true or false
36
- no_date_metadata: "[%{filename}]: no date metadata"
36
+ no_published_at_metadata: "[%{filename}]: no `published_at` metadata"
37
37
  not_found: >
38
38
  file "%{file}" does not exist
39
39
  config:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lifer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - benjamin wil
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-03-11 00:00:00.000000000 Z
11
+ date: 2025-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -159,6 +159,7 @@ files:
159
159
  - lib/lifer/brain.rb
160
160
  - lib/lifer/builder.rb
161
161
  - lib/lifer/builder/html.rb
162
+ - lib/lifer/builder/html/from_any.rb
162
163
  - lib/lifer/builder/html/from_erb.rb
163
164
  - lib/lifer/builder/html/from_liquid.rb
164
165
  - lib/lifer/builder/html/from_liquid/drops.rb
@@ -170,7 +171,6 @@ files:
170
171
  - lib/lifer/builder/html/from_liquid/drops/tag_drop.rb
171
172
  - lib/lifer/builder/html/from_liquid/drops/tags_drop.rb
172
173
  - lib/lifer/builder/html/from_liquid/filters.rb
173
- - lib/lifer/builder/html/from_liquid/layout_tag.rb
174
174
  - lib/lifer/builder/html/from_liquid/liquid_env.rb
175
175
  - lib/lifer/builder/rss.rb
176
176
  - lib/lifer/builder/txt.rb
@@ -210,8 +210,8 @@ licenses:
210
210
  - MIT
211
211
  metadata:
212
212
  allowed_push_host: https://rubygems.org
213
- homepage_uri: https://github.com/benjaminwil/lifer/blob/v0.8.0/README.md
214
- source_code_uri: https://github.com/benjaminwil/lifer/tree/v0.8.0
213
+ homepage_uri: https://github.com/benjaminwil/lifer/blob/v0.10.0/README.md
214
+ source_code_uri: https://github.com/benjaminwil/lifer/tree/v0.10.0
215
215
  changelog_uri: https://github.com/benjaminwil/lifer/blob/main/CHANGELOG.md
216
216
  post_install_message:
217
217
  rdoc_options: []
@@ -1,66 +0,0 @@
1
- class Lifer::Builder::HTML::FromLiquid
2
- # Note that if you want to learn more about the shape of this class, check out
3
- # `Liquid::Block` in the `liquid` gem.
4
- #
5
- # The layout tag is a bit magic. The idea here is to emulate how Jekyll
6
- # handles `layout:` YAML frontmatter within entries to change the normal
7
- # parent layout to an override parent layout--but without the need for
8
- # frontmatter.
9
- #
10
- # The reason we took this strategy was to avoid pre-processing every entry for
11
- # frontmatter when we didn't need to. Maybe in the long run this was a bad
12
- # call? I don't know.
13
- #
14
- # @example Usage from a Liquid template.
15
- # {% layout "path/to/my_liquid_layout_template" %}
16
- #
17
- # (The required `endlayout` tag will be appended to the end of the file
18
- # on render if you do not insert it yourself.
19
- #
20
- class LayoutTag < Liquid::Block
21
- # The name of the tag in Liquid templates, `layout`.
22
- #
23
- NAME = :layout
24
-
25
- # The end name of the tag in Liquid templates, `endlayout`.
26
- #
27
- ENDNAME = ("end%s" % NAME).to_sym
28
-
29
- def initialize(layout, path, options)
30
- @path = path.delete("\"").strip
31
- super
32
- end
33
-
34
- # A layout tag wraps an entire document and outputs it inside of whatever
35
- # the `@layout` is. This lets a child document specify a parernt layout!
36
- # Very confusing stuff.
37
- #
38
- # @param context [Liquid::Context] All of the context of the Liquid
39
- # document that would be rendered.
40
- # @return [String] A rendered document.
41
- def render(context)
42
- document_context = context.environments.first
43
- parse_options = document_context["parse_options"]
44
- liquid_file_system = parse_options[:environment].file_system
45
- render_options = document_context["render_options"]
46
-
47
- current_layout_file = File
48
- .read(document_context["entry"]["collection"]["layout_file"])
49
- .gsub(/\{%\s*#{tag_name}.+%\}/, "")
50
-
51
- content_with_layout = Liquid::Template
52
- .parse(current_layout_file, **parse_options)
53
- .render(document_context, **render_options)
54
-
55
- Liquid::Template
56
- .parse(
57
- liquid_file_system.read_template_file(@path),
58
- **parse_options
59
- )
60
- .render(
61
- document_context.merge({"content" => content_with_layout}),
62
- **render_options
63
- )
64
- end
65
- end
66
- end