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