sitepress-rails 0.1.28 → 2.0.0.beta2

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 (33) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +8 -2
  3. data/app/controllers/concerns/sitepress/site_pages.rb +57 -17
  4. data/app/controllers/sitepress/site_controller.rb +1 -1
  5. data/config/routes.rb +5 -0
  6. data/lib/sitepress/build_paths/directory_index_path.rb +12 -0
  7. data/lib/sitepress/build_paths/index_path.rb +20 -0
  8. data/lib/sitepress/build_paths/root_path.rb +40 -0
  9. data/lib/sitepress/compiler.rb +68 -0
  10. data/lib/sitepress/engine.rb +40 -17
  11. data/lib/sitepress/rails.rb +12 -10
  12. data/lib/sitepress/rails_configuration.rb +8 -6
  13. data/lib/sitepress/renderers/controller.rb +51 -0
  14. data/lib/sitepress/renderers/server.rb +25 -0
  15. data/spec/dummy/config/application.rb +3 -1
  16. data/spec/dummy/config/environments/development.rb +1 -1
  17. data/spec/dummy/config/environments/production.rb +1 -1
  18. data/spec/dummy/log/test.log +2373 -78341
  19. data/spec/sitepress-rails_spec.rb +1 -30
  20. data/spec/sitepress/compiler_spec.rb +19 -0
  21. data/spec/sitepress/sitepress_site_controller_spec.rb +47 -6
  22. metadata +59 -42
  23. data/app/helpers/sitepress/application_helper.rb +0 -4
  24. data/lib/sitepress/extensions/index_request_path.rb +0 -24
  25. data/lib/sitepress/extensions/partials_remover.rb +0 -19
  26. data/lib/sitepress/extensions/rails_request_paths.rb +0 -20
  27. data/spec/dummy/app/models/application_record.rb +0 -3
  28. data/spec/dummy/db/production.sqlite3 +0 -0
  29. data/spec/dummy/db/test.sqlite3 +0 -0
  30. data/spec/dummy/log/production.log +0 -1360
  31. data/spec/sitepress/extensions/index_request_path_spec.rb +0 -15
  32. data/spec/sitepress/extensions/partials_remover_spec.rb +0 -12
  33. data/spec/sitepress/extensions/rails_request_paths_spec.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: eae4ad0f9f5c9a8b159c1234f159dc1aeddae525
4
- data.tar.gz: 02fbd0cb3d2287fb20483ac1e3fd7cc3e0c4555c
2
+ SHA256:
3
+ metadata.gz: c381546d35f924553bfea7fb8b6f13d0d903bb02b28149474ac24c77f6f48a8e
4
+ data.tar.gz: df348b473e9450ee82817b56593cc9e4195733f5fc434fc91a4e928a2c793c2e
5
5
  SHA512:
6
- metadata.gz: 41ae4d6e3b5c2cef6bf6bf3706fe7cebbf15c846ff1569161f19e0404dbde39260c62f396acedb4844890c0ec9fa879cb009f7d3f467665ac977a225483c7615
7
- data.tar.gz: 6c2b4a5c61b7b2aae1821d8496fa5ed20ca48e73c17384cf5f67269a9781b763393a84463da1aee56c78ecbad6aba20c39249f78c8c4a9ae9bb8e15bc007ce49
6
+ metadata.gz: cdad1a1fac1fa2545c5ad611893bee0b0711dac139822ee58a4faef224d27c2b7501a48a4f38865cd4bece4bbffc5ecbb1ee0a6aa702a5fc40049dd7e20a82c8
7
+ data.tar.gz: dac978e29a5abeab9733e926a613ea8c156c7ba5a79a78509ce37a9ec16112377e390172ba367a70123fb5fff87ae7b450ef725dcd80226243c400af2fd8dd32
data/README.md CHANGED
@@ -22,10 +22,16 @@ Then mount the engine into your `config/routes.rb` file:
22
22
  mount Sitepress::Engine => "/"
23
23
  ```
24
24
 
25
- Then add pages to the `app/views/pages` directory:
25
+ Create the `app/content/pages` in your rails project:
26
26
 
27
27
  ```bash
28
- $ echo "<h1>Hello</h1><p>It is <%= Time.now %> o'clock</p>" > app/views/pages/hello.html.erb
28
+ $ mkdir -p app/content/pages
29
+ ```
30
+
31
+ Then add pages to the `app/content/pages` directory:
32
+
33
+ ```bash
34
+ $ echo "<h1>Hello</h1><p>It is <%= Time.now %> o'clock</p>" > app/content/pages/hello.html.erb
29
35
  ```
30
36
 
31
37
  Point your browser to `http://127.0.0.1:3000/hello` and if all went well you should see the page you just created.
@@ -7,12 +7,16 @@ module Sitepress
7
7
  # to return the path to the layout.
8
8
  DEFAULT_PAGE_RAILS_FORMATS = [:html].freeze
9
9
 
10
+ # Default root path of resources.
11
+ ROOT_RESOURCE_PATH = "".freeze
12
+
10
13
  extend ActiveSupport::Concern
11
14
 
12
15
  included do
13
16
  rescue_from Sitepress::PageNotFoundError, with: :page_not_found
14
17
  helper Sitepress::Engine.helpers
15
18
  helper_method :current_page, :site
19
+ before_action :append_relative_partial_path, only: :show
16
20
  end
17
21
 
18
22
  def show
@@ -21,14 +25,15 @@ module Sitepress
21
25
 
22
26
  protected
23
27
  def render_page(page)
24
- render inline: page.body,
25
- type: page.asset.template_extensions.last,
26
- layout: page.data.fetch("layout", controller_layout),
27
- content_type: page.mime_type.to_s
28
+ if page.renderable?
29
+ render_text_resource page
30
+ else
31
+ send_binary_resource page
32
+ end
28
33
  end
29
34
 
30
35
  def current_page
31
- @_current_page ||= find_resource
36
+ @current_page ||= find_resource
32
37
  end
33
38
 
34
39
  def site
@@ -40,6 +45,24 @@ module Sitepress
40
45
  end
41
46
 
42
47
  private
48
+ def append_relative_partial_path
49
+ append_view_path current_page.asset.path.dirname
50
+ end
51
+
52
+ def render_text_resource(resource)
53
+ with_sitepress_render_cache do
54
+ render inline: resource.body,
55
+ type: resource.asset.template_extensions.last,
56
+ layout: resource.data.fetch("layout", controller_layout),
57
+ content_type: resource.mime_type.to_s
58
+ end
59
+ end
60
+
61
+ def send_binary_resource(resource)
62
+ send_file resource.asset.path,
63
+ disposition: :inline,
64
+ type: resource.mime_type.to_s
65
+ end
43
66
 
44
67
  # Sitepress::PageNotFoundError is handled in the default Sitepress::SiteController
45
68
  # with an execption that Rails can use to display a 404 error.
@@ -53,30 +76,47 @@ module Sitepress
53
76
  end
54
77
  end
55
78
 
56
- # Default finder of the resource for the current controller context.###
79
+ # Default finder of the resource for the current controller context. If the :resource_path
80
+ # isn't present, then its probably the root path so grab that.
57
81
  def find_resource
58
- get params[:resource_path]
82
+ get params.fetch(:resource_path, ROOT_RESOURCE_PATH)
83
+ end
84
+
85
+ # When development environments disable the cache, we still want to turn it
86
+ # on during rendering so that view doesn't rebuild the site on each call.
87
+ def with_sitepress_render_cache(&block)
88
+ cache_resources = site.cache_resources
89
+ begin
90
+ site.cache_resources = true
91
+ yield
92
+ ensure
93
+ site.cache_resources = cache_resources
94
+ site.clear_resources_cache unless site.cache_resources
95
+ end
59
96
  end
60
97
 
61
98
  # Returns the current layout for the inline Sitepress renderer. This is
62
99
  # exposed via some really convoluted private methods inside of the various
63
100
  # versions of Rails, so I try my best to hack out the path to the layout below.
64
101
  def controller_layout
65
- # Rails 4 and 5 expose the `_layout` via methods with different arity. Since
66
- # I don't want to hard code the version, I'm detecting arity and hoping that Rails 6
67
- # doesn't break this approach. If it does I'll probably have to get into the business
68
- # of version detection.
69
102
  private_layout_method = self.method(:_layout)
70
- layout = if private_layout_method.arity == 1 # Rails 5
71
- private_layout_method.call current_page_rails_formats
72
- else # Rails 4
73
- private_layout_method.call
74
- end
103
+ layout =
104
+ if Rails.version >= "6"
105
+ private_layout_method.call lookup_context, current_page_rails_formats
106
+ elsif Rails.version >= "5"
107
+ private_layout_method.call current_page_rails_formats
108
+ else
109
+ private_layout_method.call
110
+ end
75
111
 
76
112
  if layout.instance_of? String # Rails 4 and 5 return a string from above.
77
113
  layout
78
- else # Rails 3 and older return an object that gives us a file name
114
+ elsif layout # Rails 3 and older return an object that gives us a file name
79
115
  File.basename(layout.identifier).split('.').first
116
+ else
117
+ # If none of the conditions are met, then no layout was
118
+ # specified, so nil is returned.
119
+ nil
80
120
  end
81
121
  end
82
122
 
@@ -1,5 +1,5 @@
1
1
  module Sitepress
2
- class SiteController < ::ApplicationController
2
+ class SiteController < ActionController::Base
3
3
  # Extracted into a module because other controllers may need
4
4
  # to be capable of serving Sitepress pages.
5
5
  include Sitepress::SitePages
data/config/routes.rb CHANGED
@@ -2,6 +2,11 @@ Sitepress.configuration.parent_engine.routes.draw do
2
2
  if Sitepress.configuration.routes
3
3
  constraints Sitepress::RouteConstraint.new do
4
4
  get "*resource_path", controller: "sitepress/site", action: "show", as: :page, format: false
5
+ if has_named_route? :root
6
+ Rails.logger.warn 'Sitepress tried to configure `root to: "sitepress/site#show"`, but a root route was already defined.'
7
+ else
8
+ root to: "sitepress/site#show"
9
+ end
5
10
  end
6
11
  end
7
12
  end
@@ -0,0 +1,12 @@
1
+ module Sitepress
2
+ module BuildPaths
3
+ # In many cases, you'll want to serve up `pages/blah.html.haml` as `/blah` on
4
+ # hosts like S3. To achieve this effect, we have to compile `pages/blah.html.haml`
5
+ # to a folder with the filename `index.html`, so the final path would be `/blah/index.html`
6
+ class DirectoryIndexPath < IndexPath
7
+ def path_with_default_format
8
+ File.join(node.name, "#{node.default_name}.#{format}")
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ module Sitepress
2
+ module BuildPaths
3
+ # Compiles pages directly from `/pages/blah.html.haml` to `/blah.html`. Handles root `index`
4
+ # pages too, mainly grabbing the root, which doesn't have a name in the node, to the default_name
5
+ # of the node, which is usually `index`.
6
+ class IndexPath < RootPath
7
+ def path_without_format
8
+ node.name
9
+ end
10
+
11
+ def path_with_format
12
+ "#{node.name}.#{format}"
13
+ end
14
+
15
+ def path_with_default_format
16
+ path_with_format
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,40 @@
1
+ module Sitepress
2
+ module BuildPaths
3
+ # Compiles pages directly from `/pages/blah.html.haml` to `/blah.html`. Handles root `index`
4
+ # pages too, mainly grabbing the root, which doesn't have a name in the node, to the default_name
5
+ # of the node, which is usually `index`.
6
+ class RootPath
7
+ attr_reader :resource
8
+
9
+ extend Forwardable
10
+ def_delegators :resource, :node, :format
11
+
12
+ def initialize(resource)
13
+ @resource = resource
14
+ end
15
+
16
+ def path
17
+ if format.nil?
18
+ path_without_format
19
+ elsif format == node.default_format
20
+ path_with_default_format
21
+ elsif format
22
+ path_with_format
23
+ end
24
+ end
25
+
26
+ protected
27
+ def path_without_format
28
+ node.default_name
29
+ end
30
+
31
+ def path_with_format
32
+ "#{node.default_name}.#{format}"
33
+ end
34
+
35
+ def path_with_default_format
36
+ path_with_format
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,68 @@
1
+ require "pathname"
2
+ require "fileutils"
3
+
4
+ module Sitepress
5
+ # Compile all resources from a Sitepress site into static pages.
6
+ class Compiler
7
+ include FileUtils
8
+
9
+ class ResourceCompiler
10
+ attr_reader :resource
11
+
12
+ def initialize(resource)
13
+ @resource = resource
14
+ end
15
+
16
+ def compilation_path
17
+ File.join(*resource.lineage, compilation_filename)
18
+ end
19
+
20
+ # Compiled assets have a slightly different filename for assets, especially the root node.
21
+ def compilation_filename(path_builder: BuildPaths::DirectoryIndexPath, root_path_builder: BuildPaths::RootPath)
22
+ path_builder = resource.node.root? ? root_path_builder : path_builder
23
+ path_builder.new(resource).path
24
+ end
25
+
26
+ def render(page)
27
+ Renderers::Server.new(resource).render
28
+ end
29
+ end
30
+
31
+ attr_reader :site
32
+
33
+ def initialize(site:, stdout: $stdout)
34
+ @site = site
35
+ @stdout = stdout
36
+ end
37
+
38
+ # Iterates through all pages and writes them to disk
39
+ def compile(target_path:)
40
+ target_path = Pathname.new(target_path)
41
+ mkdir_p target_path
42
+ cache_resources = @site.cache_resources
43
+ @stdout.puts "Compiling #{@site.root_path.expand_path}"
44
+
45
+ begin
46
+ @site.cache_resources = true
47
+ @site.resources.each do |resource|
48
+ compiler = ResourceCompiler.new(resource)
49
+ path = target_path.join(compiler.compilation_path)
50
+ mkdir_p path.dirname
51
+ if resource.renderable?
52
+ @stdout.puts " Rendering #{path}"
53
+ File.open(path.expand_path, "w"){ |f| f.write compiler.render(resource) }
54
+ else
55
+ @stdout.puts " Copying #{path}"
56
+ FileUtils.cp resource.asset.path, path.expand_path
57
+ end
58
+ rescue => e
59
+ @stdout.puts "Error compiling #{resource.inspect}"
60
+ raise
61
+ end
62
+ @stdout.puts "Successful compilation to #{target_path.expand_path}"
63
+ ensure
64
+ @site.cache_resources = cache_resources
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,28 +1,51 @@
1
+ require "rails/engine"
2
+
1
3
  module Sitepress
2
4
  class Engine < ::Rails::Engine
3
- config.before_configuration do |app|
4
- Sitepress.configure do |config|
5
- app.paths["app/helpers"].push config.site.root_path.join("helpers")
6
- app.paths["app/assets"].push config.site.root_path.join("assets")
7
- app.paths["app/views"].push config.site.root_path
8
- end
5
+ # Set the path for the site configuration file.
6
+ paths.add "config/site.rb", with: [
7
+ File.expand_path("./config/site.rb"), # When Sitepress is launched via `sitepress server`.
8
+ "config/site.rb" # When Sitepress is launched embedded in Rails project.
9
+ ]
9
10
 
10
- # Setup concerns paths for Rails 4 (doesn't automatically populate)
11
- concerns_path = "app/controllers/concerns"
12
- unless app.paths.keys.include?(concerns_path)
13
- app.paths.add(concerns_path)
14
- end
11
+ # Load the `config/site.rb` file so users can configure Sitepress.
12
+ initializer :load_sitepress_file, before: :set_sitepress_paths do
13
+ site_file = paths["config/site.rb"].existent.first
14
+ load site_file if site_file
15
+ end
16
+
17
+ # Load paths from `Sitepress#site` into rails so it can render views, helpers, etc. properly.
18
+ initializer :set_sitepress_paths, before: :set_autoload_paths do |app|
19
+ app.paths["app/helpers"].push site.helpers_path.expand_path
20
+ app.paths["app/views"].push site.root_path.expand_path
21
+ app.paths["app/views"].push site.pages_path.expand_path
15
22
  end
16
23
 
17
- initializer "sitepress.configure" do |app|
18
- Sitepress.configure do |config|
19
- config.parent_engine = app
20
- config.cache_resources = app.config.cache_classes
24
+ # Configure sprockets paths for the site.
25
+ initializer :set_asset_paths, before: :append_assets_path do |app|
26
+ manifest_file = sitepress_configuration.manifest_file_path.expand_path
27
+
28
+ if manifest_file.exist?
29
+ app.paths["app/assets"].push site.assets_path.expand_path
30
+ app.config.assets.precompile << manifest_file.to_s
31
+ else
32
+ Rails.logger.warn "WARNING: Sitepress could not enable Sprockets because it could not find a manifest file at #{manifest_file.to_s.inspect}."
21
33
  end
22
34
  end
23
35
 
24
- initializer "sitepress.middleware" do |app|
25
- app.middleware.use Sitepress::Middleware::RequestCache, site: Sitepress.site
36
+ # Configure Sitepress with Rails settings.
37
+ initializer :configure_sitepress do |app|
38
+ sitepress_configuration.parent_engine = app
39
+ sitepress_configuration.cache_resources = app.config.cache_classes
40
+ end
41
+
42
+ private
43
+ def sitepress_configuration
44
+ Sitepress.configuration
45
+ end
46
+
47
+ def site
48
+ sitepress_configuration.site
26
49
  end
27
50
  end
28
51
  end
@@ -1,19 +1,21 @@
1
1
  require "sitepress-core"
2
2
 
3
3
  module Sitepress
4
- # Contains singletons for rails and some configuration data.
5
- Configuration = Struct.new(:site, :routes, :parent_engine)
6
-
7
- # Rescued by ActionController to display page not found error.
8
- PageNotFoundError = Class.new(StandardError)
9
-
4
+ autoload :Compiler, "sitepress/compiler"
10
5
  autoload :RailsConfiguration, "sitepress/rails_configuration"
11
6
  autoload :RouteConstraint, "sitepress/route_constraint"
12
- module Extensions
13
- autoload :RailsRequestPaths, "sitepress/extensions/rails_request_paths"
14
- autoload :PartialsRemover, "sitepress/extensions/partials_remover"
15
- autoload :IndexRequestPath, "sitepress/extensions/index_request_path"
7
+ module Renderers
8
+ autoload :Controller, "sitepress/renderers/controller"
9
+ autoload :Server, "sitepress/renderers/server"
16
10
  end
11
+ module BuildPaths
12
+ autoload :RootPath, "sitepress/build_paths/root_path"
13
+ autoload :IndexPath, "sitepress/build_paths/index_path"
14
+ autoload :DirectoryIndexPath, "sitepress/build_paths/directory_index_path"
15
+ end
16
+
17
+ # Rescued by ActionController to display page not found error.
18
+ PageNotFoundError = Class.new(StandardError)
17
19
 
18
20
  # Make site available via Sitepress.site from Rails app.
19
21
  def self.site
@@ -6,13 +6,13 @@ module Sitepress
6
6
  # Store in ./app/content by default.
7
7
  DEFAULT_SITE_ROOT = "app/content".freeze
8
8
 
9
- attr_accessor :site, :parent_engine, :routes, :cache_resources
9
+ attr_accessor :routes
10
+ attr_writer :site, :parent_engine
10
11
 
11
12
  # Delegates configuration points into the Sitepress site.
12
13
  extend Forwardable
13
14
  def_delegators :site, :cache_resources, :cache_resources=, :cache_resources?
14
15
 
15
- # Set defaults.
16
16
  def initialize
17
17
  self.routes = true
18
18
  end
@@ -22,10 +22,12 @@ module Sitepress
22
22
  end
23
23
 
24
24
  def site
25
- @site ||= Site.new(root_path: default_root).tap do |site|
26
- site.resources_pipeline << Extensions::PartialsRemover.new
27
- site.resources_pipeline << Extensions::RailsRequestPaths.new
28
- end
25
+ @site ||= Site.new(root_path: default_root)
26
+ end
27
+
28
+ # Location of Sprockets manifest file
29
+ def manifest_file_path
30
+ site.assets_path.join("config/manifest.js")
29
31
  end
30
32
 
31
33
  private