parklife 0.7.0 → 0.8.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: 716fff5f3d7ad38f43c2fd071de3a69dc58363b05fb7fd3d997311855a207f04
4
- data.tar.gz: b153dc13fb74648185401f3a512c34eee2f0ad62659723937c0354d9c7547ecd
3
+ metadata.gz: c83a66e0d3fcb43a7687e99ed43267ac8998df9c6cb36cc066bdbce3128538ff
4
+ data.tar.gz: 0f2e982d4fc88b1389c26ae5335c5922744f3a86f100a3e0fe40a8883dcd06e7
5
5
  SHA512:
6
- metadata.gz: 7a1a022c68a6a7c77277440c926cd430ebf857a7757f42eab76b8233af84bdc4dd9407952a9465720a6a74e43d7706b8acb41a25705ebb3d0e34c9a75a11b441
7
- data.tar.gz: 80af344c3209f6a57f147714c789d6c3d21a42cd3131186e9dbebb0e267d19258cdb297f13f273baefdb4bbd4bcba955c2c1e726ee9e218d8febaf50ec4c26c8
6
+ metadata.gz: b7537ae0c2cf63a37d3710f2a70db51302c21f8ce117521f695165e4dd2874bff65d9522baacbe7b6f49397594aa4f889f2dab6a9b36415bffcee490f84dab1b
7
+ data.tar.gz: 71c26e2e286af0d8653b1e2166b2d00abbb52f16d4d3d582c3c7f799b9d5e92676d955877dd885df30f2e661063a53bf81dcddf0ef12d374daac78e2aa070b0b
@@ -0,0 +1,3 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: benpickles
@@ -18,21 +18,6 @@ jobs:
18
18
  - run: test -f build/index.html
19
19
  working-directory: examples/rack
20
20
 
21
- rails:
22
- runs-on: ubuntu-latest
23
- name: Rails example
24
- steps:
25
- - uses: actions/checkout@v3
26
- - uses: ruby/setup-ruby@v1
27
- with:
28
- bundler-cache: true
29
- ruby-version: '3.2'
30
- working-directory: examples/rails
31
- - run: bin/static-build
32
- working-directory: examples/rails
33
- - run: test -f build/index.html
34
- working-directory: examples/rails
35
-
36
21
  roda:
37
22
  runs-on: ubuntu-latest
38
23
  name: Roda example
@@ -3,52 +3,6 @@ name: Tests
3
3
  on: push
4
4
 
5
5
  jobs:
6
- rails:
7
- runs-on: ubuntu-latest
8
- strategy:
9
- fail-fast: false
10
- matrix:
11
- rails:
12
- - '7.0'
13
- - '7.1'
14
- - '7.2'
15
- - '8.0'
16
- ruby:
17
- - '2.7'
18
- - '3.0'
19
- - '3.1'
20
- - '3.2'
21
- - '3.3'
22
- - '3.4'
23
- exclude:
24
- # Rails 8.0 requires Ruby 3.2.
25
- - rails: '8.0'
26
- ruby: '3.1'
27
- - rails: '8.0'
28
- ruby: '3.0'
29
- - rails: '8.0'
30
- ruby: '2.7'
31
-
32
- # Rails 7.2 requires Ruby 3.1.
33
- - rails: '7.2'
34
- ruby: '3.0'
35
- - rails: '7.2'
36
- ruby: '2.7'
37
-
38
- # Rails 7.0 doesn't work out of the box with Ruby 3.4.
39
- - rails: '7.0'
40
- ruby: '3.4'
41
- env:
42
- BUNDLE_GEMFILE: gemfiles/rails_${{ matrix.rails }}.gemfile
43
- name: Rails (Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }})
44
- steps:
45
- - uses: actions/checkout@v4
46
- - uses: ruby/setup-ruby@v1
47
- with:
48
- bundler-cache: true
49
- ruby-version: ${{ matrix.ruby }}
50
- - run: bundle exec rspec --pattern "spec/**/*rails*"
51
-
52
6
  rspec:
53
7
  runs-on: ubuntu-latest
54
8
  strategy:
@@ -68,7 +22,7 @@ jobs:
68
22
  with:
69
23
  bundler-cache: true
70
24
  ruby-version: ${{ matrix.ruby }}
71
- - run: bundle exec rspec --exclude-pattern "spec/**/*rails*,spec/**/*sinatra*"
25
+ - run: bundle exec rspec --exclude-pattern "spec/**/*sinatra*"
72
26
 
73
27
  rubocop:
74
28
  runs-on: ubuntu-latest
@@ -99,7 +53,7 @@ jobs:
99
53
  - '4.1'
100
54
  env:
101
55
  BUNDLE_GEMFILE: gemfiles/sinatra_${{ matrix.sinatra }}.gemfile
102
- name: Rails (Ruby ${{ matrix.ruby }} / Sinatra ${{ matrix.sinatra }})
56
+ name: Ruby ${{ matrix.ruby }} / Sinatra ${{ matrix.sinatra }}
103
57
  steps:
104
58
  - uses: actions/checkout@v4
105
59
  - uses: ruby/setup-ruby@v1
data/Appraisals CHANGED
@@ -1,22 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- appraise 'rails_7.0' do
4
- gem 'concurrent-ruby', '< 1.3.5'
5
- gem 'rails', '~> 7.0.0'
6
- end
7
-
8
- appraise 'rails_7.1' do
9
- gem 'rails', '~> 7.1.0'
10
- end
11
-
12
- appraise 'rails_7.2' do
13
- gem 'rails', '~> 7.2.0'
14
- end
15
-
16
- appraise 'rails_8.0' do
17
- gem 'rails', '~> 8.0.0'
18
- end
19
-
20
3
  appraise 'sinatra_3.x' do
21
4
  gem 'sinatra', '~> 3.0'
22
5
  end
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## Unreleased
2
+
3
+ ## Version 0.8.0 - 2025-09-08
4
+
5
+ Note that **Parklife's Rails integration has been moved into a separate gem** with some additional functionality, [see the `parklife-rails` repo for more information](https://github.com/benpickles/parklife-rails).
6
+
7
+ ## Version 0.8.0.beta1 - 2025-08-10
8
+
9
+ - Remove out-of-the-box Rails integration in preparation for a separate gem. <https://github.com/benpickles/parklife/pull/131>
10
+ - Include the port when automatically assigning the base from Rails `default_url_options`. <https://github.com/benpickles/parklife/pull/130>
11
+ - Improve the HTTP redirect error message to include the request's full URL and redirect location. <https://github.com/benpickles/parklife/pull/129>
12
+ - Empty the build directory instead of deleting it. <https://github.com/benpickles/parklife/pull/125>
13
+ - Resurrect build callbacks (`before_build`/`after_build`). <https://github.com/benpickles/parklife/pull/124>
14
+
1
15
  ## Version 0.7.0 - 2025-02-03
2
16
 
3
17
  - Add support for Rails 8 and add test infrastructure to ensure future compatibility with Rails 7.0, 7.1, and 8.0. <https://github.com/benpickles/parklife/pull/115>, <https://github.com/benpickles/parklife/pull/117>, <https://github.com/benpickles/parklife/pull/121>
data/README.md CHANGED
@@ -12,38 +12,36 @@ Add Parklife to your application's Gemfile and run bundle install.
12
12
  gem 'parklife'
13
13
  ```
14
14
 
15
- Now generate a Parkfile configuration file and build script. Include some Rails- or Sinatra-specific settings by passing `--rails` or `--sinatra`, create a GitHub Actions workflow to generate your Parklife build and push it to GitHub Pages by passing `--github-pages`.
15
+ Now generate a Parkfile configuration file and build script. Include some Rails- or Sinatra-specific settings by passing `--rails` or `--sinatra`, create a GitHub Actions workflow to generate your Parklife build and deploy it to GitHub Pages by passing `--github-pages`.
16
16
 
17
17
  ```
18
18
  $ bundle exec parklife init
19
19
  ```
20
20
 
21
- ## How to use Parklife with Rails
21
+ ## How to use Parklife
22
+
23
+ > [!NOTE]
24
+ > See the [`parklife-rails` repository](https://github.com/benpickles/parklife-rails) for how to use Parklife with Rails.
22
25
 
23
26
  Parklife is configured with a file called `Parkfile` in the root of your project, here's an example `Parkfile` for an imaginary Rails app:
24
27
 
25
28
  ```ruby
26
- # Load Parklife's Rails-specific integration which, among other things, allows
27
- # you to use URL helpers within the `routes` block below.
28
- require 'parklife/rails'
29
-
30
- # Load the Rails application, this gives you full access to the application's
31
- # environment from this file - using models for example.
32
- require_relative 'config/environment'
29
+ # Assuming your Rack app lives in ./app.rb:
30
+ require_relative 'app'
33
31
 
34
32
  Parkfile.application.routes do
35
33
  # Start from the homepage and crawl all links.
36
34
  root crawl: true
37
35
 
38
36
  # Some extra paths that aren't discovered while crawling.
39
- get feed_path(format: :atom)
40
- get sitemap_path(format: :xml)
37
+ get '/feed.atom'
38
+ get '/sitemap.xml'
41
39
 
42
40
  # A couple more hidden pages.
43
- get easter_egg_path, crawl: true
41
+ get '/easter_egg', crawl: true
44
42
 
45
43
  # Services typically allow a custom 404 page.
46
- get '404.html'
44
+ get '/404.html'
47
45
  end
48
46
  ```
49
47
 
@@ -76,11 +74,11 @@ build/feed.atom
76
74
  build/sitemap.xml
77
75
  ```
78
76
 
79
- Parklife doesn't know about assets (images, CSS, etc) so you likely also need to generate those and copy them to the build directory, see the [Rails example's full build script](examples/rails/bin/static-build) for how you might do this.
77
+ Parklife doesn't know about assets (images, CSS, etc) so you likely also need to generate those and copy them to the build directory.
80
78
 
81
79
  ## More examples
82
80
 
83
- Take a look at the [Rails](examples/rails/Parkfile), [Rack](examples/rack/Parkfile) and [Sinatra](examples/sinatra/Parkfile) working examples within this repository.
81
+ Take a look at the [`parklife-rails` example app](https://github.com/benpickles/parklife-rails/tree/main/example-app), and the [Rack](examples/rack/Parkfile) and [Sinatra](examples/sinatra/Parkfile) working examples within this repository.
84
82
 
85
83
  ## Configuration
86
84
 
@@ -110,7 +108,7 @@ Parklife.application.config.nested_index = false
110
108
 
111
109
  ### Changing the build output directory
112
110
 
113
- The build directory shouldn't exist and is destroyed and recreated before each build. Defaults to `build`.
111
+ The build directory's contents are removed before each build. Defaults to `build`.
114
112
 
115
113
  ```ruby
116
114
  Parklife.application.config.build_dir = 'my/build/dir'
@@ -13,16 +13,37 @@ module Parklife
13
13
  def initialize
14
14
  @config = Config.new
15
15
  @route_set = RouteSet.new
16
+ @after_build_callbacks = []
17
+ @before_build_callbacks = []
18
+ end
19
+
20
+ def after_build(&block)
21
+ @after_build_callbacks << block
22
+ end
23
+
24
+ def before_build(&block)
25
+ @before_build_callbacks << block
16
26
  end
17
27
 
18
28
  def build
19
29
  raise BuildDirNotDefinedError if config.build_dir.nil?
20
30
  raise RackAppNotDefinedError if config.app.nil?
21
31
 
22
- FileUtils.rm_rf(config.build_dir)
23
- Dir.mkdir(config.build_dir)
32
+ if Dir.exist?(config.build_dir)
33
+ FileUtils.rm_rf(Pathname.new(config.build_dir).children)
34
+ else
35
+ Dir.mkdir(config.build_dir)
36
+ end
37
+
38
+ @before_build_callbacks.each do |callback|
39
+ callback.call(self)
40
+ end
24
41
 
25
42
  crawler.start
43
+
44
+ @after_build_callbacks.each do |callback|
45
+ callback.call(self)
46
+ end
26
47
  end
27
48
 
28
49
  def configure
@@ -18,6 +18,10 @@ module Parklife
18
18
  session.get(path, nil, env)
19
19
  end
20
20
 
21
+ def uri_for(path)
22
+ base.dup.tap { |uri| uri.path = path }
23
+ end
24
+
21
25
  private
22
26
  def set_env
23
27
  @env = {
data/lib/parklife/cli.rb CHANGED
@@ -25,7 +25,7 @@ module Parklife
25
25
  ['build_dir', application.config.build_dir],
26
26
  ['nested_index', application.config.nested_index],
27
27
  ['on_404', application.config.on_404.inspect],
28
- ['parklife/rails', defined?(::Parklife::Railtie) ? 'enabled' : '-'],
28
+ ['parklife-rails', defined?(::Parklife::Rails) ? 'enabled' : '-'],
29
29
  ['parklife/sinatra', defined?(::Parklife::Sinatra) ? 'enabled' : '-'],
30
30
  ['reporter', reporter == $stdout ? '$stdout' : reporter],
31
31
  ])
@@ -51,6 +51,12 @@ module Parklife
51
51
  case response.status
52
52
  when 200
53
53
  # Continue processing the route.
54
+ when 301, 302
55
+ raise HTTPRedirectError.new(
56
+ response.status,
57
+ browser.uri_for(route.path),
58
+ response.headers['location']
59
+ )
54
60
  when 404
55
61
  case config.on_404
56
62
  when :warn
@@ -11,6 +11,12 @@ module Parklife
11
11
  end
12
12
  end
13
13
 
14
+ class HTTPRedirectError < Error
15
+ def initialize(status, from, to)
16
+ super %Q(#{status} redirect from "#{from}" to "#{to}")
17
+ end
18
+ end
19
+
14
20
  class ParkfileLoadError < Error
15
21
  def initialize(path)
16
22
  super %Q(Cannot load Parkfile "#{path}")
@@ -1,5 +1,6 @@
1
1
  <% if options[:rails] -%>
2
- require 'parklife/rails'
2
+ # Load your application, this activates the Parklife/Rails integration and gives
3
+ # you access to route helpers and models in this file.
3
4
  require_relative 'config/environment'
4
5
  <% else -%>
5
6
  <% if options[:sinatra] -%>
@@ -3,9 +3,15 @@
3
3
  set -eu
4
4
 
5
5
  <% if options[:rails] -%>
6
- # Run the app in production mode to ensure correct asset URLs are generated etc.
6
+ # Run the app in production mode to ensure correct asset URLs are generated.
7
7
  export RAILS_ENV=production
8
+
9
+ # Prevent most logs from outputting to stdout during a build.
10
+ export RAILS_LOG_LEVEL=warn
11
+
12
+ # Enable precompiling assets.
8
13
  export SECRET_KEY_BASE=dummy
14
+ export SECRET_KEY_BASE_DUMMY=1
9
15
 
10
16
  # If your Rails app uses ActiveRecord then this is a good point to create and
11
17
  # seed the database from db/seeds.rb.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parklife
4
- VERSION = '0.7.0'
4
+ VERSION = '0.8.0'
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parklife
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Pickles
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-02-03 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: nokogiri
@@ -58,6 +58,7 @@ executables:
58
58
  extensions: []
59
59
  extra_rdoc_files: []
60
60
  files:
61
+ - ".github/FUNDING.yml"
61
62
  - ".github/workflows/examples.yml"
62
63
  - ".github/workflows/tests.yml"
63
64
  - ".gitignore"
@@ -73,10 +74,6 @@ files:
73
74
  - bin/console
74
75
  - bin/setup
75
76
  - exe/parklife
76
- - gemfiles/rails_7.0.gemfile
77
- - gemfiles/rails_7.1.gemfile
78
- - gemfiles/rails_7.2.gemfile
79
- - gemfiles/rails_8.0.gemfile
80
77
  - gemfiles/sinatra_3.x.gemfile
81
78
  - gemfiles/sinatra_4.0.gemfile
82
79
  - gemfiles/sinatra_4.1.gemfile
@@ -87,7 +84,6 @@ files:
87
84
  - lib/parklife/config.rb
88
85
  - lib/parklife/crawler.rb
89
86
  - lib/parklife/errors.rb
90
- - lib/parklife/rails.rb
91
87
  - lib/parklife/route.rb
92
88
  - lib/parklife/route_set.rb
93
89
  - lib/parklife/sinatra.rb
@@ -119,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
115
  - !ruby/object:Gem::Version
120
116
  version: '0'
121
117
  requirements: []
122
- rubygems_version: 3.6.2
118
+ rubygems_version: 3.7.1
123
119
  specification_version: 4
124
120
  summary: Convert a Rack app into a static HTML site.
125
121
  test_files: []
@@ -1,13 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal"
6
- gem "bundler"
7
- gem "rake"
8
- gem "rspec"
9
- gem "rubocop"
10
- gem "concurrent-ruby", "< 1.3.5"
11
- gem "rails", "~> 7.0.0"
12
-
13
- gemspec path: "../"
@@ -1,12 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal"
6
- gem "bundler"
7
- gem "rake"
8
- gem "rspec"
9
- gem "rubocop"
10
- gem "rails", "~> 7.1.0"
11
-
12
- gemspec path: "../"
@@ -1,12 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal"
6
- gem "bundler"
7
- gem "rake"
8
- gem "rspec"
9
- gem "rubocop"
10
- gem "rails", "~> 7.2.0"
11
-
12
- gemspec path: "../"
@@ -1,12 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "appraisal"
6
- gem "bundler"
7
- gem "rake"
8
- gem "rspec"
9
- gem "rubocop"
10
- gem "rails", "~> 8.0.0"
11
-
12
- gemspec path: "../"
@@ -1,69 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rails'
4
-
5
- module Parklife
6
- module RailsConfigRefinements
7
- # When setting Parklife's base also configure the Rails app's
8
- # default_url_options and relative_url_root to match.
9
- def base=(value)
10
- super.tap { |uri|
11
- app.default_url_options = {
12
- host: Utils.host_with_port(uri),
13
- protocol: uri.scheme,
14
- }
15
-
16
- base_path = !uri.path.empty? && uri.path != '/' ? uri.path : nil
17
- ActionController::Base.relative_url_root = base_path
18
- }
19
- end
20
- end
21
-
22
- module RailsRouteSetRefinements
23
- def default_url_options
24
- Rails.application.default_url_options
25
- end
26
- end
27
-
28
- class Railtie < Rails::Railtie
29
- initializer 'parklife.disable_host_authorization' do |app|
30
- # The offending middleware is included in Rails (6+) development mode and
31
- # rejects a request with a 403 response if its host isn't present in the
32
- # allowlist (a security feature). This prevents Parklife from working in
33
- # a Rails app out of the box unless you manually add the expected
34
- # Parklife base to the hosts allowlist or set it to nil to disable it -
35
- # both of which aren't great because they disable the security feature
36
- # whenever the development server is booted.
37
- #
38
- # https://guides.rubyonrails.org/configuring.html#actiondispatch-hostauthorization
39
- #
40
- # However it's safe to remove the middleware at this point because it
41
- # won't be executed in the normal Rails development flow, only via a
42
- # Parkfile when parklife/rails is required.
43
- if defined?(ActionDispatch::HostAuthorization)
44
- app.middleware.delete(ActionDispatch::HostAuthorization)
45
- end
46
-
47
- Parklife.application.config.app = app
48
-
49
- # Allow use of the Rails application's route helpers when defining
50
- # Parklife routes in the block form.
51
- Parklife.application.routes.singleton_class.include(RailsRouteSetRefinements)
52
- Parklife.application.routes.singleton_class.include(app.routes.url_helpers)
53
-
54
- Parklife.application.config.extend(RailsConfigRefinements)
55
- end
56
-
57
- config.after_initialize do |app|
58
- # Read the Rails app's URL config and apply it to Parklife's so that the
59
- # Rails config can be used as the single source of truth.
60
- host, protocol = app.default_url_options.values_at(:host, :protocol)
61
- protocol = 'https' if app.config.force_ssl
62
- path = ActionController::Base.relative_url_root
63
-
64
- Parklife.application.config.base.scheme = protocol if protocol
65
- Parklife.application.config.base.host = host if host
66
- Parklife.application.config.base.path = path if path
67
- end
68
- end
69
- end