sitepress-rails 2.0.0.beta3 → 2.0.0.beta8
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 +4 -4
- data/.gitignore +7 -0
- data/bin/rails +13 -0
- data/lib/sitepress/build_paths/directory_index_path.rb +1 -1
- data/lib/sitepress/build_paths/index_path.rb +4 -4
- data/lib/sitepress/build_paths/root_path.rb +12 -8
- data/lib/sitepress/compiler.rb +40 -47
- data/lib/sitepress/engine.rb +3 -9
- data/lib/sitepress/rails.rb +4 -1
- data/lib/sitepress/renderers/controller.rb +11 -9
- data/lib/sitepress/renderers/server.rb +12 -4
- data/rails/app/controllers/concerns/sitepress/site_pages.rb +132 -0
- data/rails/app/controllers/sitepress/site_controller.rb +7 -0
- data/rails/config/routes.rb +12 -0
- data/sitepress-rails.gemspec +32 -0
- data/spec/dummy/app/content/pages/all_pages.html.erb.html +14 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/production.log +1056 -0
- data/spec/dummy/log/test.log +64148 -1708
- data/spec/sitepress-rails_spec.rb +0 -23
- data/spec/sitepress/compiler_spec.rb +7 -7
- data/spec/sitepress/sitepress_site_controller_spec.rb +5 -24
- metadata +62 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8847542b4eda39498873172a50e932d9f227bb5449ad36d164a47f563eb0d058
|
4
|
+
data.tar.gz: 027d9477d21a64e432fa4a5875570cd64b52eb5fb4124479fd360e5a8d5d31fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f25562abb42ffa015f2f5736c2fe63e54f773f93f3d25fdcc8704eb23e0636fd9bd1a7e7f6834bf179092c1979620e1f96e7f1e761a1be4f3a8c8d2a2ee7591
|
7
|
+
data.tar.gz: 5fc33c2a07f472d74f1bcde41041ee833fd9bab24985282ad0e512004d5d0adc27b84c5da4cf567257699fe3f830613e040b8ebb7478760cbc137e1ef7e6d67f
|
data/.gitignore
ADDED
data/bin/rails
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails gems
|
3
|
+
# installed from the root of your application.
|
4
|
+
|
5
|
+
ENGINE_ROOT = File.expand_path('../..', __FILE__)
|
6
|
+
ENGINE_PATH = File.expand_path('../../lib/sitepress-rails/engine', __FILE__)
|
7
|
+
|
8
|
+
# Set up gems listed in the Gemfile.
|
9
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
10
|
+
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
11
|
+
|
12
|
+
require 'rails/all'
|
13
|
+
require 'rails/engine/commands'
|
@@ -4,7 +4,7 @@ module Sitepress
|
|
4
4
|
# hosts like S3. To achieve this effect, we have to compile `pages/blah.html.haml`
|
5
5
|
# to a folder with the filename `index.html`, so the final path would be `/blah/index.html`
|
6
6
|
class DirectoryIndexPath < IndexPath
|
7
|
-
def
|
7
|
+
def filename_with_default_format
|
8
8
|
File.join(node.name, "#{node.default_name}.#{format}")
|
9
9
|
end
|
10
10
|
end
|
@@ -4,16 +4,16 @@ module Sitepress
|
|
4
4
|
# pages too, mainly grabbing the root, which doesn't have a name in the node, to the default_name
|
5
5
|
# of the node, which is usually `index`.
|
6
6
|
class IndexPath < RootPath
|
7
|
-
def
|
7
|
+
def filename_without_format
|
8
8
|
node.name
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
11
|
+
def filename_with_format
|
12
12
|
"#{node.name}.#{format}"
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
15
|
+
def filename_with_default_format
|
16
|
+
filename_with_format
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -13,27 +13,31 @@ module Sitepress
|
|
13
13
|
@resource = resource
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
16
|
+
def filename
|
17
17
|
if format.nil?
|
18
|
-
|
18
|
+
filename_without_format
|
19
19
|
elsif format == node.default_format
|
20
|
-
|
20
|
+
filename_with_default_format
|
21
21
|
elsif format
|
22
|
-
|
22
|
+
filename_with_format
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
def path
|
27
|
+
File.join(*resource.lineage, filename)
|
28
|
+
end
|
29
|
+
|
26
30
|
protected
|
27
|
-
def
|
31
|
+
def filename_without_format
|
28
32
|
node.default_name
|
29
33
|
end
|
30
34
|
|
31
|
-
def
|
35
|
+
def filename_with_format
|
32
36
|
"#{node.default_name}.#{format}"
|
33
37
|
end
|
34
38
|
|
35
|
-
def
|
36
|
-
|
39
|
+
def filename_with_default_format
|
40
|
+
filename_with_format
|
37
41
|
end
|
38
42
|
end
|
39
43
|
end
|
data/lib/sitepress/compiler.rb
CHANGED
@@ -6,63 +6,56 @@ module Sitepress
|
|
6
6
|
class Compiler
|
7
7
|
include FileUtils
|
8
8
|
|
9
|
-
|
10
|
-
attr_reader :resource
|
9
|
+
attr_reader :site, :root_path
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
def initialize(site:, root_path:, stdout: $stdout)
|
12
|
+
@site = site
|
13
|
+
@stdout = stdout
|
14
|
+
@root_path = Pathname.new(root_path)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Iterates through all pages and writes them to disk
|
18
|
+
def compile
|
19
|
+
status "Building #{site.root_path.expand_path} to #{root_path.expand_path}"
|
20
|
+
resources.each do |resource, path|
|
21
|
+
if resource.renderable?
|
22
|
+
status " Rendering #{path}"
|
23
|
+
File.open(path.expand_path, "w"){ |f| f.write render resource }
|
24
|
+
else
|
25
|
+
status " Copying #{path}"
|
26
|
+
cp resource.asset.path, path.expand_path
|
27
|
+
end
|
28
|
+
rescue
|
29
|
+
status "Error building #{resource.inspect}"
|
30
|
+
raise
|
14
31
|
end
|
32
|
+
status "Successful build to #{root_path.expand_path}"
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def resources
|
37
|
+
Enumerator.new do |y|
|
38
|
+
mkdir_p root_path
|
15
39
|
|
16
|
-
|
17
|
-
|
40
|
+
site.resources.each do |resource|
|
41
|
+
path = build_path resource
|
42
|
+
mkdir_p path.dirname
|
43
|
+
y << [resource, path]
|
44
|
+
end
|
45
|
+
end
|
18
46
|
end
|
19
47
|
|
20
|
-
|
21
|
-
|
22
|
-
path_builder
|
23
|
-
path_builder.new(resource).path
|
48
|
+
def build_path(resource)
|
49
|
+
path_builder = resource.node.root? ? BuildPaths::RootPath : BuildPaths::DirectoryIndexPath
|
50
|
+
root_path.join path_builder.new(resource).path
|
24
51
|
end
|
25
52
|
|
26
|
-
def render(
|
53
|
+
def render(resource)
|
27
54
|
Renderers::Server.new(resource).render
|
28
55
|
end
|
29
|
-
end
|
30
56
|
|
31
|
-
|
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
|
57
|
+
def status(message)
|
58
|
+
@stdout.puts message
|
65
59
|
end
|
66
|
-
end
|
67
60
|
end
|
68
61
|
end
|
data/lib/sitepress/engine.rb
CHANGED
@@ -20,26 +20,20 @@ module Sitepress
|
|
20
20
|
# Load paths from `Sitepress#site` into rails so it can render views, helpers, etc. properly.
|
21
21
|
initializer :set_sitepress_paths, before: :set_autoload_paths do |app|
|
22
22
|
app.paths["app/helpers"].push site.helpers_path.expand_path
|
23
|
+
app.paths["app/assets"].push site.assets_path.expand_path
|
23
24
|
app.paths["app/views"].push site.root_path.expand_path
|
24
25
|
app.paths["app/views"].push site.pages_path.expand_path
|
25
26
|
end
|
26
27
|
|
27
28
|
# Configure sprockets paths for the site.
|
28
|
-
initializer :
|
29
|
+
initializer :set_manifest_file_path, before: :append_assets_path do |app|
|
29
30
|
manifest_file = sitepress_configuration.manifest_file_path.expand_path
|
30
|
-
|
31
|
-
if manifest_file.exist?
|
32
|
-
app.paths["app/assets"].push site.assets_path.expand_path
|
33
|
-
app.config.assets.precompile << manifest_file.to_s
|
34
|
-
else
|
35
|
-
Rails.logger.warn "WARNING: Sitepress could not enable Sprockets because it could not find a manifest file at #{manifest_file.to_s.inspect}."
|
36
|
-
end
|
31
|
+
app.config.assets.precompile << manifest_file.to_s if manifest_file.exist?
|
37
32
|
end
|
38
33
|
|
39
34
|
# Configure Sitepress with Rails settings.
|
40
35
|
initializer :configure_sitepress do |app|
|
41
36
|
sitepress_configuration.parent_engine = app
|
42
|
-
sitepress_configuration.cache_resources = app.config.cache_classes
|
43
37
|
end
|
44
38
|
|
45
39
|
private
|
data/lib/sitepress/rails.rb
CHANGED
@@ -3,11 +3,11 @@ require "sitepress-core"
|
|
3
3
|
module Sitepress
|
4
4
|
autoload :Compiler, "sitepress/compiler"
|
5
5
|
autoload :RailsConfiguration, "sitepress/rails_configuration"
|
6
|
-
autoload :RouteConstraint, "sitepress/route_constraint"
|
7
6
|
module Renderers
|
8
7
|
autoload :Controller, "sitepress/renderers/controller"
|
9
8
|
autoload :Server, "sitepress/renderers/server"
|
10
9
|
end
|
10
|
+
autoload :RouteConstraint, "sitepress/route_constraint"
|
11
11
|
module BuildPaths
|
12
12
|
autoload :RootPath, "sitepress/build_paths/root_path"
|
13
13
|
autoload :IndexPath, "sitepress/build_paths/index_path"
|
@@ -17,6 +17,9 @@ module Sitepress
|
|
17
17
|
# Rescued by ActionController to display page not found error.
|
18
18
|
PageNotFoundError = Class.new(StandardError)
|
19
19
|
|
20
|
+
# Raised when any of the Render subclasses can't render a page.
|
21
|
+
RenderingError = Class.new(RuntimeError)
|
22
|
+
|
20
23
|
# Make site available via Sitepress.site from Rails app.
|
21
24
|
def self.site
|
22
25
|
configuration.site
|
@@ -1,18 +1,20 @@
|
|
1
1
|
module Sitepress
|
2
2
|
module Renderers
|
3
|
+
# This would be the ideal way to render Sitepress resources, but there's a lot
|
4
|
+
# of hackery involved in getting it to work properly.
|
3
5
|
class Controller
|
4
|
-
attr_reader :controller, :
|
6
|
+
attr_reader :controller, :resource
|
5
7
|
|
6
|
-
def initialize(
|
8
|
+
def initialize(resource, controller = SiteController)
|
7
9
|
@controller = controller
|
8
|
-
@
|
10
|
+
@resource = resource
|
9
11
|
end
|
10
12
|
|
11
13
|
def render
|
12
|
-
renderer.render inline:
|
13
|
-
type:
|
14
|
+
renderer.render inline: resource.body,
|
15
|
+
type: resource.asset.template_extensions.last,
|
14
16
|
layout: resolve_layout,
|
15
|
-
content_type:
|
17
|
+
content_type: resource.mime_type.to_s
|
16
18
|
end
|
17
19
|
|
18
20
|
private
|
@@ -29,15 +31,15 @@ module Sitepress
|
|
29
31
|
end
|
30
32
|
|
31
33
|
def renderer
|
32
|
-
controller.renderer.new("PATH_INFO" =>
|
34
|
+
controller.renderer.new("PATH_INFO" => resource.request_path)
|
33
35
|
end
|
34
36
|
|
35
37
|
def resolve_layout
|
36
|
-
return
|
38
|
+
return resource.data.fetch("layout") if resource.data.key? "layout"
|
37
39
|
return layout unless has_layout_conditions?
|
38
40
|
|
39
41
|
clause, formats = layout_conditions.first
|
40
|
-
format =
|
42
|
+
format = resource.format.to_s
|
41
43
|
|
42
44
|
case clause
|
43
45
|
when :only
|
@@ -1,21 +1,29 @@
|
|
1
1
|
module Sitepress
|
2
2
|
module Renderers
|
3
|
+
# Renders resources by invoking a rack call to the Rails application. From my
|
4
|
+
# experiments rendering as of 2021, this is the most reliable way to render
|
5
|
+
# resources. Rendering via `Renderers::Controller` has lots of various subtle issues
|
6
|
+
# that are surprising. People don't like surprises, so I opted to render through a
|
7
|
+
# slightly heavier stack.
|
3
8
|
class Server
|
4
|
-
attr_reader :rails_app, :
|
9
|
+
attr_reader :rails_app, :resource
|
5
10
|
|
6
|
-
def initialize(
|
11
|
+
def initialize(resource, rails_app = Rails.application)
|
7
12
|
@rails_app = rails_app
|
8
|
-
@
|
13
|
+
@resource = resource
|
9
14
|
end
|
10
15
|
|
11
16
|
def render
|
12
17
|
code, headers, response = rails_app.routes.call env
|
13
18
|
response.body
|
19
|
+
rescue => e
|
20
|
+
raise RenderingError.new "Error rendering #{resource.request_path.inspect} at #{resource.asset.path.expand_path.to_s.inspect}:\n#{e.message}"
|
14
21
|
end
|
15
22
|
|
23
|
+
private
|
16
24
|
def env
|
17
25
|
{
|
18
|
-
"PATH_INFO"=>
|
26
|
+
"PATH_INFO"=> resource.request_path,
|
19
27
|
"REQUEST_METHOD"=>"GET",
|
20
28
|
"rack.input" => "GET"
|
21
29
|
}
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Sitepress
|
2
|
+
# Serves up Sitepress site pages in a rails application. This is mixed into the
|
3
|
+
# Sitepress::SiteController, but may be included into other controllers for static
|
4
|
+
# page behavior.
|
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
|
+
|
13
|
+
extend ActiveSupport::Concern
|
14
|
+
|
15
|
+
included do
|
16
|
+
rescue_from Sitepress::PageNotFoundError, with: :page_not_found
|
17
|
+
helper Sitepress::Engine.helpers
|
18
|
+
helper_method :current_page, :site
|
19
|
+
before_action :append_relative_partial_path, only: :show
|
20
|
+
after_action :reload_site, only: :show
|
21
|
+
end
|
22
|
+
|
23
|
+
def show
|
24
|
+
render_page current_page
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
def render_page(page)
|
29
|
+
if page.renderable?
|
30
|
+
render_text_resource page
|
31
|
+
else
|
32
|
+
send_binary_resource page
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def current_page
|
37
|
+
@current_page ||= find_resource
|
38
|
+
end
|
39
|
+
|
40
|
+
def site
|
41
|
+
Sitepress.site
|
42
|
+
end
|
43
|
+
|
44
|
+
def page_not_found(e)
|
45
|
+
raise ActionController::RoutingError, e.message
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def append_relative_partial_path
|
50
|
+
append_view_path current_page.asset.path.dirname
|
51
|
+
end
|
52
|
+
|
53
|
+
def render_text_resource(resource)
|
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
|
+
|
60
|
+
def send_binary_resource(resource)
|
61
|
+
send_file resource.asset.path,
|
62
|
+
disposition: :inline,
|
63
|
+
type: resource.mime_type.to_s
|
64
|
+
end
|
65
|
+
|
66
|
+
# Sitepress::PageNotFoundError is handled in the default Sitepress::SiteController
|
67
|
+
# with an execption that Rails can use to display a 404 error.
|
68
|
+
def get(path)
|
69
|
+
resource = site.resources.get(path)
|
70
|
+
if resource.nil?
|
71
|
+
# TODO: Display error in context of Reources class root.
|
72
|
+
raise Sitepress::PageNotFoundError, "No such page: #{path}"
|
73
|
+
else
|
74
|
+
resource
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Default finder of the resource for the current controller context. If the :resource_path
|
79
|
+
# isn't present, then its probably the root path so grab that.
|
80
|
+
def find_resource
|
81
|
+
get params.fetch(:resource_path, ROOT_RESOURCE_PATH)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns the current layout for the inline Sitepress renderer. This is
|
85
|
+
# exposed via some really convoluted private methods inside of the various
|
86
|
+
# versions of Rails, so I try my best to hack out the path to the layout below.
|
87
|
+
def controller_layout
|
88
|
+
private_layout_method = self.method(:_layout)
|
89
|
+
layout =
|
90
|
+
if Rails.version >= "6"
|
91
|
+
private_layout_method.call lookup_context, current_page_rails_formats
|
92
|
+
elsif Rails.version >= "5"
|
93
|
+
private_layout_method.call current_page_rails_formats
|
94
|
+
else
|
95
|
+
private_layout_method.call
|
96
|
+
end
|
97
|
+
|
98
|
+
if layout.instance_of? String # Rails 4 and 5 return a string from above.
|
99
|
+
layout
|
100
|
+
elsif layout # Rails 3 and older return an object that gives us a file name
|
101
|
+
File.basename(layout.identifier).split('.').first
|
102
|
+
else
|
103
|
+
# If none of the conditions are met, then no layout was
|
104
|
+
# specified, so nil is returned.
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Rails 5 requires an extension, like `:html`, to resolve a template. This
|
110
|
+
# method returns the intersection of the formats Rails supports from Mime::Types
|
111
|
+
# and the current page's node formats. If nothing intersects, HTML is returned
|
112
|
+
# as a default.
|
113
|
+
def current_page_rails_formats
|
114
|
+
extensions = current_page.node.formats.extensions
|
115
|
+
supported_extensions = extensions & Mime::EXTENSION_LOOKUP.keys
|
116
|
+
|
117
|
+
if supported_extensions.empty?
|
118
|
+
DEFAULT_PAGE_RAILS_FORMATS
|
119
|
+
else
|
120
|
+
supported_extensions.map?(&:to_sym)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def reload_site
|
125
|
+
site.reload! if reload_site?
|
126
|
+
end
|
127
|
+
|
128
|
+
def reload_site?
|
129
|
+
!Rails.configuration.cache_classes
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|