locomotivecms_steam 0.1.1 → 0.1.2.pre.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -2
  3. data/CHANGELOG.md +5 -0
  4. data/Gemfile +10 -2
  5. data/Gemfile.lock +37 -49
  6. data/Rakefile +5 -10
  7. data/example/server.rb +10 -6
  8. data/lib/locomotive/steam.rb +46 -0
  9. data/lib/locomotive/steam/configuration.rb +13 -0
  10. data/lib/locomotive/steam/decorators.rb +1 -0
  11. data/lib/locomotive/steam/decorators/page_decorator.rb +50 -0
  12. data/lib/locomotive/steam/entities/content_type.rb +11 -0
  13. data/lib/locomotive/steam/entities/page.rb +136 -0
  14. data/lib/locomotive/steam/entities/site.rb +30 -0
  15. data/lib/locomotive/steam/initializers/dragonfly.rb +3 -4
  16. data/lib/locomotive/steam/liquid.rb +1 -12
  17. data/lib/locomotive/steam/liquid/drops/base.rb +1 -1
  18. data/lib/locomotive/steam/liquid/drops/content_entry.rb +3 -2
  19. data/lib/locomotive/steam/liquid/drops/content_types.rb +4 -2
  20. data/lib/locomotive/steam/liquid/drops/page.rb +4 -3
  21. data/lib/locomotive/steam/liquid/drops/site.rb +3 -2
  22. data/lib/locomotive/steam/liquid/patches.rb +4 -8
  23. data/lib/locomotive/steam/liquid/tags/nav.rb +19 -17
  24. data/lib/locomotive/steam/loaders/yml/pages_loader.rb +193 -0
  25. data/lib/locomotive/steam/loaders/yml/site_loader.rb +49 -0
  26. data/lib/locomotive/steam/loaders/yml/utils/localized_tree.rb +33 -0
  27. data/lib/locomotive/steam/loaders/yml/utils/yaml_front_matters_template.rb +66 -0
  28. data/lib/locomotive/steam/loaders/yml_loader.rb +33 -0
  29. data/lib/locomotive/steam/mapper.rb +86 -0
  30. data/lib/locomotive/steam/middlewares/base.rb +12 -10
  31. data/lib/locomotive/steam/middlewares/locale.rb +3 -4
  32. data/lib/locomotive/steam/middlewares/page.rb +18 -18
  33. data/lib/locomotive/steam/middlewares/renderer.rb +41 -15
  34. data/lib/locomotive/steam/middlewares/stack.rb +1 -1
  35. data/lib/locomotive/steam/monkey_patches.rb +1 -2
  36. data/lib/locomotive/steam/monkey_patches/haml.rb +1 -1
  37. data/lib/locomotive/steam/repositories/content_types_repository.rb +14 -0
  38. data/lib/locomotive/steam/repositories/pages_repository.rb +23 -0
  39. data/lib/locomotive/steam/repositories/sites_repository.rb +16 -0
  40. data/lib/locomotive/steam/server.rb +14 -11
  41. data/lib/locomotive/steam/services/external_api.rb +2 -1
  42. data/lib/locomotive/steam/services/markdown.rb +3 -12
  43. data/lib/locomotive/steam/standalone_server.rb +2 -2
  44. data/lib/locomotive/steam/version.rb +4 -1
  45. data/locomotivecms_steam.gemspec +11 -5
  46. data/spec/fixtures/default/app/views/pages/basic.liquid.haml +13 -0
  47. data/spec/fixtures/default/config/site.yml +2 -2
  48. data/spec/integration/server/basic_spec.rb +22 -17
  49. data/spec/integration/server/contact_form_spec.rb +1 -1
  50. data/spec/integration/server/liquid_spec.rb +2 -2
  51. data/spec/integration/server/with_scope_spec.rb +2 -2
  52. data/spec/spec_helper.rb +15 -4
  53. data/spec/support/helpers.rb +26 -8
  54. data/spec/unit/decorators/page_decorator_spec.rb +55 -0
  55. data/spec/unit/entities/page_spec.rb +50 -0
  56. data/spec/unit/entities/site_spec.rb +12 -0
  57. data/spec/unit/liquid/tags/nav_spec.rb +159 -0
  58. data/spec/unit/loaders/pages_loader_spec.rb +42 -0
  59. data/spec/unit/loaders/site_loader_spec.rb +21 -0
  60. data/spec/unit/loaders/utils/localized_tree_spec.rb +33 -0
  61. data/spec/unit/loaders/utils/yaml_front_matters_template_spec.rb +39 -0
  62. data/spec/unit/middlewares/base_spec.rb +20 -0
  63. data/spec/unit/middlewares/page_spec.rb +51 -0
  64. data/spec/unit/repositories/pages_spec.rb +11 -0
  65. metadata +128 -23
  66. data/bin/publish +0 -28
  67. data/lib/locomotive/steam/misc.rb +0 -10
  68. data/lib/locomotive/steam/monkey_patches/mounter.rb +0 -54
  69. data/lib/steam.rb +0 -3
@@ -0,0 +1,49 @@
1
+ module Locomotive
2
+ module Steam
3
+ module Loader
4
+ module Yml
5
+ class SiteLoader
6
+ def initialize(path, mapper)
7
+ @root_path = path
8
+ @path = File.join(@root_path, 'config', 'site.yml')
9
+ @mapper = mapper
10
+ end
11
+
12
+ def load!
13
+ entity_class = @mapper.collection(:sites).entity
14
+ repository = @mapper.collection(:sites).repository
15
+ all.each do |site_hash|
16
+ site = entity_class.new(site_hash)
17
+ repository.create site
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def all
24
+ attributes = load_attributes
25
+ (attributes['domains'] ||= []) << '0.0.0.0'
26
+ %w{seo_title meta_keywords meta_description}.each do |field|
27
+ attributes[field] = to_locale(attributes[field], attributes['locales'].first)
28
+ end
29
+ [attributes]
30
+ end
31
+
32
+ def to_locale(field, default)
33
+ return field if field.respond_to?(:[]) && field[default]
34
+ { "#{default}" => field }
35
+ end
36
+
37
+ def load_attributes
38
+ if File.exists?(@path)
39
+ file = File.read(@path).force_encoding('utf-8')
40
+ YAML::load(file)
41
+ else
42
+ raise "#{@path} was not found"
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,33 @@
1
+ module Locomotive
2
+ module Steam
3
+ module Utils
4
+ class LocalizedTree
5
+
6
+ def initialize(entries, extensions)
7
+ @entries = entries
8
+ @extensions = extensions
9
+ end
10
+
11
+ def to_hash
12
+ group_by(locale_regexp)
13
+ end
14
+
15
+
16
+ private
17
+
18
+ def group_by(regexp)
19
+ @entries.each_with_object({}) do |entry, hsh|
20
+ file, key, subkey, *_ = regexp.match(entry).to_a
21
+ next unless file
22
+ (hsh[key] ||= {})[subkey.try(:to_sym) || :default] = file
23
+ end
24
+ end
25
+
26
+ def locale_regexp
27
+ /\A(.+?)(?:\.(.{2})){0,1}\.(?:(#{@extensions.join('|')})\.*)+\Z/
28
+ end
29
+
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,66 @@
1
+ module Locomotive
2
+ module Steam
3
+ module Utils
4
+
5
+ # YAML Front-matters for HAML/Liquid templates
6
+ class YAMLFrontMattersTemplate
7
+
8
+ attr_reader :filepath
9
+
10
+ def initialize(filepath)
11
+ @filepath = filepath
12
+ @line_offset = 0
13
+ @parsed = false
14
+ end
15
+
16
+ def attributes
17
+ self.fetch_attributes_and_raw_source
18
+ @attributes
19
+ end
20
+
21
+ def raw_source
22
+ self.fetch_attributes_and_raw_source
23
+ @raw_source
24
+ end
25
+
26
+ def line_offset
27
+ self.fetch_attributes_and_raw_source
28
+ @line_offset
29
+ end
30
+
31
+ def source
32
+ self.fetch_attributes_and_raw_source
33
+ return @source if @source
34
+
35
+ @source = if self.filepath.ends_with?('.haml')
36
+ Haml::Engine.new(self.raw_source).render
37
+ else
38
+ self.raw_source
39
+ end
40
+ end
41
+
42
+ def data
43
+ @data ||= File.read(filepath)
44
+ end
45
+
46
+ protected
47
+ def parsed?
48
+ @parsed
49
+ end
50
+ def fetch_attributes_and_raw_source
51
+ return if @parsed
52
+ if data =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)(.*)/m
53
+ @line_offset = $1.count("\n") + 1
54
+ @attributes = YAML.load($1)
55
+ @raw_source = $3
56
+ else
57
+ @attributes = {}
58
+ @raw_source = data
59
+ end
60
+ @raw_source.force_encoding('utf-8')
61
+ @parsed = true
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,33 @@
1
+ require_relative 'yml/site_loader'
2
+ require_relative 'yml/pages_loader'
3
+ require_relative 'yml/utils/yaml_front_matters_template'
4
+ require_relative 'yml/utils/localized_tree'
5
+
6
+ module Locomotive
7
+ module Steam
8
+ module Loader
9
+ class YmlLoader
10
+
11
+ MODELS = %W[site]
12
+
13
+ def initialize path, mapper
14
+ @root_path, @mapper = path, mapper
15
+ end
16
+
17
+ def load!
18
+ load_site!
19
+ load_pages!
20
+ end
21
+
22
+ def load_site!
23
+ Locomotive::Steam::Loader::Yml::SiteLoader.new(@root_path, @mapper).load!
24
+ end
25
+
26
+ def load_pages!
27
+ Locomotive::Steam::Loader::Yml::PagesLoader.new(@root_path, @mapper).load!
28
+ end
29
+
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,86 @@
1
+ Dir[File.dirname(__FILE__) + '/entities/*.rb'].each { |file| require file }
2
+ Dir[File.dirname(__FILE__) + '/repositories/*.rb'].each { |file| require file }
3
+
4
+ collection :sites do
5
+ entity Locomotive::Steam::Entities::Site
6
+ repository Locomotive::Steam::Repositories::SitesRepository
7
+
8
+ attribute :name
9
+ attribute :locales
10
+ attribute :subdomain
11
+ attribute :domains
12
+ attribute :seo_title, localized: true
13
+ attribute :meta_keywords, localized: true
14
+ attribute :meta_description, localized: true
15
+ attribute :robots_txt
16
+ attribute :timezone
17
+
18
+
19
+ end
20
+
21
+ collection :pages do
22
+ entity Locomotive::Steam::Entities::Page
23
+ repository Locomotive::Steam::Repositories::PagesRepository
24
+
25
+ attribute :site, association: {type: :belongs_to, key: :site_id, name: :sites}
26
+ attribute :content_type, association: {type: :belongs_to, key: :content_type_id, name: :content_types}
27
+ attribute :parent, association: {type: :belongs_to, key: :parent_id, name: :pages}
28
+ attribute :children, association: {type: :has_many, key: :parent_id, name: :pages}
29
+ attribute :title, localized: true
30
+ attribute :slug, localized: true
31
+ attribute :fullpath, localized: true
32
+ attribute :redirect_url, localized: true
33
+ attribute :redirect_type, default: 301
34
+ attribute :template, localized: true
35
+ attribute :handle
36
+ attribute :listed, default: false
37
+ attribute :searchable
38
+ attribute :templatized, default: false
39
+ attribute :content_type
40
+ attribute :published, default: true
41
+ attribute :cache_strategy
42
+ attribute :response_type
43
+ attribute :position
44
+
45
+ attribute :seo_title, localized: true
46
+ attribute :meta_keywords, localized: true
47
+ attribute :meta_description, localized: true
48
+
49
+ attribute :editable_elements, type: :array, class_name: 'Locomotive::Mounter::Models::EditableElement'
50
+
51
+ end
52
+
53
+ collection :content_types do
54
+ entity Locomotive::Steam::Entities::ContentType
55
+ repository Locomotive::Steam::Repositories::ContentTypesRepository
56
+ attribute :slug
57
+ attribute :site, association: {type: :belongs_to, key: :site_id, name: :sites}
58
+ end
59
+
60
+ collection :content_entries do
61
+
62
+ end
63
+
64
+ collection :content_fields do
65
+
66
+ end
67
+
68
+ collection :content_select_options do
69
+
70
+ end
71
+
72
+ collection :editable_elements do
73
+
74
+ end
75
+
76
+ collection :snippets do
77
+
78
+ end
79
+
80
+ collection :theme_assets do
81
+
82
+ end
83
+
84
+ collection :translations do
85
+
86
+ end
@@ -5,33 +5,35 @@ module Locomotive::Steam
5
5
 
6
6
  attr_accessor :app, :request, :path
7
7
  attr_accessor :liquid_assigns, :services
8
- attr_accessor :mounting_point, :page, :content_entry
8
+ attr_accessor :site, :page, :content_entry, :locale
9
9
 
10
10
  def initialize(app = nil)
11
11
  @app = app
12
12
  end
13
13
 
14
14
  def call(env)
15
- dup._call(env) # thread-safe purpose
15
+ if Locomotive::Steam.mode == :test
16
+ _call(env)
17
+ else
18
+ dup._call(env) # thread-safe purpose
19
+ end
16
20
  end
17
21
 
18
22
  def _call(env)
23
+ code, headers, response = @app.call(env)
19
24
  self.set_accessors(env)
25
+ [code, headers, [response]]
20
26
  end
21
27
 
22
28
  protected
23
29
 
24
30
  def set_accessors(env)
25
- %w(path request mounting_point page content_entry services).each do |name|
26
- self.send(:"#{name}=", env["steam.#{name}"])
31
+ %w(path site request page content_entry services locale).each do |name|
32
+ self.send(:"#{name}=", env.fetch("steam.#{name}", nil))
27
33
  end
28
34
 
29
35
  env['steam.liquid_assigns'] ||= {}
30
- self.liquid_assigns = env['steam.liquid_assigns']
31
- end
32
-
33
- def site
34
- self.mounting_point.site
36
+ self.liquid_assigns = env.fetch('steam.liquid_assigns')
35
37
  end
36
38
 
37
39
  def params
@@ -60,4 +62,4 @@ module Locomotive::Steam
60
62
  end
61
63
 
62
64
  end
63
- end
65
+ end
@@ -20,15 +20,14 @@ module Locomotive::Steam
20
20
  protected
21
21
 
22
22
  def set_locale!(env)
23
- locale = self.mounting_point.default_locale
23
+ locale = site.default_locale
24
24
 
25
- if self.path =~ /^(#{self.mounting_point.locales.join('|')})+(\/|$)/
25
+ if self.path =~ /^(#{self.site.locales.join('|')})+(\/|$)/
26
26
  locale = $1
27
27
  self.path = self.path.gsub($1 + $2, '')
28
28
  self.path = 'index' if self.path.blank?
29
29
  end
30
30
 
31
- Locomotive::Mounter.locale = locale
32
31
  ::I18n.locale = locale
33
32
 
34
33
  self.log "Detecting locale #{locale.upcase}"
@@ -39,4 +38,4 @@ module Locomotive::Steam
39
38
 
40
39
  end
41
40
  end
42
- end
41
+ end
@@ -8,37 +8,38 @@ module Locomotive::Steam
8
8
 
9
9
  def _call(env)
10
10
  super
11
-
12
- self.set_page!(env)
13
-
11
+ set_page!(env)
14
12
  app.call(env)
15
13
  end
16
14
 
17
15
  protected
18
16
 
19
17
  def set_page!(env)
20
- page = self.fetch_page
21
-
18
+ page = fetch_page env['steam.locale']
22
19
  if page
23
- self.log "Found page \"#{page.title}\" [#{page.safe_fullpath}]"
20
+ log "Found page \"#{page.title}\" [#{page.fullpath}]"
24
21
  end
25
22
 
26
23
  env['steam.page'] = page
27
24
  end
28
25
 
29
- def fetch_page
30
- matchers = self.path_combinations(self.path)
31
-
32
- pages = self.mounting_point.pages.values.find_all do |_page|
33
- matchers.include?(_page.safe_fullpath) ||
34
- matchers.include?(_page.safe_fullpath.try(:underscore))
35
- end.sort_by { |p| p.position || Float::INFINITY }
36
-
37
- if pages.size > 1
38
- self.log "Found multiple pages: #{pages.collect(&:title).join(', ')}"
26
+ def fetch_page locale
27
+ decorated(locale) do
28
+ Locomotive::Models[:pages].current_locale = locale
29
+ Locomotive::Models[:pages].matching_paths(path_combinations(path)).tap do |pages|
30
+ if pages.size > 1
31
+ self.log "Found multiple pages: #{pages.all.collect(&:title).join(', ')}"
32
+ end
33
+ end.first
39
34
  end
35
+ end
40
36
 
41
- pages.first
37
+ def decorated(locale)
38
+ entity = yield
39
+ unless entity.nil?
40
+ Locomotive::Steam::Decorators::PageDecorator.new(
41
+ Locomotive::Decorators::I18nDecorator.new(entity, locale))
42
+ end
42
43
  end
43
44
 
44
45
  def path_combinations(path)
@@ -47,7 +48,6 @@ module Locomotive::Steam
47
48
 
48
49
  def _path_combinations(segments, can_include_template = true)
49
50
  return nil if segments.empty?
50
-
51
51
  segment = segments.shift
52
52
 
53
53
  (can_include_template ? [segment, '*'] : [segment]).map do |_segment|
@@ -6,19 +6,19 @@ module Locomotive::Steam
6
6
  def _call(env)
7
7
  super
8
8
 
9
- if self.page
10
- if self.page.redirect?
11
- self.redirect_to(self.page.redirect_url, self.page.redirect_type)
9
+ if page
10
+ if page.redirect?
11
+ redirect_to(page.redirect_url, page.redirect_type)
12
12
  else
13
- type = self.page.response_type || 'text/html'
14
- html = self.render_page
13
+ type = page.response_type || 'text/html'
14
+ html = render_page
15
15
 
16
- self.log 'Rendered liquid page template'
16
+ log 'Rendered liquid page template'
17
17
 
18
18
  [200, { 'Content-Type' => type }, [html]]
19
19
  end
20
20
  else
21
- [404, { 'Content-Type' => 'text/html' }, [self.render_404]]
21
+ [404, { 'Content-Type' => 'text/html' }, [render_404]]
22
22
  end
23
23
  end
24
24
 
@@ -26,15 +26,42 @@ module Locomotive::Steam
26
26
 
27
27
  def render_page
28
28
  context = self.locomotive_context
29
+ # begin
30
+ # binding.pry
31
+ render(page, context)
32
+ # rescue Exception => e
33
+
34
+ # raise RendererException.new(e, self.page.title, self.page.template, context)
35
+ # end
36
+ end
37
+
38
+ def render(page, context)
39
+ parse(page, context).render(context)
40
+ end
41
+
42
+ protected
43
+
44
+ def parse(page, context)
45
+
46
+ options = {
47
+ page: page,
48
+ mapper: context.registers[:mapper],
49
+ error_mode: :strict,
50
+ count_lines: true
51
+ }
52
+
29
53
  begin
30
- self.page.render(context)
31
- rescue Exception => e
32
- raise RendererException.new(e, self.page.title, self.page.template, context)
54
+ ::Liquid::Template.parse(page.source(I18n.locale), options)
55
+ rescue ::Liquid::SyntaxError
56
+ # do it again on the raw source instead so that the error line matches
57
+ # the source file.
58
+ ::Liquid::Template.parse(self.template.raw_source, options)
33
59
  end
34
60
  end
35
61
 
62
+
36
63
  def render_404
37
- if self.page = self.mounting_point.pages['404']
64
+ if self.page = Locomotive::Models[:pages]['404']
38
65
  self.render_page
39
66
  else
40
67
  'Page not found'
@@ -88,8 +115,8 @@ module Locomotive::Steam
88
115
  'now' => Time.zone.now,
89
116
  'today' => Date.today,
90
117
  'locale' => I18n.locale.to_s,
91
- 'default_locale' => self.mounting_point.default_locale.to_s,
92
- 'locales' => self.mounting_point.locales.map(&:to_s),
118
+ 'default_locale' => self.site.default_locale.to_s,
119
+ 'locales' => self.site.locales.map(&:to_s),
93
120
  'current_user' => {},
94
121
  'session' => Locomotive::Steam::Liquid::Drops::SessionProxy.new,
95
122
  'steam' => true,
@@ -106,7 +133,6 @@ module Locomotive::Steam
106
133
  request: self.request,
107
134
  site: self.site,
108
135
  page: self.page,
109
- mounting_point: self.mounting_point,
110
136
  services: self.services,
111
137
  inline_editor: false,
112
138
  logger: Locomotive::Common::Logger
@@ -116,4 +142,4 @@ module Locomotive::Steam
116
142
  end
117
143
 
118
144
  end
119
- end
145
+ end