lifer 0.2.0 → 0.3.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +1 -1
  3. data/.gitignore +1 -0
  4. data/CHANGELOG.md +26 -0
  5. data/Gemfile +9 -0
  6. data/Gemfile.lock +110 -25
  7. data/LICENSE +18 -0
  8. data/README.md +79 -14
  9. data/Rakefile +2 -4
  10. data/bin/lifer +4 -2
  11. data/lib/lifer/brain.rb +171 -21
  12. data/lib/lifer/builder/html/from_erb.rb +92 -0
  13. data/lib/lifer/builder/html/from_liquid/drops/collection_drop.rb +40 -0
  14. data/lib/lifer/builder/html/from_liquid/drops/collections_drop.rb +40 -0
  15. data/lib/lifer/builder/html/from_liquid/drops/entry_drop.rb +63 -0
  16. data/lib/lifer/builder/html/from_liquid/drops/frontmatter_drop.rb +45 -0
  17. data/lib/lifer/builder/html/from_liquid/drops/settings_drop.rb +42 -0
  18. data/lib/lifer/builder/html/from_liquid/drops.rb +15 -0
  19. data/lib/lifer/builder/html/from_liquid/filters.rb +27 -0
  20. data/lib/lifer/builder/html/from_liquid/layout_tag.rb +67 -0
  21. data/lib/lifer/builder/html/from_liquid.rb +116 -0
  22. data/lib/lifer/builder/html.rb +107 -51
  23. data/lib/lifer/builder/rss.rb +113 -0
  24. data/lib/lifer/builder/txt.rb +60 -0
  25. data/lib/lifer/builder.rb +100 -1
  26. data/lib/lifer/cli.rb +105 -0
  27. data/lib/lifer/collection.rb +87 -8
  28. data/lib/lifer/config.rb +159 -31
  29. data/lib/lifer/dev/response.rb +61 -0
  30. data/lib/lifer/dev/router.rb +44 -0
  31. data/lib/lifer/dev/server.rb +97 -0
  32. data/lib/lifer/entry/html.rb +39 -0
  33. data/lib/lifer/entry/markdown.rb +162 -0
  34. data/lib/lifer/entry/txt.rb +41 -0
  35. data/lib/lifer/entry.rb +142 -41
  36. data/lib/lifer/message.rb +58 -0
  37. data/lib/lifer/selection/all_markdown.rb +16 -0
  38. data/lib/lifer/selection/included_in_feeds.rb +15 -0
  39. data/lib/lifer/selection.rb +79 -0
  40. data/lib/lifer/shared/finder_methods.rb +35 -0
  41. data/lib/lifer/shared.rb +6 -0
  42. data/lib/lifer/templates/cli.txt.erb +10 -0
  43. data/lib/lifer/templates/config.yaml +77 -0
  44. data/lib/lifer/templates/its-a-living.png +0 -0
  45. data/lib/lifer/templates/layout.html.erb +1 -1
  46. data/lib/lifer/uri_strategy/pretty.rb +14 -6
  47. data/lib/lifer/uri_strategy/pretty_root.rb +24 -0
  48. data/lib/lifer/uri_strategy/pretty_yyyy_mm_dd.rb +32 -0
  49. data/lib/lifer/uri_strategy/root.rb +17 -0
  50. data/lib/lifer/uri_strategy/simple.rb +10 -6
  51. data/lib/lifer/uri_strategy.rb +46 -6
  52. data/lib/lifer/utilities.rb +117 -0
  53. data/lib/lifer/version.rb +3 -0
  54. data/lib/lifer.rb +130 -23
  55. data/lifer.gemspec +12 -6
  56. data/locales/en.yml +54 -0
  57. metadata +142 -9
  58. data/lib/lifer/layout.rb +0 -25
  59. data/lib/lifer/templates/config +0 -4
  60. data/lib/lifer/uri_strategy/base.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5891938dbf0269f6cf30b14cd14130025b2214e0b03b6c756d48efa1abf8ae3
4
- data.tar.gz: a6bb29832ac1e2ccde939d17f6c84643c5d8f3544d0cda7f407a696d642836e7
3
+ metadata.gz: 5b5555d8af73f17e139a069f5b18b104c7938cf8089525ecd3d27b703d388d64
4
+ data.tar.gz: 83ed1f8052bb3f7e241276ca2e7354f870429e5fd5ff5a5a2a97c36d1d756c4c
5
5
  SHA512:
6
- metadata.gz: 6cd12ec2588d1afc192352219a98e04672ce721069160bc5b3f0db5e2c91998a156318d30ee7a3299d062f32127b0cf9cc9d7eea7ece320212627c3e27344d91
7
- data.tar.gz: 1506e4a3bf8957dce6dbacccf25d75a52edf710c886a8955b979dede89b698dfc8f0a8dd1571fa6275ad8737ad0cdc2e9897503b16bb848bcaef2027ddfb8fcf
6
+ metadata.gz: b79197172aedc215a7d1acab9665406e5065b0aa32451ca5b76d89742021660f87c6ab6366edb581ab2477ad400a3a741468480d5a428cab1113544e11485c3a
7
+ data.tar.gz: e09e4484fb63f9b093b7a03ddff94ee49e0dc7c3bca1fe68e316540c9a02f4561f215f7c32bb77e842c83d1e63f30d57d252569218b8d2eddf2aa8823ce06d15
@@ -11,7 +11,7 @@ jobs:
11
11
  - name: Set up Ruby
12
12
  uses: ruby/setup-ruby@v1
13
13
  with:
14
- ruby-version: 3.1.2
14
+ ruby-version: 3.3.4
15
15
  bundler-cache: true
16
16
  - name: Run the default task
17
17
  run: bundle exec rake
data/.gitignore CHANGED
@@ -11,3 +11,4 @@ lifer*.gem
11
11
 
12
12
  # Temp files.
13
13
  /tmp/
14
+ /doc/
data/CHANGELOG.md ADDED
@@ -0,0 +1,26 @@
1
+ ## v0.3.0
2
+
3
+ This version marks the first version of Lifer that is kind of usable. The README
4
+ currently describes the big picture best. But I can that as of this version,
5
+ I've documented all of the public interfaces and added a good number of `FIXME`
6
+ comments to indicate functionality that _works_ but isn't quite where I want it
7
+ to be long term.
8
+
9
+ To manually test everything, I took my legacy Jekyll-based static site and
10
+ successfully ported it to Lifer.
11
+
12
+ The biggest thorn in my side is the Liquid rendering implementation. It works,
13
+ but the amount of trouble it was, and the not-very-serious way Liquid reports
14
+ rendering issues after build time, makes me think that this will come back to
15
+ haunt me.
16
+
17
+ Special thanks to [Chris][1] for helping me with some loading issues and
18
+ [Madeline][2] for helping me diagnose some disgusting Liquid template rendering
19
+ issues.
20
+
21
+ [1]: https://github.com/forkata
22
+ [2]: https://github.com/madelinecollier
23
+
24
+ ## v0.2.0
25
+
26
+ ![It's a living](lib/lifer/templates/its-a-living.png)
data/Gemfile CHANGED
@@ -4,5 +4,14 @@ source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
6
 
7
+ gem "bump"
8
+
9
+ gem "capybara"
10
+
11
+ gem "debug", ">= 1.0.0"
7
12
  gem "rake", "~> 13.0"
8
13
  gem "rspec", "~> 3.0"
14
+ gem "parallel_tests"
15
+ gem "ruby-lsp"
16
+
17
+ gem "yard"
data/Gemfile.lock CHANGED
@@ -1,48 +1,133 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lifer (0.1.0)
4
+ lifer (0.3.0)
5
+ i18n (< 2)
5
6
  kramdown (~> 2.4)
7
+ liquid (< 6)
8
+ listen (< 4)
9
+ puma (< 7)
10
+ rack (< 4)
11
+ rss
6
12
 
7
13
  GEM
8
14
  remote: https://rubygems.org/
9
15
  specs:
10
- debug (1.6.2)
11
- irb (>= 1.3.6)
12
- reline (>= 0.3.1)
13
- diff-lcs (1.5.0)
14
- io-console (0.5.11)
15
- irb (1.4.1)
16
- reline (>= 0.3.0)
17
- kramdown (2.4.0)
18
- rexml
19
- rake (13.0.6)
20
- reline (0.3.1)
16
+ addressable (2.8.7)
17
+ public_suffix (>= 2.0.2, < 7.0)
18
+ bigdecimal (3.1.9)
19
+ bump (0.10.0)
20
+ capybara (3.40.0)
21
+ addressable
22
+ matrix
23
+ mini_mime (>= 0.1.3)
24
+ nokogiri (~> 1.11)
25
+ rack (>= 1.6.0)
26
+ rack-test (>= 0.6.3)
27
+ regexp_parser (>= 1.5, < 3.0)
28
+ xpath (~> 3.2)
29
+ concurrent-ruby (1.3.4)
30
+ debug (1.9.2)
31
+ irb (~> 1.10)
32
+ reline (>= 0.3.8)
33
+ diff-lcs (1.5.1)
34
+ ffi (1.17.1-arm64-darwin)
35
+ ffi (1.17.1-x86_64-darwin)
36
+ ffi (1.17.1-x86_64-linux-gnu)
37
+ i18n (1.14.6)
38
+ concurrent-ruby (~> 1.0)
39
+ io-console (0.7.2)
40
+ irb (1.14.0)
41
+ rdoc (>= 4.0.0)
42
+ reline (>= 0.4.2)
43
+ kramdown (2.5.1)
44
+ rexml (>= 3.3.9)
45
+ language_server-protocol (3.17.0.3)
46
+ liquid (5.6.0)
47
+ bigdecimal
48
+ strscan
49
+ listen (3.9.0)
50
+ rb-fsevent (~> 0.10, >= 0.10.3)
51
+ rb-inotify (~> 0.9, >= 0.9.10)
52
+ logger (1.6.1)
53
+ matrix (0.4.2)
54
+ mini_mime (1.1.5)
55
+ nio4r (2.7.4)
56
+ nokogiri (1.16.7-arm64-darwin)
57
+ racc (~> 1.4)
58
+ nokogiri (1.16.7-x86_64-darwin)
59
+ racc (~> 1.4)
60
+ nokogiri (1.16.7-x86_64-linux)
61
+ racc (~> 1.4)
62
+ parallel (1.26.3)
63
+ parallel_tests (4.7.2)
64
+ parallel
65
+ prism (1.0.0)
66
+ psych (5.1.2)
67
+ stringio
68
+ public_suffix (6.0.1)
69
+ puma (6.5.0)
70
+ nio4r (~> 2.0)
71
+ racc (1.8.1)
72
+ rack (3.1.7)
73
+ rack-test (2.1.0)
74
+ rack (>= 1.3)
75
+ rake (13.2.1)
76
+ rb-fsevent (0.11.2)
77
+ rb-inotify (0.11.1)
78
+ ffi (~> 1.0)
79
+ rbs (3.5.3)
80
+ logger
81
+ rdoc (6.7.0)
82
+ psych (>= 4.0.0)
83
+ regexp_parser (2.9.2)
84
+ reline (0.5.10)
21
85
  io-console (~> 0.5)
22
- rexml (3.2.5)
23
- rspec (3.11.0)
24
- rspec-core (~> 3.11.0)
25
- rspec-expectations (~> 3.11.0)
26
- rspec-mocks (~> 3.11.0)
27
- rspec-core (3.11.0)
28
- rspec-support (~> 3.11.0)
29
- rspec-expectations (3.11.0)
86
+ rexml (3.4.0)
87
+ rspec (3.13.0)
88
+ rspec-core (~> 3.13.0)
89
+ rspec-expectations (~> 3.13.0)
90
+ rspec-mocks (~> 3.13.0)
91
+ rspec-core (3.13.1)
92
+ rspec-support (~> 3.13.0)
93
+ rspec-expectations (3.13.3)
30
94
  diff-lcs (>= 1.2.0, < 2.0)
31
- rspec-support (~> 3.11.0)
32
- rspec-mocks (3.11.1)
95
+ rspec-support (~> 3.13.0)
96
+ rspec-mocks (3.13.1)
33
97
  diff-lcs (>= 1.2.0, < 2.0)
34
- rspec-support (~> 3.11.0)
35
- rspec-support (3.11.0)
98
+ rspec-support (~> 3.13.0)
99
+ rspec-support (3.13.1)
100
+ rss (0.3.1)
101
+ rexml
102
+ ruby-lsp (0.17.17)
103
+ language_server-protocol (~> 3.17.0)
104
+ prism (~> 1.0)
105
+ rbs (>= 3, < 4)
106
+ sorbet-runtime (>= 0.5.10782)
107
+ sorbet-runtime (0.5.11558)
108
+ stringio (3.1.1)
109
+ strscan (3.1.2)
110
+ xpath (3.2.0)
111
+ nokogiri (~> 1.8)
112
+ yard (0.9.37)
36
113
 
37
114
  PLATFORMS
115
+ arm64-darwin-22
38
116
  x86_64-darwin-21
117
+ x86_64-darwin-22
39
118
  x86_64-linux
40
119
 
41
120
  DEPENDENCIES
42
- debug
121
+ bump
122
+ capybara
123
+ debug (>= 1.0.0)
43
124
  lifer!
125
+ nokogiri
126
+ parallel_tests
44
127
  rake (~> 13.0)
45
128
  rspec (~> 3.0)
129
+ ruby-lsp
130
+ yard
46
131
 
47
132
  BUNDLED WITH
48
133
  2.3.21
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright 2024 benjamin wil
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the “Software”), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,35 +1,100 @@
1
1
  # Lifer
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/lifer`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Lifer is an extensible static site generator. Out of the box, it provides a
4
+ classic static site generation experience, complete with RSS feeds, ERB template
5
+ rendering, and Liquid template rendering. Unlike other Ruby-based static site
6
+ generators, Lifer encourages you to bring your own asset pipeline and configure
7
+ it as a pre-build step.
4
8
 
5
- TODO: Delete this and the text above, and describe your gem
9
+ _Lifer is currently in pre-release. Features are incomplete. Your mileage may
10
+ vary._
11
+
12
+ **What's with the name?** Lifer aims to be easy to maintain for the lifetime of
13
+ your static site by requiring few dependencies and being very extensible by the
14
+ end user. There is no need for plugins in the form of separate Ruby gems. The
15
+ generator should also "breathe life" into your project because it's so easy to
16
+ use (🤞).
17
+
18
+ ## Features
19
+
20
+ Here's a short overview of Lifer's flagship features.
21
+
22
+ ### Bring your own asset pipeline
23
+
24
+ Whether you want to compile assets with Ruby-based tools, JavaScript-based
25
+ tools, or other tools, Lifer is okay with that. As long as those tools come with
26
+ a commandline interface, Lifer can shell out to those tools as a prebuild step.
27
+
28
+ The tradeoff here is that your templates will not be asset aware, meaning asset
29
+ fingerprinting and complex asset locating isn't really possible at this time. If
30
+ you need features like that, consider other static site generators or consider
31
+ *not* using a static site generator.
32
+
33
+ ### Collections and selections
34
+
35
+ If you have multiple collections of entries that must be output in different
36
+ ways, Lifer can help you do this. While every entry can only belong to a single
37
+ collection, you can create your own "selections" filter to group entries across
38
+ collections.
39
+
40
+ ### Extensibility
41
+
42
+ Lifer autoloads any Ruby files included in the root of your project
43
+ automatically. This lets you specify your own custom output builders, feed
44
+ formats, and meta-collections of entries.
45
+
46
+ ### Development server
47
+
48
+ Need to preview your static site before your build it on your production server?
49
+ No problem. Just use the Lifer commandline interface to start a development
50
+ server at `http://localhost:9292`:
51
+
52
+ $ lifer serve
53
+
54
+ The development server is not very sophisticated and can still be improved. But
55
+ for previewing new entries? It works just fine.
6
56
 
7
57
  ## Installation
8
58
 
9
- Add this line to your application's Gemfile:
59
+ _This installation guide assumes you already have Ruby 3 installed on your
60
+ system._
61
+
62
+ I recommend installing Lifer via Bundler. In the root directory of your static
63
+ site source, add a Gemfile if one doesn't exist already:
64
+
65
+ $ bundle init
66
+
67
+ In the Gemfile, add the `lifer` gem:
10
68
 
11
69
  ```ruby
12
- gem 'lifer'
70
+ gem "lifer", "<= 1"
13
71
  ```
14
72
 
15
73
  And then execute:
16
74
 
17
75
  $ bundle install
18
76
 
19
- Or install it yourself as:
20
-
21
- $ gem install lifer
77
+ ## Development
22
78
 
23
- ## Usage
79
+ _This development guide assumes you already have Ruby 3 installed on your
80
+ system._
24
81
 
25
- TODO: Write usage instructions here
82
+ Clone this repository, install dependencies via Bundler, and ensure the test
83
+ suite can run on your machine:
26
84
 
27
- ## Development
85
+ $ git clone https://github.com/benjaminwil/lifer lifer
86
+ $ cd lifer
87
+ $ bundle install
88
+ $ bundle exec rspec
28
89
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
90
+ ## Contributing
30
91
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
92
+ I'm not currently accepting unsolicited contributions to Lifer. I'm still
93
+ figuring out what the shape of this project is.
32
94
 
33
- ## Contributing
95
+ If you encounter bugs, please open an issue.
34
96
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/lifer.
97
+ If you have ideas for improving existing functionality or adding *missing*
98
+ functionality, please open an issue. Maybe there is room for you to contribute,
99
+ but I don't want you to waste your time preparing a merge request that I won't
100
+ accept.
data/Rakefile CHANGED
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
4
+ require "parallel_tests/tasks"
5
5
 
6
- RSpec::Core::RakeTask.new(:spec)
7
-
8
- task default: :spec
6
+ task default: :"parallel:spec"
data/bin/lifer CHANGED
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env -S ruby -Eutf-8
2
2
 
3
3
  require "bundler/setup"
4
- require_relative "../lib/lifer"
5
4
 
6
- Lifer.build
5
+ require "lifer"
6
+ require "lifer/cli"
7
+
8
+ Lifer::CLI.start!
data/lib/lifer/brain.rb CHANGED
@@ -1,45 +1,195 @@
1
+ require "fileutils"
2
+
3
+ require_relative "config"
4
+
5
+ # The brain is the object that keeps track of all essential information about
6
+ # the current Lifer project. Usually this information will be consumed via the
7
+ # `Lifer` module methods.
8
+ #
1
9
  class Lifer::Brain
10
+ # The default configuration file URI.
11
+ #
12
+ DEFAULT_CONFIG_FILE_URI = ".config/lifer.yaml"
13
+
2
14
  attr_reader :root
3
15
 
4
16
  class << self
5
- def init(root: Dir.pwd)
6
- new(root: root)
7
- end
17
+ # The preferred initializer for the single `Lifer::Brain` object that
18
+ # represents the user's Lifer project.
19
+ #
20
+ # @param root [String] The root Lifer project directory.
21
+ # @param config_file [String] A path to the correct Lifer config file. If
22
+ # left empty, the brain uses the one at the default path or the one
23
+ # bundled with the gem.
24
+ # @return [Lifer::Brain] The brain object for the current Lifer project.
25
+ def init(root: Dir.pwd, config_file: nil) = new(root:, config_file:)
8
26
  end
9
27
 
10
- def build!
11
- Lifer::Builder::HTML.execute(root: root)
28
+ # Destroy any existing build output and then build the Lifer project with all
29
+ # configured `Lifer::Builder`s.
30
+ #
31
+ # @param environment [Symbol] The current Lifer environment.
32
+ # @return [void] This builds the Lifer site to the configured output
33
+ # directory.
34
+ def build!(environment: :build)
35
+ brainwash!
36
+
37
+ prebuild_steps =
38
+ case setting(:global, :prebuild)
39
+ when Array, NilClass then setting(:global, :prebuild)
40
+ when Hash then setting(:global, :prebuild, environment)
41
+ end
42
+
43
+ builder_list =
44
+ case setting(:global, :build)
45
+ when Array, NilClass then setting(:global, :build)
46
+ when Hash then setting(:global, :build, environment)
47
+ end
48
+
49
+ Lifer::Builder.prebuild!(*prebuild_steps, root:)
50
+ Lifer::Builder.build!(*builder_list, root:)
12
51
  end
13
52
 
53
+ # Returns all collections and selections within the Lifer root.
54
+ #
55
+ # Collections only exist if they're explicitly configured in a configuration
56
+ # file and they match a subdirectory within the root.
57
+ #
58
+ # Selections, on the other hand, reorganize entries from literal collections.
59
+ # For example, a user could collect all of their entries that were authored
60
+ # by Harry B. Cutler.
61
+ #
62
+ # Every Lifer build contains at least one collection. (That collection is
63
+ # `:root`.)
64
+ #
65
+ # @return [Array<Lifer::Collection>] All the collections for the current Lifer
66
+ # project.
14
67
  def collections
15
- @collections ||=
68
+ @collections ||= generate_collections + generate_selections
69
+ end
70
+
71
+ # Returns the Lifer project's configuration object.
72
+ #
73
+ # @return [Lifer::Config] The Lifer configuration object.
74
+ def config = (@config ||= Lifer::Config.build file: config_file_location)
75
+
76
+ # Returns all entries that have been added to the manifest. If all is working
77
+ # as intended, this should be every entry ever generated.
78
+ #
79
+ # @return [Set<Lifer::Entry>] All entries that currently exist.
80
+ def entry_manifest = (@entry_manifest ||= Set.new)
81
+
82
+ # A manifest of all Lifer project entries.
83
+ #
84
+ # @return [Set<Lifer::Entry>] A set of all entries.
85
+ def manifest = (@manifest ||= Set.new)
86
+
87
+ # Returns the build directory for the Lifer project's build output.
88
+ #
89
+ # @return [String] The Lifer build directory.
90
+ def output_directory
91
+ @output_directory ||=
16
92
  begin
17
- collection_map =
18
- config.collections.map { |collection_name|
19
- [collection_name, "#{root}/#{collection_name}"]
20
- }.to_h.merge!({root: root})
21
-
22
- collection_map.map { |name, dir|
23
- Lifer::Collection.generate(name: name, directory: dir)
24
- }
93
+ dir = "%s/%s" % [root, setting(:global, :output_directory)]
94
+
95
+ return Pathname(dir) if Dir.exist? dir
96
+
97
+ Dir.mkdir(dir)
98
+ Pathname(dir)
25
99
  end
26
100
  end
27
101
 
28
- def config
29
- @config ||= Lifer::Config.build(file: config_file_location)
102
+ # The user can bring their own Ruby files to be read by Lifer. This ensures
103
+ # they are loaded before the build starts.
104
+ #
105
+ # Note that the user's Bundler path may be in scope, so we need to skip
106
+ # those Ruby files.
107
+ #
108
+ # @return [void]
109
+ def require_user_provided_ruby_files!
110
+ return if root.include? Lifer.gem_root
111
+
112
+ rb_files = Dir.glob("#{root}/**/*.rb", File::FNM_DOTMATCH)
113
+
114
+ if Bundler.bundle_path.to_s.include? root
115
+ rb_files -=
116
+ Dir.glob("#{Bundler.bundle_path}/**/*.rb", File::FNM_DOTMATCH)
117
+ end
118
+
119
+ rb_files.each do |rb_file|
120
+ load rb_file
121
+ end
30
122
  end
31
123
 
32
- def manifest
33
- @manifest ||= Set.new
124
+ # Given the tree of a setting name, and the setting scope, returns the setting
125
+ # value. If the in-scope collection does not have a configured setting, this
126
+ # method will return fallback settings (unless `:strict` is `true`).
127
+ #
128
+ # Example usage:
129
+ #
130
+ # setting(:my, :great, :setting)
131
+ #
132
+ # @overload setting(path, ..., collection: nil, strict: false)
133
+ # @param name [Symbol] A key in the tree to a setting value.
134
+ # @param ... [Symbol] Any additional keys in the tree.
135
+ # @param collection [Lifer::Collection] The collection to scope the result
136
+ # to.
137
+ # @param strict [boolean] If true, do not return fallback setting values.
138
+ # @return [Array, String] The value of the requested setting.
139
+ def setting(*name, collection: nil, strict: false)
140
+ config.setting *name, collection_name: collection&.name, strict: strict
34
141
  end
35
142
 
36
143
  private
37
144
 
38
- def initialize(root:)
145
+ attr_reader :config_file_location
146
+
147
+ def initialize(root:, config_file:)
39
148
  @root = root
149
+ @config_file_location = build_config_file_location(config_file)
40
150
  end
41
151
 
42
- def config_file_location
43
- File.join(root, ".config", "lifer.yaml")
152
+ def brainwash!
153
+ FileUtils.rm_r output_directory
154
+ FileUtils.mkdir_p output_directory
155
+ end
156
+
157
+ def build_config_file_location(path)
158
+ return File.join(root, DEFAULT_CONFIG_FILE_URI) if path.nil?
159
+
160
+ path.start_with?("/") ? path : File.join(root, path)
161
+ end
162
+
163
+ # FIXME:
164
+ # Do collections work with sub-subdirectories? For example, what if the
165
+ # configured collection maps to a directory:
166
+ #
167
+ # subdirectory_one/sub_subdirectory_one
168
+ #
169
+ # @return [Set<Lifer::Collection>]
170
+ def generate_collections
171
+ config.collectionables
172
+ .map { |collection_name| [collection_name, "#{root}/#{collection_name}"] }
173
+ .to_h
174
+ .merge!({root: root})
175
+ .map { |collection_name, directory|
176
+ Lifer::Collection.generate name: collection_name, directory: directory
177
+ }
178
+ .to_set
179
+ end
180
+
181
+ # @private
182
+ # Requires user-provided selection classes (classes that subclass
183
+ # `Lifer::Selection` and implement an `#entries` method) so that users can
184
+ # bring their own pseudo-collections of entries.
185
+ #
186
+ # @return [Set<Lifer::Selection>]
187
+ def generate_selections
188
+ return [] if config.file.to_s.include? Lifer.gem_root
189
+
190
+ config.setting(:selections).map { |selection_name|
191
+ klass = Lifer::Utilities.classify selection_name
192
+ klass.generate
193
+ }.to_set
44
194
  end
45
195
  end