sitepress-rails 0.1.27 → 2.0.0.beta1

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 +82 -11
  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 +2692 -57880
  19. data/spec/sitepress-rails_spec.rb +11 -33
  20. data/spec/sitepress/compiler_spec.rb +19 -0
  21. data/spec/sitepress/sitepress_site_controller_spec.rb +59 -9
  22. metadata +61 -44
  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 -392
  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: 027cfbb8b2287f8ed5c2da1368cfc75821b3d9c2
4
- data.tar.gz: c0ee867a1293ff9ffed5aaa150df8d491bbc4f4c
2
+ SHA256:
3
+ metadata.gz: ef7991baba77ba1d9f5686ec4f8570e60b9ecfbd4d56c9daf0af7a4eef835cfa
4
+ data.tar.gz: 20c870b3d71fb594dbc8c904a74a084d8b67c90b4f5c2f7f7b02c71be69b1ce1
5
5
  SHA512:
6
- metadata.gz: b5f4109ea391c4f76fc5b71b892a973964e56f9bf9e25f4738c69fb8bdb99fd027e5576df7051be35e77fad1a43c5de815eebfcb2c6864306b4fab9c900072ec
7
- data.tar.gz: e990a3321275c5d4e2edf96bdac2f2f92049f5449cb2e397b0b5c623851d89669fcefb736c8ce53d41c5d37c2709a7cf7f4064fa6125327f1bde4babea767b8e
6
+ metadata.gz: d4b6f85510e7fe4078679203d2f86ac04ac22428463714ce236f06220513443fa64998598c35ac5fdbd6494ff7547743dd4b0539d48d04824e8c775a638d07dc
7
+ data.tar.gz: 16174ec324144ffa5b3b3ea8bc67a93c724713af7a4269a48859653d2cab09db366dd597d0fce3c5fd4418b1948687a79d61e89077b0d04475f1d25d2c0a42d9
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.
@@ -3,12 +3,20 @@ module Sitepress
3
3
  # Sitepress::SiteController, but may be included into other controllers for static
4
4
  # page behavior.
5
5
  module SitePages
6
+ # Rails 5 requires a format to be given to the private layout method
7
+ # to return the path to the layout.
8
+ DEFAULT_PAGE_RAILS_FORMATS = [:html].freeze
9
+
10
+ # Default root path of resources.
11
+ ROOT_RESOURCE_PATH = "".freeze
12
+
6
13
  extend ActiveSupport::Concern
7
14
 
8
15
  included do
9
16
  rescue_from Sitepress::PageNotFoundError, with: :page_not_found
10
17
  helper Sitepress::Engine.helpers
11
18
  helper_method :current_page, :site
19
+ before_action :append_relative_partial_path, only: :show
12
20
  end
13
21
 
14
22
  def show
@@ -17,14 +25,15 @@ module Sitepress
17
25
 
18
26
  protected
19
27
  def render_page(page)
20
- render inline: page.body,
21
- type: page.asset.template_extensions.last,
22
- layout: page.data.fetch("layout", controller_layout),
23
- 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
24
33
  end
25
34
 
26
35
  def current_page
27
- @_current_page ||= find_resource
36
+ @current_page ||= find_resource
28
37
  end
29
38
 
30
39
  def site
@@ -36,6 +45,24 @@ module Sitepress
36
45
  end
37
46
 
38
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
39
66
 
40
67
  # Sitepress::PageNotFoundError is handled in the default Sitepress::SiteController
41
68
  # with an execption that Rails can use to display a 404 error.
@@ -49,18 +76,62 @@ module Sitepress
49
76
  end
50
77
  end
51
78
 
52
- # 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.
53
81
  def find_resource
54
- get params[:resource_path]
82
+ get params.fetch(:resource_path, ROOT_RESOURCE_PATH)
55
83
  end
56
84
 
57
- # Returns the current layout for the inline Sitepress renderer.
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
96
+ end
97
+
98
+ # Returns the current layout for the inline Sitepress renderer. This is
99
+ # exposed via some really convoluted private methods inside of the various
100
+ # versions of Rails, so I try my best to hack out the path to the layout below.
58
101
  def controller_layout
59
- layout = self.send(:_layout)
60
- if layout.instance_of? String
102
+ private_layout_method = self.method(:_layout)
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
111
+
112
+ if layout.instance_of? String # Rails 4 and 5 return a string from above.
61
113
  layout
62
- else
114
+ elsif layout # Rails 3 and older return an object that gives us a file name
63
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
120
+ end
121
+ end
122
+
123
+ # Rails 5 requires an extension, like `:html`, to resolve a template. This
124
+ # method returns the intersection of the formats Rails supports from Mime::Types
125
+ # and the current page's node formats. If nothing intersects, HTML is returned
126
+ # as a default.
127
+ def current_page_rails_formats
128
+ extensions = current_page.node.formats.extensions
129
+ supported_extensions = extensions & Mime::EXTENSION_LOOKUP.keys
130
+
131
+ if supported_extensions.empty?
132
+ DEFAULT_PAGE_RAILS_FORMATS
133
+ else
134
+ supported_extensions.map?(&:to_sym)
64
135
  end
65
136
  end
66
137
  end
@@ -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