locomotivecms_builder 1.0.0.alpha1
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.
- data/.gitignore +31 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +68 -0
- data/Rakefile +47 -0
- data/TODO +57 -0
- data/bin/builder +9 -0
- data/generators/blank/Gemfile.tt +20 -0
- data/generators/blank/app/content_types/.empty_directory +1 -0
- data/generators/blank/app/views/pages/404.liquid +11 -0
- data/generators/blank/app/views/pages/index.liquid +19 -0
- data/generators/blank/app/views/snippets/.empty_directory +1 -0
- data/generators/blank/config/deploy.yml +12 -0
- data/generators/blank/config/site.yml.tt +16 -0
- data/generators/blank/config/translations.yml +8 -0
- data/generators/blank/config.ru +3 -0
- data/generators/blank/data/.empty_directory +1 -0
- data/generators/blank/public/fonts/.empty_directory +1 -0
- data/generators/blank/public/images/.empty_directory +1 -0
- data/generators/blank/public/javascripts/.empty_directory +1 -0
- data/generators/blank/public/samples/.empty_directory +1 -0
- data/generators/blank/public/stylesheets/.empty_directory +1 -0
- data/generators/bootstrap/Gemfile.tt +20 -0
- data/generators/bootstrap/app/content_types/.empty_directory +1 -0
- data/generators/bootstrap/app/views/pages/404.liquid +13 -0
- data/generators/bootstrap/app/views/pages/404.liquid.haml +10 -0
- data/generators/bootstrap/app/views/pages/index.liquid +85 -0
- data/generators/bootstrap/app/views/pages/index.liquid.haml +72 -0
- data/generators/bootstrap/app/views/snippets/footer.liquid +3 -0
- data/generators/bootstrap/app/views/snippets/footer.liquid.haml +2 -0
- data/generators/bootstrap/config/deploy.yml +12 -0
- data/generators/bootstrap/config/site.yml.tt +16 -0
- data/generators/bootstrap/config/translations.yml +8 -0
- data/generators/bootstrap/config.ru +3 -0
- data/generators/bootstrap/data/.empty_directory +1 -0
- data/generators/bootstrap/public/fonts/FontAwesome.otf +0 -0
- data/generators/bootstrap/public/fonts/font-awesome-ie7.min.css +23 -0
- data/generators/bootstrap/public/fonts/font-awesome.css +469 -0
- data/generators/bootstrap/public/fonts/font-awesome.min.css +34 -0
- data/generators/bootstrap/public/fonts/fontawesome-webfont.eot +0 -0
- data/generators/bootstrap/public/fonts/fontawesome-webfont.ttf +0 -0
- data/generators/bootstrap/public/fonts/fontawesome-webfont.woff +0 -0
- data/generators/bootstrap/public/javascripts/bootstrap.js +2159 -0
- data/generators/bootstrap/public/javascripts/bootstrap.min.js +6 -0
- data/generators/bootstrap/public/samples/.empty_directory +1 -0
- data/generators/bootstrap/public/stylesheets/application.css.scss +39 -0
- data/generators/bootstrap/public/stylesheets/bootstrap-responsive.css +1092 -0
- data/generators/bootstrap/public/stylesheets/bootstrap-responsive.min.css +9 -0
- data/generators/bootstrap/public/stylesheets/bootstrap.css +5652 -0
- data/generators/bootstrap/public/stylesheets/bootstrap.min.css +726 -0
- data/generators/content_type/app/content_types/%name%.yml.tt +58 -0
- data/generators/content_type/data/%name%.yml.tt +24 -0
- data/generators/page/template.liquid.haml.tt +35 -0
- data/generators/page/template.liquid.tt +1 -0
- data/generators/snippet/template.liquid.haml.tt +4 -0
- data/generators/snippet/template.liquid.tt +4 -0
- data/lib/locomotive/builder/cli.rb +225 -0
- data/lib/locomotive/builder/exceptions.rb +17 -0
- data/lib/locomotive/builder/generators/content_type.rb +47 -0
- data/lib/locomotive/builder/generators/page.rb +57 -0
- data/lib/locomotive/builder/generators/site/base.rb +30 -0
- data/lib/locomotive/builder/generators/site/blank.rb +23 -0
- data/lib/locomotive/builder/generators/site/bootstrap.rb +35 -0
- data/lib/locomotive/builder/generators/site.rb +97 -0
- data/lib/locomotive/builder/generators/snippet.rb +54 -0
- data/lib/locomotive/builder/liquid/drops/base.rb +44 -0
- data/lib/locomotive/builder/liquid/drops/content_entry.rb +48 -0
- data/lib/locomotive/builder/liquid/drops/content_types.rb +121 -0
- data/lib/locomotive/builder/liquid/drops/page.rb +36 -0
- data/lib/locomotive/builder/liquid/drops/site.rb +21 -0
- data/lib/locomotive/builder/liquid/errors.rb +7 -0
- data/lib/locomotive/builder/liquid/filters/date.rb +98 -0
- data/lib/locomotive/builder/liquid/filters/html.rb +154 -0
- data/lib/locomotive/builder/liquid/filters/misc.rb +28 -0
- data/lib/locomotive/builder/liquid/filters/resize.rb +18 -0
- data/lib/locomotive/builder/liquid/filters/text.rb +50 -0
- data/lib/locomotive/builder/liquid/filters/translate.rb +24 -0
- data/lib/locomotive/builder/liquid/patches.rb +47 -0
- data/lib/locomotive/builder/liquid/tags/consume.rb +58 -0
- data/lib/locomotive/builder/liquid/tags/csrf.rb +34 -0
- data/lib/locomotive/builder/liquid/tags/editable/base.rb +46 -0
- data/lib/locomotive/builder/liquid/tags/editable/control.rb +19 -0
- data/lib/locomotive/builder/liquid/tags/editable/file.rb +15 -0
- data/lib/locomotive/builder/liquid/tags/editable/long_text.rb +15 -0
- data/lib/locomotive/builder/liquid/tags/editable/short_text.rb +15 -0
- data/lib/locomotive/builder/liquid/tags/editable.rb +5 -0
- data/lib/locomotive/builder/liquid/tags/extends.rb +25 -0
- data/lib/locomotive/builder/liquid/tags/google_analytics.rb +28 -0
- data/lib/locomotive/builder/liquid/tags/inline_editor.rb +16 -0
- data/lib/locomotive/builder/liquid/tags/locale_switcher.rb +180 -0
- data/lib/locomotive/builder/liquid/tags/nav.rb +167 -0
- data/lib/locomotive/builder/liquid/tags/paginate.rb +105 -0
- data/lib/locomotive/builder/liquid/tags/seo.rb +74 -0
- data/lib/locomotive/builder/liquid/tags/snippet.rb +42 -0
- data/lib/locomotive/builder/liquid/tags/with_scope.rb +43 -0
- data/lib/locomotive/builder/liquid.rb +19 -0
- data/lib/locomotive/builder/listen.rb +48 -0
- data/lib/locomotive/builder/misc/core_ext.rb +29 -0
- data/lib/locomotive/builder/misc/dragonfly.rb +82 -0
- data/lib/locomotive/builder/misc/httparty.rb +47 -0
- data/lib/locomotive/builder/misc/i18n.rb +2 -0
- data/lib/locomotive/builder/misc/will_paginate.rb +16 -0
- data/lib/locomotive/builder/misc.rb +5 -0
- data/lib/locomotive/builder/server/dynamic_assets.rb +31 -0
- data/lib/locomotive/builder/server/entry_submission.rb +116 -0
- data/lib/locomotive/builder/server/favicon.rb +17 -0
- data/lib/locomotive/builder/server/locale.rb +42 -0
- data/lib/locomotive/builder/server/middleware.rb +54 -0
- data/lib/locomotive/builder/server/not_found.rb +18 -0
- data/lib/locomotive/builder/server/page.rb +59 -0
- data/lib/locomotive/builder/server/path.rb +34 -0
- data/lib/locomotive/builder/server/renderer.rb +105 -0
- data/lib/locomotive/builder/server/templatized_page.rb +32 -0
- data/lib/locomotive/builder/server.rb +78 -0
- data/lib/locomotive/builder/standalone_server.rb +33 -0
- data/lib/locomotive/builder/version.rb +5 -0
- data/lib/locomotive/builder.rb +167 -0
- data/locales/de.yml +143 -0
- data/locales/en.yml +164 -0
- data/locales/es.yml +119 -0
- data/locales/et.yml +140 -0
- data/locales/fr.yml +133 -0
- data/locales/it.yml +141 -0
- data/locales/nb.yml +177 -0
- data/locales/nl.yml +148 -0
- data/locales/pl.yml +189 -0
- data/locales/pt-BR.yml +125 -0
- data/locales/ru.yml +210 -0
- data/locomotivecms_builder.gemspec +42 -0
- data/spec/integration/cassettes/pull.yml +590 -0
- data/spec/integration/cassettes/push.yml +775 -0
- data/spec/integration/integration_helper.rb +15 -0
- data/spec/integration/server_spec.rb +37 -0
- data/spec/integration/sites_spec.rb +27 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/helpers.rb +13 -0
- metadata +468 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Locomotive::Builder
|
|
2
|
+
class Server
|
|
3
|
+
|
|
4
|
+
class DynamicAssets < Middleware
|
|
5
|
+
|
|
6
|
+
def call(env)
|
|
7
|
+
self.set_accessors(env)
|
|
8
|
+
|
|
9
|
+
path = env['PATH_INFO']
|
|
10
|
+
|
|
11
|
+
if path =~ /^\/(stylesheets|javascripts)\//
|
|
12
|
+
|
|
13
|
+
mime_type = MIME::Types.type_for(path).first.try(:to_s) || 'text/plain'
|
|
14
|
+
asset = self.mounting_point.theme_assets.detect do |_asset|
|
|
15
|
+
_asset.path == path
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
if asset
|
|
19
|
+
[200, { 'Content-Type' => mime_type }, [asset.content!]]
|
|
20
|
+
else
|
|
21
|
+
[404, { 'Content-Type' => mime_type }, ['Asset not found']]
|
|
22
|
+
end
|
|
23
|
+
else
|
|
24
|
+
app.call(env)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
module Locomotive::Builder
|
|
2
|
+
class Server
|
|
3
|
+
|
|
4
|
+
# Mimic the submission of a content entry
|
|
5
|
+
#
|
|
6
|
+
class EntrySubmission < Middleware
|
|
7
|
+
|
|
8
|
+
def call(env)
|
|
9
|
+
self.set_accessors(env)
|
|
10
|
+
|
|
11
|
+
if self.request.post? && env['PATH_INFO'] =~ /^\/entry_submissions\/(.*)/
|
|
12
|
+
self.process_form($1)
|
|
13
|
+
|
|
14
|
+
if @entry.valid?
|
|
15
|
+
if self.html?
|
|
16
|
+
self.record_submitted_entry
|
|
17
|
+
self.redirect_to self.callback_url
|
|
18
|
+
elsif self.json?
|
|
19
|
+
self.json_response
|
|
20
|
+
end
|
|
21
|
+
else
|
|
22
|
+
if self.html?
|
|
23
|
+
if self.callback_url =~ /^http:\/\//
|
|
24
|
+
self.redirect_to self.callback_url
|
|
25
|
+
else
|
|
26
|
+
env['PATH_INFO'] = self.callback_url
|
|
27
|
+
self.liquid_assigns[@content_type.slug.singularize] = @entry
|
|
28
|
+
app.call(env)
|
|
29
|
+
end
|
|
30
|
+
elsif self.json?
|
|
31
|
+
self.json_response(422)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
else
|
|
35
|
+
self.fetch_submitted_entry
|
|
36
|
+
|
|
37
|
+
app.call(env)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
protected
|
|
42
|
+
|
|
43
|
+
def record_submitted_entry
|
|
44
|
+
self.request.session[:now] ||= {}
|
|
45
|
+
self.request.session[:now][:submitted_entry] = [@content_type.slug, @entry._slug]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def fetch_submitted_entry
|
|
49
|
+
if data = self.request.session[:now].try(:delete, :submitted_entry)
|
|
50
|
+
content_type = self.mounting_point.content_types[data.first.to_s]
|
|
51
|
+
|
|
52
|
+
entry = (content_type.entries || []).detect { |e| e._slug == data.last }
|
|
53
|
+
|
|
54
|
+
# do not keep track of the entry
|
|
55
|
+
content_type.entries.delete(entry) if entry
|
|
56
|
+
|
|
57
|
+
# add it to the additional liquid assigns for the next liquid rendering
|
|
58
|
+
if entry
|
|
59
|
+
self.liquid_assigns[content_type.slug.singularize] = entry
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Mimic the creation of a content entry with a minimal validation.
|
|
65
|
+
#
|
|
66
|
+
# @param [ String ] permalink The permalink (or slug) of the content type
|
|
67
|
+
#
|
|
68
|
+
#
|
|
69
|
+
def process_form(permalink)
|
|
70
|
+
permalink = permalink.split('.').first
|
|
71
|
+
|
|
72
|
+
@content_type = self.mounting_point.content_types[permalink]
|
|
73
|
+
|
|
74
|
+
raise "Unknown content type '#{@content_type.inspect}'" if @content_type.nil?
|
|
75
|
+
|
|
76
|
+
@entry = @content_type.build_entry(self.params[:entry] || self.params[:content])
|
|
77
|
+
|
|
78
|
+
# if not valid, we do not need to keep track of the entry
|
|
79
|
+
@content_type.entries.delete(@entry) if !@entry.valid?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def callback_url
|
|
83
|
+
(@entry.valid? ? params[:success_callback] : params[:error_callback]) || '/'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Build the JSON response
|
|
87
|
+
#
|
|
88
|
+
# @param [ Integer ] status The HTTP return code
|
|
89
|
+
#
|
|
90
|
+
# @return [ Array ] The rack response depending on the validation status and the requested format
|
|
91
|
+
#
|
|
92
|
+
def json_response(status = 200)
|
|
93
|
+
locale = self.mounting_point.default_locale
|
|
94
|
+
|
|
95
|
+
if self.request.path =~ /^\/(#{self.mounting_point.locales.join('|')})+(\/|$)/
|
|
96
|
+
locale = $1
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
hash = @entry.to_hash(false).tap do |_hash|
|
|
100
|
+
if !@entry.valid?
|
|
101
|
+
_hash['errors'] = @entry.errors.inject({}) do |memo, name|
|
|
102
|
+
memo[name] = ::I18n.t('errors.messages.blank', locale: locale)
|
|
103
|
+
memo
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
[status, { 'Content-Type' => 'application/json' }, [
|
|
109
|
+
{ @content_type.slug.singularize => hash }.to_json
|
|
110
|
+
]]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Locomotive::Builder
|
|
2
|
+
class Server
|
|
3
|
+
|
|
4
|
+
class Favicon < Middleware
|
|
5
|
+
|
|
6
|
+
def call(env)
|
|
7
|
+
if env['PATH_INFO'] == '/favicon.ico'
|
|
8
|
+
[200, { 'Content-Type' => 'image/vnd.microsoft.icon' }, ['']]
|
|
9
|
+
else
|
|
10
|
+
app.call(env)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Locomotive::Builder
|
|
2
|
+
class Server
|
|
3
|
+
|
|
4
|
+
# Set the locale from the path if possible or use the default one
|
|
5
|
+
# Examples:
|
|
6
|
+
# /fr/index => locale = :fr
|
|
7
|
+
# /fr/ => locale = :fr
|
|
8
|
+
# /index => locale = :en (default one)
|
|
9
|
+
#
|
|
10
|
+
class Locale < Middleware
|
|
11
|
+
|
|
12
|
+
def call(env)
|
|
13
|
+
self.set_accessors(env)
|
|
14
|
+
|
|
15
|
+
self.set_locale!(env)
|
|
16
|
+
|
|
17
|
+
app.call(env)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
protected
|
|
21
|
+
|
|
22
|
+
def set_locale!(env)
|
|
23
|
+
locale = self.mounting_point.default_locale
|
|
24
|
+
|
|
25
|
+
if self.path =~ /^(#{self.mounting_point.locales.join('|')})+(\/|$)/
|
|
26
|
+
locale = $1
|
|
27
|
+
self.path = self.path.gsub($1 + $2, '')
|
|
28
|
+
self.path = 'index' if self.path.blank?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
Locomotive::Mounter.locale = locale
|
|
32
|
+
::I18n.locale = locale
|
|
33
|
+
|
|
34
|
+
puts "[Builder|Locale] path = #{self.path.inspect}, locale = #{locale.inspect}"
|
|
35
|
+
|
|
36
|
+
env['builder.locale'] = locale
|
|
37
|
+
env['builder.path'] = self.path
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Locomotive::Builder
|
|
2
|
+
class Server
|
|
3
|
+
|
|
4
|
+
class Middleware
|
|
5
|
+
|
|
6
|
+
attr_accessor :app, :request, :path, :liquid_assigns
|
|
7
|
+
|
|
8
|
+
attr_accessor :mounting_point, :page, :content_entry
|
|
9
|
+
|
|
10
|
+
def initialize(app = nil)
|
|
11
|
+
@app = app
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def call(env)
|
|
15
|
+
app.call(env)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
protected
|
|
19
|
+
|
|
20
|
+
def set_accessors(env)
|
|
21
|
+
self.path = env['builder.path']
|
|
22
|
+
self.request = Rack::Request.new(env)
|
|
23
|
+
self.mounting_point = env['builder.mounting_point']
|
|
24
|
+
self.page = env['builder.page']
|
|
25
|
+
self.content_entry = env['builder.content_entry']
|
|
26
|
+
|
|
27
|
+
env['builder.liquid_assigns'] ||= {}
|
|
28
|
+
self.liquid_assigns = env['builder.liquid_assigns']
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def site
|
|
32
|
+
self.mounting_point.site
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def params
|
|
36
|
+
self.request.params.deep_symbolize_keys
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def html?
|
|
40
|
+
self.request.media_type == 'text/html' || !self.request.xhr?
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def json?
|
|
44
|
+
self.request.content_type == 'application/json' || File.extname(self.request.path) == '.json'
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def redirect_to(location)
|
|
48
|
+
[301, { 'Content-Type' => 'text/html', 'Location' => location }, []]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Locomotive::Builder
|
|
2
|
+
class Server
|
|
3
|
+
|
|
4
|
+
class NotFound < Middleware
|
|
5
|
+
|
|
6
|
+
def call(env)
|
|
7
|
+
self.set_accessors(env)
|
|
8
|
+
|
|
9
|
+
if self.page.nil?
|
|
10
|
+
env['builder.page'] = self.mounting_point.pages['404']
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
app.call(env)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Locomotive::Builder
|
|
2
|
+
class Server
|
|
3
|
+
|
|
4
|
+
# Sanitize the path from the previous middleware in order
|
|
5
|
+
# to make it work for the renderer.
|
|
6
|
+
#
|
|
7
|
+
class Page < Middleware
|
|
8
|
+
|
|
9
|
+
def call(env)
|
|
10
|
+
self.set_accessors(env)
|
|
11
|
+
|
|
12
|
+
self.set_page!(env)
|
|
13
|
+
|
|
14
|
+
app.call(env)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
protected
|
|
18
|
+
|
|
19
|
+
def set_page!(env)
|
|
20
|
+
page = self.fetch_page
|
|
21
|
+
|
|
22
|
+
puts "[Builder|Page] #{page.inspect}"
|
|
23
|
+
|
|
24
|
+
env['builder.page'] = page
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def fetch_page
|
|
28
|
+
matchers = self.path_combinations(self.path)
|
|
29
|
+
|
|
30
|
+
self.mounting_point.pages.values.detect do |_page|
|
|
31
|
+
matchers.include?(_page.safe_fullpath) ||
|
|
32
|
+
matchers.include?(_page.safe_fullpath.try(:underscore))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def path_combinations(path)
|
|
37
|
+
self._path_combinations(path.split('/'))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def _path_combinations(segments, can_include_template = true)
|
|
41
|
+
return nil if segments.empty?
|
|
42
|
+
|
|
43
|
+
segment = segments.shift
|
|
44
|
+
|
|
45
|
+
(can_include_template ? [segment, '*'] : [segment]).map do |_segment|
|
|
46
|
+
if (_combinations = _path_combinations(segments.clone, can_include_template && _segment != '*'))
|
|
47
|
+
[*_combinations].map do |_combination|
|
|
48
|
+
File.join(_segment, _combination)
|
|
49
|
+
end
|
|
50
|
+
else
|
|
51
|
+
[_segment]
|
|
52
|
+
end
|
|
53
|
+
end.flatten
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Locomotive::Builder
|
|
2
|
+
class Server
|
|
3
|
+
|
|
4
|
+
# Sanitize the path from the previous middleware in order
|
|
5
|
+
# to make it work for the renderer.
|
|
6
|
+
#
|
|
7
|
+
class Path < Middleware
|
|
8
|
+
|
|
9
|
+
def call(env)
|
|
10
|
+
self.set_accessors(env)
|
|
11
|
+
|
|
12
|
+
self.set_path!(env)
|
|
13
|
+
|
|
14
|
+
app.call(env)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
protected
|
|
18
|
+
|
|
19
|
+
def set_path!(env)
|
|
20
|
+
path = env['PATH_INFO'].clone
|
|
21
|
+
|
|
22
|
+
path.gsub!(/\.[a-zA-Z][a-zA-Z0-9]{2,}$/, '')
|
|
23
|
+
path.gsub!(/^\//, '')
|
|
24
|
+
path.gsub!(/^[A-Z]:\//, '')
|
|
25
|
+
|
|
26
|
+
path = 'index' if path.blank?
|
|
27
|
+
|
|
28
|
+
env['builder.path'] = path
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
module Locomotive::Builder
|
|
2
|
+
class Server
|
|
3
|
+
|
|
4
|
+
class Renderer < Middleware
|
|
5
|
+
|
|
6
|
+
def call(env)
|
|
7
|
+
self.set_accessors(env)
|
|
8
|
+
|
|
9
|
+
puts "[Builder|Renderer] page = #{page.inspect}"
|
|
10
|
+
|
|
11
|
+
if self.page
|
|
12
|
+
if self.page.redirect?
|
|
13
|
+
[self.page.redirect_type, { 'Location' => self.page.redirect_url, 'Content-Type' => 'text/html' }, []]
|
|
14
|
+
else
|
|
15
|
+
type = self.page.response_type || 'text/html'
|
|
16
|
+
html = self.render
|
|
17
|
+
|
|
18
|
+
[200, { 'Content-Type' => type }, [html]]
|
|
19
|
+
end
|
|
20
|
+
else
|
|
21
|
+
# no page at all, even not the 404 page
|
|
22
|
+
[404, { 'Content-Type' => 'text/html' }, ['Page not found']]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
protected
|
|
27
|
+
|
|
28
|
+
def render
|
|
29
|
+
context = self.locomotive_context
|
|
30
|
+
|
|
31
|
+
template = ::Liquid::Template.parse(self.page.source, {
|
|
32
|
+
page: self.page,
|
|
33
|
+
mounting_point: self.mounting_point
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
template.render(context)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Build the Liquid context used to render the Locomotive page. It
|
|
40
|
+
# stores both assigns and registers.
|
|
41
|
+
#
|
|
42
|
+
# @param [ Hash ] other_assigns Assigns coming for instance from the controler (optional)
|
|
43
|
+
#
|
|
44
|
+
# @return [ Object ] A new instance of the Liquid::Context class.
|
|
45
|
+
#
|
|
46
|
+
def locomotive_context(other_assigns = {})
|
|
47
|
+
assigns = self.locomotive_default_assigns
|
|
48
|
+
|
|
49
|
+
# assigns from other middlewares
|
|
50
|
+
assigns.merge!(self.liquid_assigns)
|
|
51
|
+
|
|
52
|
+
assigns.merge!(other_assigns)
|
|
53
|
+
|
|
54
|
+
# templatized page
|
|
55
|
+
if self.page && self.content_entry
|
|
56
|
+
['content_entry', 'entry', self.page.content_type.slug.singularize].each do |key|
|
|
57
|
+
assigns[key] = self.content_entry
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Tip: switch from false to true to enable the re-thrown exception flag
|
|
62
|
+
::Liquid::Context.new({}, assigns, self.locomotive_default_registers, true)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Return the default Liquid assigns used inside the Locomotive Liquid context
|
|
66
|
+
#
|
|
67
|
+
# @return [ Hash ] The default liquid assigns object
|
|
68
|
+
#
|
|
69
|
+
def locomotive_default_assigns
|
|
70
|
+
{
|
|
71
|
+
'site' => self.site.to_liquid,
|
|
72
|
+
'page' => self.page,
|
|
73
|
+
'models' => Locomotive::Builder::Liquid::Drops::ContentTypes.new,
|
|
74
|
+
'contents' => Locomotive::Builder::Liquid::Drops::ContentTypes.new,
|
|
75
|
+
'current_page' => self.params[:page],
|
|
76
|
+
'params' => self.params,
|
|
77
|
+
'path' => self.request.path,
|
|
78
|
+
'fullpath' => self.request.fullpath,
|
|
79
|
+
'url' => self.request.url,
|
|
80
|
+
'now' => Time.now.utc,
|
|
81
|
+
'today' => Date.today,
|
|
82
|
+
'locale' => I18n.locale.to_s,
|
|
83
|
+
'default_locale' => self.mounting_point.default_locale.to_s,
|
|
84
|
+
'locales' => self.mounting_point.locales.map(&:to_s),
|
|
85
|
+
'current_user' => {}
|
|
86
|
+
}
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Return the default Liquid registers used inside the Locomotive Liquid context
|
|
90
|
+
#
|
|
91
|
+
# @return [ Hash ] The default liquid registers object
|
|
92
|
+
#
|
|
93
|
+
def locomotive_default_registers
|
|
94
|
+
{
|
|
95
|
+
site: self.site,
|
|
96
|
+
page: self.page,
|
|
97
|
+
mounting_point: self.mounting_point,
|
|
98
|
+
inline_editor: false
|
|
99
|
+
}
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Locomotive::Builder
|
|
2
|
+
class Server
|
|
3
|
+
|
|
4
|
+
class TemplatizedPage < Middleware
|
|
5
|
+
|
|
6
|
+
def call(env)
|
|
7
|
+
self.set_accessors(env)
|
|
8
|
+
|
|
9
|
+
if self.page && self.page.templatized?
|
|
10
|
+
self.set_content_entry!(env)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
app.call(env)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
protected
|
|
17
|
+
|
|
18
|
+
def set_content_entry!(env)
|
|
19
|
+
%r(^#{self.page.safe_fullpath.gsub('*', '([^\/]+)')}$) =~ self.path
|
|
20
|
+
|
|
21
|
+
permalink = $1
|
|
22
|
+
|
|
23
|
+
if content_entry = self.page.content_type.find_entry(permalink)
|
|
24
|
+
env['builder.content_entry'] = content_entry
|
|
25
|
+
else
|
|
26
|
+
env['builder.page'] = nil
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'rack/showexceptions'
|
|
2
|
+
require 'coffee_script'
|
|
3
|
+
|
|
4
|
+
require 'locomotive/builder/listen'
|
|
5
|
+
require 'locomotive/builder/server/middleware'
|
|
6
|
+
require 'locomotive/builder/server/favicon'
|
|
7
|
+
require 'locomotive/builder/server/dynamic_assets'
|
|
8
|
+
require 'locomotive/builder/server/entry_submission'
|
|
9
|
+
require 'locomotive/builder/server/path'
|
|
10
|
+
require 'locomotive/builder/server/locale'
|
|
11
|
+
require 'locomotive/builder/server/page'
|
|
12
|
+
require 'locomotive/builder/server/templatized_page'
|
|
13
|
+
require 'locomotive/builder/server/not_found'
|
|
14
|
+
require 'locomotive/builder/server/renderer'
|
|
15
|
+
|
|
16
|
+
require 'locomotive/builder/liquid'
|
|
17
|
+
require 'locomotive/builder/misc'
|
|
18
|
+
|
|
19
|
+
module Locomotive::Builder
|
|
20
|
+
class Server
|
|
21
|
+
|
|
22
|
+
def initialize(reader, options = {})
|
|
23
|
+
Locomotive::Builder::Dragonfly.setup!(reader.mounting_point.path)
|
|
24
|
+
|
|
25
|
+
@reader = reader
|
|
26
|
+
@app = self.create_rack_app(@reader)
|
|
27
|
+
|
|
28
|
+
unless options[:disable_listen]
|
|
29
|
+
Locomotive::Builder::Listen.instance.start(@reader)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def call(env)
|
|
34
|
+
env['builder.mounting_point'] = @reader.mounting_point
|
|
35
|
+
@app.call(env)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
protected
|
|
39
|
+
|
|
40
|
+
def create_rack_app(reader)
|
|
41
|
+
Rack::Builder.new do
|
|
42
|
+
use Rack::ShowExceptions
|
|
43
|
+
use Rack::Lint
|
|
44
|
+
|
|
45
|
+
use Rack::Session::Cookie, {
|
|
46
|
+
key: 'rack.session',
|
|
47
|
+
domain: '0.0.0.0',
|
|
48
|
+
path: '/',
|
|
49
|
+
expire_after: 2592000,
|
|
50
|
+
secret: 'uselessinlocal'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
use ::Dragonfly::Middleware, :images
|
|
54
|
+
|
|
55
|
+
use Rack::Static, {
|
|
56
|
+
urls: ['/images', '/fonts', '/samples'],
|
|
57
|
+
root: File.join(reader.mounting_point.path, 'public')
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
use Favicon
|
|
61
|
+
use DynamicAssets
|
|
62
|
+
|
|
63
|
+
use EntrySubmission
|
|
64
|
+
|
|
65
|
+
use Path
|
|
66
|
+
use Locale
|
|
67
|
+
|
|
68
|
+
use Page
|
|
69
|
+
use TemplatizedPage
|
|
70
|
+
use NotFound
|
|
71
|
+
use Renderer
|
|
72
|
+
|
|
73
|
+
run Renderer.new
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require "locomotive/builder/server"
|
|
2
|
+
$:.unshift(File.expand_path(File.dirname(__FILE__) + '/../..'))
|
|
3
|
+
|
|
4
|
+
require 'locomotive/builder/version'
|
|
5
|
+
require 'locomotive/builder/exceptions'
|
|
6
|
+
require 'locomotive/mounter'
|
|
7
|
+
|
|
8
|
+
module Locomotive
|
|
9
|
+
module Builder
|
|
10
|
+
class StandaloneServer < Server
|
|
11
|
+
|
|
12
|
+
def initialize(path)
|
|
13
|
+
# setting the logger
|
|
14
|
+
logfile = File.join(path, 'log', 'mounter.log')
|
|
15
|
+
FileUtils.mkdir_p(File.dirname(logfile))
|
|
16
|
+
|
|
17
|
+
Locomotive::Mounter.logger = ::Logger.new(logfile).tap do |log|
|
|
18
|
+
log.level = Logger::DEBUG
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# get the reader
|
|
22
|
+
reader = Locomotive::Mounter::Reader::FileSystem.instance
|
|
23
|
+
reader.run!(path: path)
|
|
24
|
+
reader
|
|
25
|
+
|
|
26
|
+
# run the rack app
|
|
27
|
+
Bundler.require 'misc'
|
|
28
|
+
|
|
29
|
+
super(reader, disable_listen: true)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|