get the liquid source of a page (do not parse and render yet)
did
committed Feb 11, 2015
commit b86f1d8c63c341b8eadf102e44b7ad43792e5d61
Showing 16
changed files with
241 additions
and 229 deletions
locomotive/steam/decorators.rb b/lib/locomotive/steam/decorators.rb
+1
-0
| @@ | @@ -1 +1,2 @@ |
| require_relative 'decorators/i18n_decorator' | |
| + | require_relative 'decorators/page_decorator' |
locomotive/steam/decorators/i18n_decorator.rb b/lib/locomotive/steam/decorators/i18n_decorator.rb
+14
-1
| @@ | @@ -10,7 +10,7 @@ module Locomotive |
| attr_reader :__default_locale__ | |
| def initialize(object, attributes, locale = nil, default_locale = nil) | |
| - | self.__localized_attributes__ = attributes |
| + | self.__localized_attributes__ = attributes || (object.respond_to?(:localized_attributes) ? object.localized_attributes : []) |
| self.__frozen_locale__ = false | |
| self.__locale__ = locale | |
| self.__default_locale__ = default_locale | |
| @@ | @@ -18,6 +18,18 @@ module Locomotive |
| super(object) | |
| end | |
| + | class << self |
| + | |
| + | def decorate(object_or_list, attributes = nil, locale = nil, default_locale = nil) |
| + | decorated = [[object_or_list]].flatten.map do |object| |
| + | new(object, attributes, locale, default_locale) |
| + | end |
| + | |
| + | object_or_list.respond_to?(:attributes) ? decorated.first : decorated |
| + | end |
| + | |
| + | end |
| + | |
| def __locale__=(locale) | |
| unless self.__frozen_locale__ | |
| @__locale__ = locale.try(:to_sym) | |
| @@ | @@ -46,6 +58,7 @@ module Locomotive |
| end | |
| def method_missing(name, *args, &block) | |
| + | # DEBUG: ::Object.send(:puts, "[#{name}] with #{args.inspect}") |
| if __localized_attributes__.include?(name.to_sym) | |
| field = __getobj__.public_send(:attributes)[name.to_sym] | |
| field[__locale__] || field[__default_locale__] || super | |
locomotive/steam/decorators/page_decorator.rb b/lib/locomotive/steam/decorators/page_decorator.rb
+7
-37
| @@ | @@ -1,48 +1,18 @@ |
| module Locomotive | |
| module Steam | |
| module Decorators | |
| - | class PageDecorator < SimpleDelegator |
| + | class PageDecorator < I18nDecorator |
| - | # Return the fullpath dasherized and with the "*" character |
| - | # for the slug of templatized page. |
| - | # |
| - | # @return [ hash ] The safe full paths |
| - | # |
| - | def safe_fullpath |
| - | if index_or_404? |
| - | slug[current_locale] |
| + | def source |
| + | source = File.open(template_path).read.force_encoding('utf-8') |
| + | |
| + | if match = source.match(/^((---\s*\n.*?\n?)^(---\s*$\n?))?(?<template>.*)/m) |
| + | match[:template] |
| else | |
| - | base = parent.safe_fullpath |
| - | _slug = if templatized? && !templatized_from_parent |
| - | '*' |
| - | else |
| - | slug[current_locale] |
| - | end |
| - | (base == 'index' ? _slug : File.join(base, _slug)).dasherize |
| + | source |
| end | |
| end | |
| - | def parent |
| - | Locomotive::Steam::Decorators::PageDecorator.new( |
| - | Locomotive::Decorators::I18nDecorator.new( |
| - | __getobj__.parent, current_locale |
| - | ) |
| - | ) |
| - | end |
| - | |
| - | # Return the Liquid template based on the raw_template property |
| - | # of the page. If the template is HAML or SLIM, then a pre-rendering to Liquid is done. |
| - | # |
| - | # @return [ String ] The liquid template or nil if not template has been provided |
| - | # |
| - | def source(locale) |
| - | @source ||= self.template[locale].source |
| - | end |
| - | |
| - | def to_liquid |
| - | ::Locomotive::Steam::Liquid::Drops::Page.new(self) |
| - | end |
| - | |
| end | |
| end | |
| end | |
locomotive/steam/liquid/drops/i18n_base.rb b/lib/locomotive/steam/liquid/drops/i18n_base.rb
+1
-1
| @@ | @@ -4,7 +4,7 @@ module Locomotive |
| module Drops | |
| class I18nBase < Base | |
| - | def initialize(source, localized_attributes = []) |
| + | def initialize(source, localized_attributes = nil) |
| decorated = source if source.respond_to?(:__locale__) | |
| decorated ||= Locomotive::Steam::Decorators::I18nDecorator.new(source, localized_attributes) | |
| super(decorated) | |
locomotive/steam/middlewares/default_env.rb b/lib/locomotive/steam/middlewares/default_env.rb
+3
-7
| @@ | @@ -4,14 +4,10 @@ module Locomotive::Steam |
| class DefaultEnv < Struct.new(:app, :options) | |
| def call(env) | |
| - | # time = Benchmark.realtime do |
| - | request = Rack::Request.new(env) |
| + | request = Rack::Request.new(env) |
| - | env['steam.request'] = request |
| - | env['steam.services'] = Locomotive::Steam::Services.build_instance(request, options) |
| - | # end |
| - | |
| - | # puts "[Benchmark][DefaultEnv] Time elapsed #{time*1000} milliseconds" |
| + | env['steam.request'] = request |
| + | env['steam.services'] = Locomotive::Steam::Services.build_instance(request, options) |
| app.call(env) | |
| end | |
locomotive/steam/middlewares/helpers.rb b/lib/locomotive/steam/middlewares/helpers.rb
+4
-0
| @@ | @@ -13,6 +13,10 @@ module Locomotive::Steam |
| self.request.content_type == 'application/json' || File.extname(self.request.path) == '.json' | |
| end | |
| + | def render_response(content, code = 200, type = 'text/html') |
| + | @next_response = [code, { 'Content-Type' => type }, [content]] |
| + | end |
| + | |
| def redirect_to(location, type = 301) | |
| self.log "Redirected to #{location}" | |
| [type, { 'Content-Type' => 'text/html', 'Location' => location }, []] | |
locomotive/steam/middlewares/page.rb b/lib/locomotive/steam/middlewares/page.rb
+10
-39
| @@ | @@ -10,7 +10,11 @@ module Locomotive::Steam |
| def _call | |
| if page = fetch_page | |
| - | log "Found page \"#{page.title}\" [#{page.fullpath}]" |
| + | if !page.not_found? |
| + | log "Found page \"#{page.title}\" [#{page.fullpath}]" |
| + | else |
| + | log "Page not found, rendering the 404 page.".red |
| + | end |
| end | |
| env['steam.page'] = page | |
| @@ | @@ -19,46 +23,13 @@ module Locomotive::Steam |
| protected | |
| def fetch_page | |
| - | if (pages = services.page_finder.find(path)).size > 1 |
| - | titles = pages.map { |p| p.attributes[:title][repository.current_locale] } |
| - | self.log "Found multiple pages: #{titles.join(', ')}" |
| - | end |
| - | |
| - | if page = pages.first |
| - | Locomotive::Steam::Decorators::I18nDecorator.new(page, page.localized_attributes, locale, default_locale) |
| - | else |
| - | nil |
| - | end |
| - | |
| - | # if page = services.page_finder.find(path) |
| - | # puts page.inspect |
| - | # Locomotive::Steam::Decorators::I18nDecorator.new(page, page.localized_attributes, locale, site.default_locale) |
| - | # else |
| - | # nil |
| - | # end |
| - | |
| - | # decorated(locale) do |
| - | # Locomotive::Models[:pages].current_locale = locale |
| - | # Locomotive::Models[:pages].matching_paths(path_combinations(path)).tap do |pages| |
| - | # if pages.size > 1 |
| - | # self.log "Found multiple pages: #{pages.all.collect(&:title).join(', ')}" |
| - | # end |
| - | # end.first |
| - | # end |
| + | services.page_finder.match(path).tap do |pages| |
| + | if pages.size > 1 |
| + | self.log "Found multiple pages: #{pages.map(&:title).join(', ')}" |
| + | end |
| + | end.first || services.page_finder.find('404') |
| end | |
| - | # def repository |
| - | # services.repositories.page |
| - | # end |
| - | |
| - | # def decorated(locale) |
| - | # entity = yield |
| - | # unless entity.nil? |
| - | # # Locomotive::Steam::Decorators::PageDecorator.new( |
| - | # # Locomotive::Decorators::I18nDecorator.new(entity, locale)) |
| - | # end |
| - | # end |
| - | |
| end | |
| end | |
locomotive/steam/middlewares/renderer.rb b/lib/locomotive/steam/middlewares/renderer.rb
+157
-132
| @@ | @@ -1,19 +1,44 @@ |
| module Locomotive::Steam | |
| module Middlewares | |
| - | class Renderer |
| + | class Renderer < ThreadSafe |
| - | def call(env) |
| - | response = nil |
| + | include Helpers |
| - | # time = Benchmark.realtime do |
| - | # puts "[Rendered] TODO" |
| - | # self.set_accessors(env) |
| - | response = [200, { 'Content-Type' => 'text/html' }, ['TODO']] |
| - | # end |
| + | def _call |
| + | if page |
| + | render_page |
| + | else |
| + | render_missing_404 |
| + | end |
| + | end |
| + | |
| + | private |
| + | |
| + | def render_page |
| + | content = parse_and_render_liquid |
| + | render_response(content, page.not_found? ? 404: 200) |
| + | end |
| + | |
| + | def render_missing_404 |
| + | render_response('Missing 404 page', 404) |
| + | end |
| + | |
| + | def parse_and_render_liquid |
| + | page.source.tap { |s| puts s.inspect } |
| + | end |
| - | # puts "[Benchmark][Renderer] Time elapsed #{time*1000} milliseconds" |
| - | response |
| + | |
| + | # response = nil |
| + | |
| + | # # time = Benchmark.realtime do |
| + | # # puts "[Rendered] TODO" |
| + | # # self.set_accessors(env) |
| + | # response = [200, { 'Content-Type' => 'text/html' }, ['TODO']] |
| + | # # end |
| + | |
| + | # # puts "[Benchmark][Renderer] Time elapsed #{time*1000} milliseconds" |
| + | # response |
| # if page | |
| # if page.redirect? | |
| @@ | @@ -29,128 +54,128 @@ module Locomotive::Steam |
| # else | |
| # [404, { 'Content-Type' => 'text/html' }, [render_404]] | |
| # end | |
| - | end |
| - | |
| - | def self.call(env) |
| - | raise 'TODO' |
| - | end |
| - | |
| - | protected |
| - | |
| - | def render_page |
| - | context = self.locomotive_context |
| - | # begin |
| - | # binding.pry |
| - | render(page, context) |
| - | # rescue Exception => e |
| - | |
| - | # raise RendererException.new(e, self.page.title, self.page.template, context) |
| - | # end |
| - | end |
| - | |
| - | def render(page, context) |
| - | parse(page, context).render(context) |
| - | end |
| - | |
| - | protected |
| - | |
| - | def parse(page, context) |
| - | |
| - | options = { |
| - | page: page, |
| - | mapper: context.registers[:mapper], |
| - | error_mode: :strict, |
| - | count_lines: true |
| - | } |
| - | |
| - | begin |
| - | ::Liquid::Template.parse(page.source(I18n.locale), options) |
| - | rescue ::Liquid::SyntaxError |
| - | # do it again on the raw source instead so that the error line matches |
| - | # the source file. |
| - | ::Liquid::Template.parse(self.template.raw_source, options) |
| - | end |
| - | end |
| - | |
| - | |
| - | def render_404 |
| - | if self.page = Locomotive::Models[:pages]['404'] |
| - | self.render_page |
| - | else |
| - | 'Page not found' |
| - | end |
| - | end |
| - | |
| - | # Build the Liquid context used to render the Locomotive page. It |
| - | # stores both assigns and registers. |
| - | # |
| - | # @param [ Hash ] other_assigns Assigns coming for instance from the controler (optional) |
| - | # |
| - | # @return [ Object ] A new instance of the Liquid::Context class. |
| - | # |
| - | def locomotive_context(other_assigns = {}) |
| - | assigns = self.locomotive_default_assigns |
| - | |
| - | # assigns from other middlewares |
| - | assigns.merge!(self.liquid_assigns) |
| - | |
| - | assigns.merge!(other_assigns) |
| - | |
| - | # templatized page |
| - | if self.page && self.content_entry |
| - | ['content_entry', 'entry', self.page.content_type.slug.singularize].each do |key| |
| - | assigns[key] = self.content_entry |
| - | end |
| - | end |
| - | |
| - | # Tip: switch from false to true to enable the re-thrown exception flag |
| - | ::Liquid::Context.new({}, assigns, self.locomotive_default_registers, true) |
| - | end |
| - | |
| - | # Return the default Liquid assigns used inside the Locomotive Liquid context |
| - | # |
| - | # @return [ Hash ] The default liquid assigns object |
| - | # |
| - | def locomotive_default_assigns |
| - | { |
| - | 'site' => self.site.to_liquid, |
| - | 'page' => self.page, |
| - | 'models' => Locomotive::Steam::Liquid::Drops::ContentTypes.new, |
| - | 'contents' => Locomotive::Steam::Liquid::Drops::ContentTypes.new, |
| - | 'current_page' => self.params[:page], |
| - | 'params' => self.params.stringify_keys, |
| - | 'path' => self.request.path, |
| - | 'fullpath' => self.request.fullpath, |
| - | 'url' => self.request.url, |
| - | 'ip_address' => self.request.ip, |
| - | 'post?' => self.request.post?, |
| - | 'host' => self.request.host_with_port, |
| - | 'now' => Time.zone.now, |
| - | 'today' => Date.today, |
| - | 'locale' => I18n.locale.to_s, |
| - | 'default_locale' => self.site.default_locale.to_s, |
| - | 'locales' => self.site.locales.map(&:to_s), |
| - | 'current_user' => {}, |
| - | 'session' => Locomotive::Steam::Liquid::Drops::SessionProxy.new, |
| - | 'steam' => true, |
| - | 'editing' => false |
| - | } |
| - | end |
| - | |
| - | # Return the default Liquid registers used inside the Locomotive Liquid context |
| - | # |
| - | # @return [ Hash ] The default liquid registers object |
| - | # |
| - | def locomotive_default_registers |
| - | { |
| - | request: self.request, |
| - | site: self.site, |
| - | page: self.page, |
| - | services: self.services, |
| - | inline_editor: false, |
| - | logger: Locomotive::Common::Logger |
| - | } |
| - | end |
| + | # end |
| + | |
| + | # def self.call(env) |
| + | # raise 'TODO' |
| + | # end |
| + | |
| + | # protected |
| + | |
| + | # def render_page |
| + | # context = self.locomotive_context |
| + | # # begin |
| + | # # binding.pry |
| + | # render(page, context) |
| + | # # rescue Exception => e |
| + | |
| + | # # raise RendererException.new(e, self.page.title, self.page.template, context) |
| + | # # end |
| + | # end |
| + | |
| + | # def render(page, context) |
| + | # parse(page, context).render(context) |
| + | # end |
| + | |
| + | # protected |
| + | |
| + | # def parse(page, context) |
| + | |
| + | # options = { |
| + | # page: page, |
| + | # mapper: context.registers[:mapper], |
| + | # error_mode: :strict, |
| + | # count_lines: true |
| + | # } |
| + | |
| + | # begin |
| + | # ::Liquid::Template.parse(page.source(I18n.locale), options) |
| + | # rescue ::Liquid::SyntaxError |
| + | # # do it again on the raw source instead so that the error line matches |
| + | # # the source file. |
| + | # ::Liquid::Template.parse(self.template.raw_source, options) |
| + | # end |
| + | # end |
| + | |
| + | |
| + | # def render_404 |
| + | # if self.page = Locomotive::Models[:pages]['404'] |
| + | # self.render_page |
| + | # else |
| + | # 'Page not found' |
| + | # end |
| + | # end |
| + | |
| + | # # Build the Liquid context used to render the Locomotive page. It |
| + | # # stores both assigns and registers. |
| + | # # |
| + | # # @param [ Hash ] other_assigns Assigns coming for instance from the controler (optional) |
| + | # # |
| + | # # @return [ Object ] A new instance of the Liquid::Context class. |
| + | # # |
| + | # def locomotive_context(other_assigns = {}) |
| + | # assigns = self.locomotive_default_assigns |
| + | |
| + | # # assigns from other middlewares |
| + | # assigns.merge!(self.liquid_assigns) |
| + | |
| + | # assigns.merge!(other_assigns) |
| + | |
| + | # # templatized page |
| + | # if self.page && self.content_entry |
| + | # ['content_entry', 'entry', self.page.content_type.slug.singularize].each do |key| |
| + | # assigns[key] = self.content_entry |
| + | # end |
| + | # end |
| + | |
| + | # # Tip: switch from false to true to enable the re-thrown exception flag |
| + | # ::Liquid::Context.new({}, assigns, self.locomotive_default_registers, true) |
| + | # end |
| + | |
| + | # # Return the default Liquid assigns used inside the Locomotive Liquid context |
| + | # # |
| + | # # @return [ Hash ] The default liquid assigns object |
| + | # # |
| + | # def locomotive_default_assigns |
| + | # { |
| + | # 'site' => self.site.to_liquid, |
| + | # 'page' => self.page, |
| + | # 'models' => Locomotive::Steam::Liquid::Drops::ContentTypes.new, |
| + | # 'contents' => Locomotive::Steam::Liquid::Drops::ContentTypes.new, |
| + | # 'current_page' => self.params[:page], |
| + | # 'params' => self.params.stringify_keys, |
| + | # 'path' => self.request.path, |
| + | # 'fullpath' => self.request.fullpath, |
| + | # 'url' => self.request.url, |
| + | # 'ip_address' => self.request.ip, |
| + | # 'post?' => self.request.post?, |
| + | # 'host' => self.request.host_with_port, |
| + | # 'now' => Time.zone.now, |
| + | # 'today' => Date.today, |
| + | # 'locale' => I18n.locale.to_s, |
| + | # 'default_locale' => self.site.default_locale.to_s, |
| + | # 'locales' => self.site.locales.map(&:to_s), |
| + | # 'current_user' => {}, |
| + | # 'session' => Locomotive::Steam::Liquid::Drops::SessionProxy.new, |
| + | # 'steam' => true, |
| + | # 'editing' => false |
| + | # } |
| + | # end |
| + | |
| + | # # Return the default Liquid registers used inside the Locomotive Liquid context |
| + | # # |
| + | # # @return [ Hash ] The default liquid registers object |
| + | # # |
| + | # def locomotive_default_registers |
| + | # { |
| + | # request: self.request, |
| + | # site: self.site, |
| + | # page: self.page, |
| + | # services: self.services, |
| + | # inline_editor: false, |
| + | # logger: Locomotive::Common::Logger |
| + | # } |
| + | # end |
| end | |
locomotive/steam/middlewares/threadsafe.rb b/lib/locomotive/steam/middlewares/threadsafe.rb
+5
-1
| @@ | @@ -9,7 +9,7 @@ module Locomotive::Steam::Middlewares |
| threadsafed.env = env | |
| # time = Benchmark.realtime do | |
| - | threadsafed._call # thread-safe purpose |
| + | threadsafed._call # thread-safe purpose |
| # end | |
| # puts "[Benchmark][#{self.class.name}] Time elapsed #{time*1000} milliseconds" | |
| @@ | @@ -36,6 +36,10 @@ module Locomotive::Steam::Middlewares |
| @site ||= env.fetch('steam.site') | |
| end | |
| + | def page |
| + | @page ||= env.fetch('steam.page') |
| + | end |
| + | |
| def path | |
| @path ||= env.fetch('steam.path') | |
| end | |
locomotive/steam/repositories/filesystem/memory_adapter/condition.rb b/lib/locomotive/steam/repositories/filesystem/memory_adapter/condition.rb
+1
-1
| @@ | @@ -14,7 +14,7 @@ module Locomotive |
| def initialize(operator_and_field, value, locale) | |
| @locale = locale.to_sym | |
| @operator_and_field, @value = operator_and_field, value | |
| - | @operator, @field = :==, nil |
| + | @operator, @field = :==, operator_and_field |
| decode_operator_and_field! | |
| end | |
locomotive/steam/repositories/filesystem/models/page.rb b/lib/locomotive/steam/repositories/filesystem/models/page.rb
+5
-1
| @@ | @@ -28,6 +28,10 @@ module Locomotive |
| !!content_type | |
| end | |
| + | def not_found? |
| + | attributes[:fullpath].values.first == '404' |
| + | end |
| + | |
| def localized_attributes | |
| self.class.localized_attributes | |
| end | |
| @@ | @@ -37,7 +41,7 @@ module Locomotive |
| end | |
| def to_liquid | |
| - | Steam::Liquids::Drops::Page.new(self, localized_attributes) |
| + | Steam::Liquids::Drops::Page.new(self) |
| end | |
| end | |
locomotive/steam/repositories/filesystem/page.rb b/lib/locomotive/steam/repositories/filesystem/page.rb
+1
-1
| @@ | @@ -20,7 +20,7 @@ module Locomotive |
| def by_fullpath(path) | |
| MemoryAdapter::Query.new(collection, current_locale) do | |
| - | where(fullpath: path) |
| + | where(:fullpath => path) |
| end.first | |
| end | |
locomotive/steam/server.rb b/lib/locomotive/steam/server.rb
+1
-1
| @@ | @@ -25,7 +25,7 @@ module Locomotive::Steam |
| use Middlewares::Timezone | |
| use Middlewares::Page | |
| - | run Middlewares::Renderer.new |
| + | run Middlewares::Renderer.new(nil) |
| end | |
| end | |
locomotive/steam/services/page_finder.rb b/lib/locomotive/steam/services/page_finder.rb
+25
-1
| @@ | @@ -7,11 +7,27 @@ module Locomotive |
| WILDCARD = 'content-type-template' | |
| def find(path) | |
| - | repository.matching_fullpath(path_combinations(path)) |
| + | decorate do |
| + | repository.by_fullpath(path) |
| + | end |
| + | end |
| + | |
| + | def match(path) |
| + | decorate do |
| + | repository.matching_fullpath(path_combinations(path)) |
| + | end |
| end | |
| private | |
| + | def decorate(&block) |
| + | if (object = yield).blank? |
| + | object |
| + | else |
| + | Decorators::PageDecorator.decorate(object, nil, locale, default_locale) |
| + | end |
| + | end |
| + | |
| def path_combinations(path) | |
| _path_combinations(path.split('/')) | |
| end | |
| @@ | @@ -31,6 +47,14 @@ module Locomotive |
| end.flatten | |
| end | |
| + | def locale |
| + | repository.current_locale |
| + | end |
| + | |
| + | def default_locale |
| + | repository.site.default_locale |
| + | end |
| + | |
| end | |
| end | |
spec/integration/server/basic_spec.rb
+5
-5
| @@ | @@ -18,11 +18,11 @@ describe Locomotive::Steam::Server do |
| # expect(last_response.body).to match(/Upcoming events/) | |
| # end | |
| - | # it 'shows the 404 page', pending: true do |
| - | # get '/void' |
| - | # last_response.status.should eq(404) |
| - | # last_response.body.should =~ /page not found/ |
| - | # end |
| + | it 'shows the 404 page' do |
| + | get '/void' |
| + | expect(last_response.status).to eq(404) |
| + | expect(last_response.body).to match /page not found/ |
| + | end |
| # it 'shows the 404 page with 200 status code when its called explicitly', pending: true do | |
| # get '/404' | |
spec/support/helpers.rb
+1
-1
| @@ | @@ -19,7 +19,7 @@ module Spec |
| end | |
| def run_server | |
| - | setup_common(File.join(default_fixture_site_path, 'log/steam.log')) |
| + | setup_common #(File.join(default_fixture_site_path, 'log/steam.log')) |
| Locomotive::Common::Logger.info 'Server started...' | |
| Locomotive::Steam::Server.new(path: default_fixture_site_path).to_app | |