make Steam as thread-safe as possible + prepare the future integration into a rails app + close issues #15 and #16
did
committed Apr 13, 2014
commit 4e0a6225331bc19ee358c3385fe21adcb5478f4e
Showing 51
changed files with
1016 additions
and 986 deletions
Gemfile.lock
+5
-25
| @@ | @@ -3,11 +3,10 @@ PATH |
| specs: | |
| locomotivecms_steam (0.1.0) | |
| activesupport (~> 3.2) | |
| - | better_errors (~> 1.0) |
| - | dragonfly (~> 0.9) |
| - | listen (~> 2.7) |
| + | dragonfly (~> 1.0.3) |
| locomotivecms-solid | |
| locomotivecms_mounter | |
| + | moneta (~> 0.7.20) |
| rack-cache (~> 1.1) | |
| redcarpet (~> 3.1) | |
| sprockets (~> 2.0) | |
| @@ | @@ -22,14 +21,6 @@ GEM |
| i18n (~> 0.6, >= 0.6.4) | |
| multi_json (~> 1.0) | |
| addressable (2.3.6) | |
| - | better_errors (1.1.0) |
| - | coderay (>= 1.0.0) |
| - | erubis (>= 2.6.6) |
| - | celluloid (0.15.2) |
| - | timers (~> 1.1.0) |
| - | celluloid-io (0.15.0) |
| - | celluloid (>= 0.15.0) |
| - | nio4r (>= 0.5.0) |
| chronic (0.10.2) | |
| chunky_png (1.3.0) | |
| coderay (1.1.0) | |
| @@ | @@ -53,12 +44,10 @@ GEM |
| safe_yaml (~> 1.0.0) | |
| diff-lcs (1.2.5) | |
| docile (1.1.3) | |
| - | dragonfly (0.9.15) |
| + | dragonfly (1.0.4) |
| multi_json (~> 1.0) | |
| rack | |
| - | erubis (2.7.0) |
| execjs (2.0.2) | |
| - | ffi (1.9.3) |
| fssm (0.2.10) | |
| haml (4.0.5) | |
| tilt | |
| @@ | @@ -66,7 +55,7 @@ GEM |
| httmultiparty (0.3.10) | |
| httparty (>= 0.7.3) | |
| multipart-post | |
| - | httparty (0.13.0) |
| + | httparty (0.13.1) |
| json (~> 1.8) | |
| multi_xml (>= 0.5.2) | |
| i18n (0.6.9) | |
| @@ | @@ -79,11 +68,6 @@ GEM |
| addressable (~> 2.3) | |
| less (2.2.2) | |
| commonjs (~> 0.2.6) | |
| - | listen (2.7.1) |
| - | celluloid (>= 0.15.2) |
| - | celluloid-io (>= 0.15.0) |
| - | rb-fsevent (>= 0.9.3) |
| - | rb-inotify (>= 0.9) |
| locomotivecms-liquid (2.6.0) | |
| locomotivecms-solid (0.2.2.1) | |
| locomotivecms-liquid (~> 2.6.0) | |
| @@ | @@ -112,10 +96,10 @@ GEM |
| logger (1.2.8) | |
| method_source (0.8.2) | |
| mime-types (1.25.1) | |
| + | moneta (0.7.20) |
| multi_json (1.7.9) | |
| multi_xml (0.5.5) | |
| multipart-post (2.0.0) | |
| - | nio4r (1.0.0) |
| pry (0.9.12.6) | |
| coderay (~> 1.0) | |
| method_source (~> 0.8) | |
| @@ | @@ -126,9 +110,6 @@ GEM |
| rack-test (0.6.2) | |
| rack (>= 1.0) | |
| rake (10.2.2) | |
| - | rb-fsevent (0.9.4) |
| - | rb-inotify (0.9.3) |
| - | ffi (>= 0.5.0) |
| redcarpet (3.1.1) | |
| rest-client (1.6.7) | |
| mime-types (>= 1.16) | |
| @@ | @@ -161,7 +142,6 @@ GEM |
| tins (~> 1.0) | |
| thor (0.18.1) | |
| tilt (1.4.1) | |
| - | timers (1.1.0) |
| tins (1.0.0) | |
| tzinfo (0.3.39) | |
| vcr (2.9.0) | |
example/server.rb
+22
-0
| @@ | @@ -0,0 +1,22 @@ |
| + | #!/usr/bin/env ruby |
| + | |
| + | require 'thin' |
| + | |
| + | DIR = File.expand_path(File.dirname(__FILE__)) |
| + | |
| + | require File.join(DIR, '../lib/steam') |
| + | require File.join(DIR, '../lib/locomotive/steam/server') |
| + | require File.join(DIR, '../lib/locomotive/steam/initializers') |
| + | |
| + | path = File.join(DIR, '../spec/fixtures/default') |
| + | Locomotive::Steam::Logger.setup(path, false) |
| + | reader = Locomotive::Mounter::Reader::FileSystem.instance |
| + | reader.run!(path: path) |
| + | |
| + | app = Locomotive::Steam::Server.new(reader, { |
| + | serve_assets: true |
| + | }) |
| + | |
| + | server = Thin::Server.new('localhost', '3333', app) |
| + | server.threaded = true |
| + | server.start |
| \ No newline at end of file | |
locomotive/steam/initializers.rb b/lib/locomotive/steam/initializers.rb
+2
-4
| @@ | @@ -1,5 +1,3 @@ |
| - | require_relative 'core_ext.rb' |
| - | |
| + | require_relative 'initializers/sprockets.rb' |
| require_relative 'initializers/i18n.rb' | |
| - | require_relative 'initializers/markdown.rb' |
| - | require_relative 'initializers/will_paginate.rb' |
| \ No newline at end of file | |
| + | require_relative 'initializers/dragonfly.rb' |
locomotive/steam/initializers/better_errors.rb b/lib/locomotive/steam/initializers/better_errors.rb
+73
-0
| @@ | @@ -0,0 +1,73 @@ |
| + | # BetterErrors.application_root = reader.mounting_point.path |
| + | |
| + | # require 'better_errors' |
| + | # require 'ostruct' |
| + | |
| + | # module BetterErrors |
| + | # class MiddlewareWrapper |
| + | |
| + | # def initialize(app) |
| + | # @@middleware ||= BetterErrors::Middleware.new(app) |
| + | # @@middleware.instance_variable_set(:@app, app) |
| + | # end |
| + | |
| + | # def call(env) |
| + | # env['action_dispatch.request.parameters'] = Rack::Request.new(env).params |
| + | |
| + | # @@middleware.call(env) |
| + | # end |
| + | |
| + | # end |
| + | |
| + | # module FrameWithLiquidContext |
| + | |
| + | # extend ActiveSupport::Concern |
| + | |
| + | # included do |
| + | |
| + | # attr_accessor :liquid_context |
| + | |
| + | # alias_method_chain :local_variables, :liquid_context |
| + | |
| + | # class << self |
| + | |
| + | # alias_method_chain :from_exception, :liquid_context |
| + | |
| + | # end |
| + | # end |
| + | |
| + | # def local_variables_with_liquid_context |
| + | # if self.liquid_context |
| + | # scope = self.liquid_context.scopes.last.clone |
| + | |
| + | # scope.delete_if { |k, _| %w(models contents params session).include?(k) }.tap do |_scope| |
| + | # _scope['site'] = _scope['site'].send(:_source).to_hash |
| + | # _scope['page'] = _scope['page'].to_hash.delete_if { |k, _| %w(template).include?(k) } |
| + | # end |
| + | # else |
| + | # self.local_variables_without_liquid_context |
| + | # end |
| + | # rescue Exception => e |
| + | # puts "[BetterError] Fatal error: #{e.message}".red |
| + | # puts e.backtrace.join("\n") |
| + | # {} |
| + | # end |
| + | |
| + | # module ClassMethods |
| + | |
| + | # def from_exception_with_liquid_context(exception) |
| + | # from_exception_without_liquid_context(exception).tap do |list| |
| + | # if exception.respond_to?(:liquid_context) |
| + | # list.first.liquid_context = exception.liquid_context |
| + | # end |
| + | # end |
| + | # end |
| + | |
| + | # end |
| + | # end |
| + | |
| + | # class StackFrame |
| + | # include FrameWithLiquidContext |
| + | # end |
| + | |
| + | # end |
| \ No newline at end of file | |
locomotive/steam/initializers/dragonfly.rb b/lib/locomotive/steam/initializers/dragonfly.rb
+18
-0
| @@ | @@ -0,0 +1,18 @@ |
| + | require 'dragonfly' |
| + | |
| + | # Configure |
| + | Dragonfly.app(:steam).configure do |
| + | plugin :imagemagick, |
| + | convert_command: `which convert`.strip.presence || '/usr/local/bin/convert', |
| + | identify_command: `which identify`.strip.presence || '/usr/local/bin/identify' |
| + | |
| + | protect_from_dos_attacks true |
| + | |
| + | url_format '/images/dynamic/:job/:basename.:ext' |
| + | |
| + | fetch_file_whitelist /public/ |
| + | |
| + | fetch_url_whitelist /.+/ |
| + | end |
| + | |
| + | Dragonfly.logger = Locomotive::Steam::Logger.instance |
| \ No newline at end of file | |
locomotive/steam/initializers/markdown.rb b/lib/locomotive/steam/initializers/markdown.rb
+0
-27
| @@ | @@ -1,27 +0,0 @@ |
| - | require 'redcarpet' |
| - | |
| - | module Locomotive |
| - | module Steam |
| - | module Markdown |
| - | |
| - | def self.render(text) |
| - | self.parser.render(text) |
| - | end |
| - | |
| - | def self.parser |
| - | @@markdown ||= Redcarpet::Markdown.new Redcarpet::Steam::HTML, { |
| - | autolink: true, |
| - | fenced_code: true, |
| - | generate_toc: true, |
| - | gh_blockcode: true, |
| - | hard_wrap: true, |
| - | no_intraemphasis: true, |
| - | strikethrough: true, |
| - | tables: true, |
| - | xhtml: true |
| - | } |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/initializers/sprockets.rb b/lib/locomotive/steam/initializers/sprockets.rb
+1
-0
| @@ | @@ -0,0 +1 @@ |
| + | Sprockets::Sass.add_sass_functions = false |
| \ No newline at end of file | |
locomotive/steam/initializers/will_paginate.rb b/lib/locomotive/steam/initializers/will_paginate.rb
+0
-16
| @@ | @@ -1,16 +0,0 @@ |
| - | require 'will_paginate' |
| - | require 'will_paginate/collection' |
| - | |
| - | Array.class_eval do |
| - | def paginate(options = {}) |
| - | raise ArgumentError, "parameter hash expected (got #{options.inspect})" unless Hash === options |
| - | |
| - | WillPaginate::Collection.create( |
| - | options[:page] || 1, |
| - | options[:per_page] || 30, |
| - | options[:total_entries] || self.length |
| - | ) { |pager| |
| - | pager.replace self[pager.offset, pager.per_page].to_a |
| - | } |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/liquid/filters/resize.rb b/lib/locomotive/steam/liquid/filters/resize.rb
+2
-1
| @@ | @@ -5,7 +5,8 @@ module Locomotive |
| module Resize | |
| def resize(input, resize_string) | |
| - | Locomotive::Steam::Dragonfly.instance.resize_url(input, resize_string) |
| + | dragonfly = @context.registers[:services][:dragonfly] |
| + | dragonfly.resize_url(input, resize_string) |
| end | |
| end | |
locomotive/steam/liquid/tags/consume.rb b/lib/locomotive/steam/liquid/tags/consume.rb
+6
-1
| @@ | @@ -72,7 +72,8 @@ module Locomotive |
| def render_all_without_cache(context) | |
| context.stack do | |
| begin | |
| - | context.scopes.last[@target.to_s] = Locomotive::Steam::Httparty::Webservice.consume(@url, @options.symbolize_keys) |
| + | context.scopes.last[@target.to_s] = external_api_service(context).consume(@url, @options.symbolize_keys) |
| + | |
| self.cached_response = context.scopes.last[@target.to_s] | |
| rescue Timeout::Error | |
| context.scopes.last[@target.to_s] = self.cached_response | |
| @@ | @@ -88,6 +89,10 @@ module Locomotive |
| end | |
| end | |
| + | def external_api_service(context) |
| + | context.registers[:services][:external_api] |
| + | end |
| + | |
| end | |
| ::Liquid::Template.register_tag('consume', Consume) | |
locomotive/steam/listen.rb b/lib/locomotive/steam/listen.rb
+0
-64
| @@ | @@ -1,64 +0,0 @@ |
| - | require 'listen' |
| - | |
| - | module Locomotive::Steam |
| - | class Listen |
| - | |
| - | attr_accessor :reader |
| - | |
| - | def self.instance |
| - | @@instance = new |
| - | end |
| - | |
| - | def start(reader) |
| - | # if $parent_pid && $parent_pid == Process.pid |
| - | # puts "bypassing Listen in the parent process" |
| - | # return false |
| - | # end |
| - | |
| - | puts "Listening here: #{Process.pid}" |
| - | |
| - | self.reader = reader |
| - | |
| - | self.definitions.each do |definition| |
| - | self.apply(definition) |
| - | end |
| - | end |
| - | |
| - | def definitions |
| - | [ |
| - | ['config', /\.yml/, [:site, :content_types, :pages, :snippets, :content_entries, :translations]], |
| - | ['app/views', /\.liquid/, [:pages, :snippets]], |
| - | ['app/content_types', /\.yml/, [:content_types, :content_entries]], |
| - | ['data', /\.yml/, :content_entries] |
| - | ] |
| - | end |
| - | |
| - | protected |
| - | |
| - | def apply(definition) |
| - | reloader = Proc.new do |modified, added, removed| |
| - | resources = [*definition.last] |
| - | names = resources.map { |n| "\"#{n}\"" }.join(', ') |
| - | |
| - | Locomotive::Steam::Logger.info "* Reloaded #{names} at #{Time.now}" |
| - | |
| - | begin |
| - | reader.reload(resources) |
| - | rescue Exception => e |
| - | Locomotive::Steam::MounterException.new('Unable to reload', e) |
| - | end |
| - | end |
| - | |
| - | filter = definition[1] |
| - | path = File.join(self.reader.mounting_point.path, definition.first) |
| - | path = File.expand_path(path) |
| - | |
| - | listener = ::Listen.to(path, only: filter, &reloader) |
| - | |
| - | # non blocking listener |
| - | listener.start #(false) |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| \ No newline at end of file | |
locomotive/steam/middlewares.rb b/lib/locomotive/steam/middlewares.rb
+15
-0
| @@ | @@ -0,0 +1,15 @@ |
| + | require_relative 'middlewares/base' |
| + | |
| + | require_relative 'middlewares/favicon' |
| + | require_relative 'middlewares/static_assets' |
| + | require_relative 'middlewares/dynamic_assets' |
| + | require_relative 'middlewares/logging' |
| + | require_relative 'middlewares/entry_submission' |
| + | require_relative 'middlewares/path' |
| + | require_relative 'middlewares/locale' |
| + | require_relative 'middlewares/page' |
| + | require_relative 'middlewares/timezone' |
| + | require_relative 'middlewares/templatized_page' |
| + | require_relative 'middlewares/renderer' |
| + | |
| + | require_relative 'middlewares/stack' |
| \ No newline at end of file | |
locomotive/steam/middlewares/base.rb b/lib/locomotive/steam/middlewares/base.rb
+63
-0
| @@ | @@ -0,0 +1,63 @@ |
| + | module Locomotive::Steam |
| + | module Middlewares |
| + | |
| + | class Base |
| + | |
| + | attr_accessor :app, :request, :path |
| + | attr_accessor :liquid_assigns, :services |
| + | attr_accessor :mounting_point, :page, :content_entry |
| + | |
| + | def initialize(app = nil) |
| + | @app = app |
| + | end |
| + | |
| + | def call(env) |
| + | dup._call(env) # thread-safe purpose |
| + | end |
| + | |
| + | def _call(env) |
| + | self.set_accessors(env) |
| + | end |
| + | |
| + | protected |
| + | |
| + | def set_accessors(env) |
| + | %w(path request mounting_point page content_entry services).each do |name| |
| + | self.send(:"#{name}=", env["steam.#{name}"]) |
| + | end |
| + | |
| + | env['steam.liquid_assigns'] ||= {} |
| + | self.liquid_assigns = env['steam.liquid_assigns'] |
| + | end |
| + | |
| + | def site |
| + | self.mounting_point.site |
| + | end |
| + | |
| + | def params |
| + | self.request.params.deep_symbolize_keys |
| + | end |
| + | |
| + | def html? |
| + | ['text/html', 'application/x-www-form-urlencoded'].include?(self.request.media_type) && |
| + | !self.request.xhr? && |
| + | !self.json? |
| + | end |
| + | |
| + | def json? |
| + | self.request.content_type == 'application/json' || File.extname(self.request.path) == '.json' |
| + | end |
| + | |
| + | def redirect_to(location, type = 301) |
| + | self.log "Redirected to #{location}" |
| + | [type, { 'Content-Type' => 'text/html', 'Location' => location }, []] |
| + | end |
| + | |
| + | def log(msg) |
| + | Locomotive::Steam::Logger.info msg |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/middlewares/dynamic_assets.rb b/lib/locomotive/steam/middlewares/dynamic_assets.rb
+40
-0
| @@ | @@ -0,0 +1,40 @@ |
| + | require 'coffee_script' |
| + | |
| + | module Locomotive::Steam |
| + | module Middlewares |
| + | |
| + | class DynamicAssets < Base |
| + | |
| + | attr_reader :app, :regexp |
| + | |
| + | def initialize(app) |
| + | super(app) |
| + | |
| + | @regexp = /^\/(javascripts|stylesheets)\/(.*)$/ |
| + | end |
| + | |
| + | def call(env) |
| + | dup._call(env) # thread-safe purpose |
| + | end |
| + | |
| + | def _call(env) |
| + | if env['PATH_INFO'] =~ self.regexp |
| + | env['PATH_INFO'] = $2 |
| + | |
| + | base_path = env['steam.mounting_point'].path |
| + | |
| + | begin |
| + | sprockets = Locomotive::Mounter::Extensions::Sprockets.environment(base_path) |
| + | sprockets.call(env) |
| + | rescue Exception => e |
| + | raise Locomotive::Steam::DefaultException.new "Unable to serve a dynamic asset. Please check the logs.", e |
| + | end |
| + | else |
| + | app.call(env) |
| + | end |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/middlewares/entry_submission.rb b/lib/locomotive/steam/middlewares/entry_submission.rb
+120
-0
| @@ | @@ -0,0 +1,120 @@ |
| + | module Locomotive::Steam |
| + | module Middlewares |
| + | |
| + | # Mimic the submission of a content entry |
| + | # |
| + | class EntrySubmission < Base |
| + | |
| + | def _call(env) |
| + | super |
| + | |
| + | if self.request.post? && env['PATH_INFO'] =~ /^\/entry_submissions\/(.*)/ |
| + | self.process_form($1) |
| + | |
| + | # puts "html? #{html?} / json? #{json?} / #{self.callback_url} / #{params.inspect}" |
| + | |
| + | if @entry.valid? |
| + | if self.html? |
| + | self.record_submitted_entry |
| + | self.redirect_to self.callback_url |
| + | elsif self.json? |
| + | self.json_response |
| + | end |
| + | else |
| + | if self.html? |
| + | if self.callback_url =~ /^http:\/\// |
| + | self.redirect_to self.callback_url |
| + | else |
| + | env['PATH_INFO'] = self.callback_url |
| + | self.liquid_assigns[@content_type.slug.singularize] = @entry |
| + | app.call(env) |
| + | end |
| + | elsif self.json? |
| + | self.json_response(422) |
| + | end |
| + | end |
| + | else |
| + | self.fetch_submitted_entry |
| + | |
| + | app.call(env) |
| + | end |
| + | end |
| + | |
| + | protected |
| + | |
| + | def record_submitted_entry |
| + | self.request.session[:now] ||= {} |
| + | self.request.session[:now][:submitted_entry] = [@content_type.slug, @entry._slug] |
| + | end |
| + | |
| + | def fetch_submitted_entry |
| + | if data = self.request.session[:now].try(:delete, :submitted_entry) |
| + | content_type = self.mounting_point.content_types[data.first.to_s] |
| + | |
| + | entry = (content_type.entries || []).detect { |e| e._slug == data.last } |
| + | |
| + | # do not keep track of the entry |
| + | content_type.entries.delete(entry) if entry |
| + | |
| + | # add it to the additional liquid assigns for the next liquid rendering |
| + | if entry |
| + | self.liquid_assigns[content_type.slug.singularize] = entry |
| + | end |
| + | end |
| + | end |
| + | |
| + | # Mimic the creation of a content entry with a minimal validation. |
| + | # |
| + | # @param [ String ] permalink The permalink (or slug) of the content type |
| + | # |
| + | # |
| + | def process_form(permalink) |
| + | permalink = permalink.split('.').first |
| + | |
| + | @content_type = self.mounting_point.content_types[permalink] |
| + | |
| + | raise "Unknown content type '#{@content_type.inspect}'" if @content_type.nil? |
| + | |
| + | attributes = self.params[:entry] || self.params[:content] || {} |
| + | |
| + | @entry = @content_type.build_entry(attributes) |
| + | |
| + | # if not valid, we do not need to keep track of the entry |
| + | @content_type.entries.delete(@entry) if !@entry.valid? |
| + | end |
| + | |
| + | def callback_url |
| + | (@entry.valid? ? params[:success_callback] : params[:error_callback]) || '/' |
| + | end |
| + | |
| + | # Build the JSON response |
| + | # |
| + | # @param [ Integer ] status The HTTP return code |
| + | # |
| + | # @return [ Array ] The rack response depending on the validation status and the requested format |
| + | # |
| + | def json_response(status = 200) |
| + | locale = self.mounting_point.default_locale |
| + | |
| + | if self.request.path =~ /^\/(#{self.mounting_point.locales.join('|')})+(\/|$)/ |
| + | locale = $1 |
| + | end |
| + | |
| + | hash = @entry.to_hash(false).tap do |_hash| |
| + | if !@entry.valid? |
| + | _hash['errors'] = @entry.errors.inject({}) do |memo, name| |
| + | memo[name] = ::I18n.t('errors.messages.blank', locale: locale) |
| + | memo |
| + | end |
| + | end |
| + | end |
| + | |
| + | [status, { 'Content-Type' => 'application/json' }, [ |
| + | { @content_type.slug.singularize => hash }.to_json |
| + | ]] |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/middlewares/favicon.rb b/lib/locomotive/steam/middlewares/favicon.rb
+17
-0
| @@ | @@ -0,0 +1,17 @@ |
| + | module Locomotive::Steam |
| + | module Middlewares |
| + | |
| + | class Favicon < Base |
| + | |
| + | def call(env) |
| + | if env['PATH_INFO'] == '/favicon.ico' |
| + | [200, { 'Content-Type' => 'image/vnd.microsoft.icon' }, ['']] |
| + | else |
| + | app.call(env) |
| + | end |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/middlewares/locale.rb b/lib/locomotive/steam/middlewares/locale.rb
+42
-0
| @@ | @@ -0,0 +1,42 @@ |
| + | module Locomotive::Steam |
| + | module Middlewares |
| + | |
| + | # Set the locale from the path if possible or use the default one |
| + | # Examples: |
| + | # /fr/index => locale = :fr |
| + | # /fr/ => locale = :fr |
| + | # /index => locale = :en (default one) |
| + | # |
| + | class Locale < Base |
| + | |
| + | def _call(env) |
| + | super |
| + | |
| + | self.set_locale!(env) |
| + | |
| + | app.call(env) |
| + | end |
| + | |
| + | protected |
| + | |
| + | def set_locale!(env) |
| + | locale = self.mounting_point.default_locale |
| + | |
| + | if self.path =~ /^(#{self.mounting_point.locales.join('|')})+(\/|$)/ |
| + | locale = $1 |
| + | self.path = self.path.gsub($1 + $2, '') |
| + | self.path = 'index' if self.path.blank? |
| + | end |
| + | |
| + | Locomotive::Mounter.locale = locale |
| + | ::I18n.locale = locale |
| + | |
| + | self.log "Detecting locale #{locale.upcase}" |
| + | |
| + | env['steam.locale'] = locale |
| + | env['steam.path'] = self.path |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/middlewares/logging.rb b/lib/locomotive/steam/middlewares/logging.rb
+32
-0
| @@ | @@ -0,0 +1,32 @@ |
| + | module Locomotive::Steam |
| + | module Middlewares |
| + | |
| + | # Track the request into the current logger |
| + | # |
| + | class Logging < Base |
| + | |
| + | def call(env) |
| + | now = Time.now |
| + | |
| + | log "Started #{env['REQUEST_METHOD'].upcase} \"#{env['PATH_INFO']}\" at #{now}".light_white |
| + | |
| + | app.call(env).tap do |response| |
| + | done_in_ms = ((Time.now - now) * 10000).truncate / 10.0 |
| + | log "Completed #{code_to_human(response.first)} in #{done_in_ms}ms\n\n".green |
| + | end |
| + | end |
| + | |
| + | protected |
| + | |
| + | def code_to_human(code) |
| + | case code.to_i |
| + | when 200 then '200 OK' |
| + | when 301 then '301 Found' |
| + | when 302 then '302 Found' |
| + | when 404 then '404 Not Found' |
| + | end |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/middlewares/page.rb b/lib/locomotive/steam/middlewares/page.rb
+67
-0
| @@ | @@ -0,0 +1,67 @@ |
| + | module Locomotive::Steam |
| + | module Middlewares |
| + | |
| + | # Sanitize the path from the previous middleware in order |
| + | # to make it work for the renderer. |
| + | # |
| + | class Page < Base |
| + | |
| + | def _call(env) |
| + | super |
| + | |
| + | self.set_page!(env) |
| + | |
| + | app.call(env) |
| + | end |
| + | |
| + | protected |
| + | |
| + | def set_page!(env) |
| + | page = self.fetch_page |
| + | |
| + | if page |
| + | self.log "Found page \"#{page.title}\" [#{page.safe_fullpath}]" |
| + | end |
| + | |
| + | env['steam.page'] = page |
| + | end |
| + | |
| + | def fetch_page |
| + | matchers = self.path_combinations(self.path) |
| + | |
| + | pages = self.mounting_point.pages.values.find_all do |_page| |
| + | matchers.include?(_page.safe_fullpath) || |
| + | matchers.include?(_page.safe_fullpath.try(:underscore)) |
| + | end.sort_by { |p| p.position || Float::INFINITY } |
| + | |
| + | if pages.size > 1 |
| + | self.log "Found multiple pages: #{pages.collect(&:title).join(', ')}" |
| + | end |
| + | |
| + | pages.first |
| + | end |
| + | |
| + | def path_combinations(path) |
| + | self._path_combinations(path.split('/')) |
| + | end |
| + | |
| + | def _path_combinations(segments, can_include_template = true) |
| + | return nil if segments.empty? |
| + | |
| + | segment = segments.shift |
| + | |
| + | (can_include_template ? [segment, '*'] : [segment]).map do |_segment| |
| + | if (_combinations = _path_combinations(segments.clone, can_include_template && _segment != '*')) |
| + | [*_combinations].map do |_combination| |
| + | File.join(_segment, _combination) |
| + | end |
| + | else |
| + | [_segment] |
| + | end |
| + | end.flatten |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
locomotive/steam/middlewares/path.rb b/lib/locomotive/steam/middlewares/path.rb
+34
-0
| @@ | @@ -0,0 +1,34 @@ |
| + | module Locomotive::Steam |
| + | module Middlewares |
| + | |
| + | # Sanitize the path from the previous middleware in order |
| + | # to make it work for the renderer. |
| + | # |
| + | class Path < Base |
| + | |
| + | def _call(env) |
| + | super |
| + | |
| + | self.set_path!(env) |
| + | |
| + | app.call(env) |
| + | end |
| + | |
| + | protected |
| + | |
| + | def set_path!(env) |
| + | path = env['PATH_INFO'].clone |
| + | |
| + | path.gsub!(/\.[a-zA-Z][a-zA-Z0-9]{2,}$/, '') |
| + | path.gsub!(/^\//, '') |
| + | path.gsub!(/^[A-Z]:\//, '') |
| + | |
| + | path = 'index' if path.blank? |
| + | |
| + | env['steam.path'] = path |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/middlewares/renderer.rb b/lib/locomotive/steam/middlewares/renderer.rb
+119
-0
| @@ | @@ -0,0 +1,119 @@ |
| + | module Locomotive::Steam |
| + | module Middlewares |
| + | |
| + | class Renderer < Base |
| + | |
| + | def _call(env) |
| + | super |
| + | |
| + | if self.page |
| + | if self.page.redirect? |
| + | self.redirect_to(self.page.redirect_url, self.page.redirect_type) |
| + | else |
| + | type = self.page.response_type || 'text/html' |
| + | html = self.render_page |
| + | |
| + | self.log 'Rendered liquid page template' |
| + | |
| + | [200, { 'Content-Type' => type }, [html]] |
| + | end |
| + | else |
| + | [404, { 'Content-Type' => 'text/html' }, [self.render_404]] |
| + | end |
| + | end |
| + | |
| + | protected |
| + | |
| + | def render_page |
| + | context = self.locomotive_context |
| + | begin |
| + | self.page.render(context) |
| + | rescue Exception => e |
| + | raise RendererException.new(e, self.page.title, self.page.template, context) |
| + | end |
| + | end |
| + | |
| + | def render_404 |
| + | if self.page = self.mounting_point.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.mounting_point.default_locale.to_s, |
| + | 'locales' => self.mounting_point.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, |
| + | mounting_point: self.mounting_point, |
| + | services: self.services, |
| + | inline_editor: false, |
| + | logger: Locomotive::Steam::Logger |
| + | } |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/middlewares/stack.rb b/lib/locomotive/steam/middlewares/stack.rb
+63
-0
| @@ | @@ -0,0 +1,63 @@ |
| + | require 'rack/session/moneta' |
| + | |
| + | module Locomotive |
| + | module Steam |
| + | module Middlewares |
| + | |
| + | class Stack |
| + | |
| + | def initialize(options) |
| + | @options = prepare_options(options) |
| + | end |
| + | |
| + | def create |
| + | options = @options |
| + | |
| + | Rack::Builder.new do |
| + | use Rack::Lint |
| + | |
| + | use Middlewares::Favicon |
| + | |
| + | if options[:serve_assets] |
| + | use Middlewares::StaticAssets, { |
| + | urls: ['/images', '/fonts', '/samples', '/media'] |
| + | } |
| + | |
| + | use Middlewares::DynamicAssets |
| + | end |
| + | |
| + | use ::Dragonfly::Middleware, :steam |
| + | |
| + | use Rack::Session::Moneta, options[:moneta] |
| + | |
| + | use Middlewares::Logging |
| + | |
| + | use Middlewares::EntrySubmission |
| + | |
| + | use Middlewares::Path |
| + | use Middlewares::Locale |
| + | use Middlewares::Timezone |
| + | |
| + | use Middlewares::Page |
| + | use Middlewares::TemplatizedPage |
| + | |
| + | run Middlewares::Renderer.new |
| + | end |
| + | end |
| + | |
| + | protected |
| + | |
| + | def prepare_options(options) |
| + | { |
| + | serve_assets: false, |
| + | moneta: { |
| + | store: Moneta.new(:Memory, :expires => true) |
| + | } |
| + | }.merge(options) |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/middlewares/static_assets.rb b/lib/locomotive/steam/middlewares/static_assets.rb
+25
-0
| @@ | @@ -0,0 +1,25 @@ |
| + | require 'rack/static' |
| + | |
| + | module Locomotive::Steam |
| + | module Middlewares |
| + | |
| + | class StaticAssets < ::Rack::Static |
| + | |
| + | alias_method :call_without_threadsafety, :call |
| + | |
| + | def call(env) |
| + | dup._call(env) # thread-safe purpose |
| + | end |
| + | |
| + | def _call(env) |
| + | mounting_point = env['steam.mounting_point'] |
| + | |
| + | @file_server = Rack::File.new(mounting_point.assets_path) |
| + | |
| + | call_without_threadsafety(env) |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/middlewares/templatized_page.rb b/lib/locomotive/steam/middlewares/templatized_page.rb
+32
-0
| @@ | @@ -0,0 +1,32 @@ |
| + | module Locomotive::Steam |
| + | module Middlewares |
| + | |
| + | class TemplatizedPage < Base |
| + | |
| + | def _call(env) |
| + | super |
| + | |
| + | if self.page && self.page.templatized? |
| + | self.set_content_entry!(env) |
| + | end |
| + | |
| + | app.call(env) |
| + | end |
| + | |
| + | protected |
| + | |
| + | def set_content_entry!(env) |
| + | %r(^#{self.page.safe_fullpath.gsub('*', '([^\/]+)')}$) =~ self.path |
| + | |
| + | permalink = $1 |
| + | |
| + | if content_entry = self.page.content_type.find_entry(permalink) |
| + | env['steam.content_entry'] = content_entry |
| + | else |
| + | env['steam.page'] = nil |
| + | end |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/middlewares/timezone.rb b/lib/locomotive/steam/middlewares/timezone.rb
+18
-0
| @@ | @@ -0,0 +1,18 @@ |
| + | module Locomotive::Steam |
| + | module Middlewares |
| + | |
| + | # Set the timezone according to the settings of the site |
| + | # |
| + | class Timezone < Base |
| + | |
| + | def _call(env) |
| + | super |
| + | |
| + | Time.use_zone(site.try(:timezone) || 'UTC') do |
| + | app.call(env) |
| + | end |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/monkey_patches.rb b/lib/locomotive/steam/monkey_patches.rb
+3
-3
| @@ | @@ -1,5 +1,5 @@ |
| - | require_relative 'monkey_patches/httparty.rb' |
| - | require_relative 'monkey_patches/dragonfly.rb' |
| + | # require_relative 'monkey_patches/httparty.rb' |
| + | # require_relative 'monkey_patches/dragonfly.rb' |
| require_relative 'monkey_patches/mounter.rb' | |
| require_relative 'monkey_patches/haml.rb' | |
| - | require_relative 'monkey_patches/better_errors.rb' |
| \ No newline at end of file | |
| + | # require_relative 'monkey_patches/better_errors.rb' |
| \ No newline at end of file | |
locomotive/steam/monkey_patches/better_errors.rb b/lib/locomotive/steam/monkey_patches/better_errors.rb
+0
-70
| @@ | @@ -1,70 +0,0 @@ |
| - | require 'ostruct' |
| - | |
| - | module BetterErrors |
| - | class MiddlewareWrapper |
| - | |
| - | def initialize(app) |
| - | @@middleware ||= BetterErrors::Middleware.new(app) |
| - | @@middleware.instance_variable_set(:@app, app) |
| - | end |
| - | |
| - | def call(env) |
| - | env['action_dispatch.request.parameters'] = Rack::Request.new(env).params |
| - | |
| - | @@middleware.call(env) |
| - | end |
| - | |
| - | end |
| - | |
| - | module FrameWithLiquidContext |
| - | |
| - | extend ActiveSupport::Concern |
| - | |
| - | included do |
| - | |
| - | attr_accessor :liquid_context |
| - | |
| - | alias_method_chain :local_variables, :liquid_context |
| - | |
| - | class << self |
| - | |
| - | alias_method_chain :from_exception, :liquid_context |
| - | |
| - | end |
| - | end |
| - | |
| - | def local_variables_with_liquid_context |
| - | if self.liquid_context |
| - | scope = self.liquid_context.scopes.last.clone |
| - | |
| - | scope.delete_if { |k, _| %w(models contents params session).include?(k) }.tap do |_scope| |
| - | _scope['site'] = _scope['site'].send(:_source).to_hash |
| - | _scope['page'] = _scope['page'].to_hash.delete_if { |k, _| %w(template).include?(k) } |
| - | end |
| - | else |
| - | self.local_variables_without_liquid_context |
| - | end |
| - | rescue Exception => e |
| - | puts "[BetterError] Fatal error: #{e.message}".red |
| - | puts e.backtrace.join("\n") |
| - | {} |
| - | end |
| - | |
| - | module ClassMethods |
| - | |
| - | def from_exception_with_liquid_context(exception) |
| - | from_exception_without_liquid_context(exception).tap do |list| |
| - | if exception.respond_to?(:liquid_context) |
| - | list.first.liquid_context = exception.liquid_context |
| - | end |
| - | end |
| - | end |
| - | |
| - | end |
| - | end |
| - | |
| - | class StackFrame |
| - | include FrameWithLiquidContext |
| - | end |
| - | |
| - | end |
| \ No newline at end of file | |
locomotive/steam/monkey_patches/dragonfly.rb b/lib/locomotive/steam/monkey_patches/dragonfly.rb
+0
-79
| @@ | @@ -1,79 +0,0 @@ |
| - | module Locomotive |
| - | module Steam |
| - | class Dragonfly |
| - | |
| - | attr_accessor :path, :enabled |
| - | |
| - | def enabled? |
| - | !!self.enabled |
| - | end |
| - | |
| - | def resize_url(source, resize_string) |
| - | _source = (case source |
| - | when String then source |
| - | when Hash then source['url'] || source[:url] |
| - | else |
| - | source.try(:url) |
| - | end) |
| - | |
| - | if _source.blank? |
| - | Locomotive::Steam::Logger.error "Unable to resize on the fly: #{source.inspect}" |
| - | return |
| - | end |
| - | |
| - | return _source unless self.enabled? |
| - | |
| - | if _source =~ /^http/ |
| - | file = self.class.app.fetch_url(_source) |
| - | else |
| - | file = self.class.app.fetch_file(File.join(self.path, 'public', _source)) |
| - | end |
| - | |
| - | file.process(:thumb, resize_string).url |
| - | end |
| - | |
| - | def self.app |
| - | ::Dragonfly[:images] |
| - | end |
| - | |
| - | |
| - | def self.instance |
| - | @@instance ||= new |
| - | end |
| - | |
| - | def self.setup!(path) |
| - | self.instance.path = path |
| - | self.instance.enabled = false |
| - | |
| - | begin |
| - | require 'rack/cache' |
| - | require 'dragonfly' |
| - | |
| - | ## initialize Dragonfly ## |
| - | app = ::Dragonfly[:images].configure_with(:imagemagick) |
| - | |
| - | ## configure it ## |
| - | ::Dragonfly[:images].configure do |c| |
| - | convert = `which convert`.strip.presence || '/usr/bin/env convert' |
| - | c.convert_command = convert |
| - | c.identify_command = convert |
| - | |
| - | c.allow_fetch_url = true |
| - | c.allow_fetch_file = true |
| - | |
| - | c.url_format = '/images/dynamic/:job/:basename.:format' |
| - | end |
| - | |
| - | self.instance.enabled = true |
| - | rescue Exception => e |
| - | |
| - | Locomotive::Steam::Logger.warn %{ |
| - | [Dragonfly] !disabled! |
| - | [Dragonfly] If you want to take full benefits of all the features in the LocomotiveSteam, we recommend you to install ImageMagick and RMagick. Check out the documentation here: http://doc.locomotivecms.com/editor/installation. |
| - | } |
| - | end |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/monkey_patches/haml.rb b/lib/locomotive/steam/monkey_patches/haml.rb
+3
-1
| @@ | @@ -1,3 +1,5 @@ |
| + | require 'haml' |
| + | |
| module Haml::Filters | |
| remove_filter("Markdown") #remove the existing Markdown filter | |
| @@ | @@ -7,7 +9,7 @@ module Haml::Filters |
| include Haml::Filters::Base | |
| def render text | |
| - | Locomotive::Steam::Markdown.steam text |
| + | Locomotive::Steam::Markdown.new.render text |
| end | |
| end | |
locomotive/steam/monkey_patches/httparty.rb b/lib/locomotive/steam/monkey_patches/httparty.rb
+0
-46
| @@ | @@ -1,46 +0,0 @@ |
| - | require 'uri' |
| - | |
| - | module Locomotive |
| - | module Steam |
| - | module Httparty |
| - | class Webservice |
| - | |
| - | include ::HTTParty |
| - | |
| - | def self.consume(url, options = {}) |
| - | url = ::HTTParty.normalize_base_uri(url) |
| - | |
| - | uri = URI.parse(url) |
| - | options[:base_uri] = "#{uri.scheme}://#{uri.host}" |
| - | options[:base_uri] += ":#{uri.port}" if uri.port != 80 |
| - | path = uri.request_uri |
| - | |
| - | options.delete(:format) if options[:format] == 'default' |
| - | |
| - | username, password = options.delete(:username), options.delete(:password) |
| - | options[:basic_auth] = { username: username, password: password } if username |
| - | |
| - | path ||= '/' |
| - | |
| - | # Locomotive::Steam::Logger.debug "[WebService] consuming #{path}, #{options.inspect}" |
| - | |
| - | response = self.get(path, options) |
| - | |
| - | if response.code == 200 |
| - | _response = response.parsed_response |
| - | if _response.respond_to?(:underscore_keys) |
| - | _response.underscore_keys |
| - | else |
| - | _response.collect(&:underscore_keys) |
| - | end |
| - | else |
| - | Locomotive::Steam::Logger.error "[WebService] consumed #{path}, #{options.inspect}, response = #{response.inspect}" |
| - | nil |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/monkey_patches/mounter.rb b/lib/locomotive/steam/monkey_patches/mounter.rb
+22
-0
| @@ | @@ -1,3 +1,5 @@ |
| + | require 'locomotive/mounter' |
| + | |
| module Locomotive | |
| module Mounter | |
| module Models | |
| @@ | @@ -28,5 +30,25 @@ module Locomotive |
| end | |
| end | |
| + | |
| + | module Reader |
| + | module FileSystem |
| + | class Runner |
| + | |
| + | def new_mounting_point(host) |
| + | self.mounting_point |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| + | |
| + | class MountingPoint |
| + | |
| + | def assets_path |
| + | File.join(self.path, 'public') |
| + | end |
| + | |
| + | end |
| end | |
| end | |
| \ No newline at end of file | |
locomotive/steam/server.rb b/lib/locomotive/steam/server.rb
+33
-58
| @@ | @@ -1,80 +1,55 @@ |
| - | require 'better_errors' |
| - | require 'coffee_script' |
| - | |
| - | require_relative 'listen' |
| - | require_relative 'server/middleware' |
| - | require_relative 'server/favicon' |
| - | require_relative 'server/dynamic_assets' |
| - | require_relative 'server/logging' |
| - | require_relative 'server/entry_submission' |
| - | require_relative 'server/path' |
| - | require_relative 'server/locale' |
| - | require_relative 'server/page' |
| - | require_relative 'server/timezone' |
| - | require_relative 'server/templatized_page' |
| - | require_relative 'server/renderer' |
| - | |
| - | require_relative 'liquid' |
| - | require_relative 'initializers' |
| + | require_relative 'core_ext' |
| require_relative 'monkey_patches' | |
| + | require_relative 'liquid' |
| + | require_relative 'services' |
| + | require_relative 'middlewares' |
| module Locomotive::Steam | |
| class Server | |
| - | def initialize(reader, options = {}) |
| - | Locomotive::Steam::Dragonfly.setup!(reader.mounting_point.path) |
| - | |
| - | Sprockets::Sass.add_sass_functions = false |
| + | attr_reader :reader, :app, :options |
| - | @reader = reader |
| - | @app = self.create_rack_app(@reader) |
| + | def initialize(reader, options = {}) |
| + | @reader = reader |
| + | @options = options |
| - | BetterErrors.application_root = reader.mounting_point.path |
| + | stack = Middlewares::Stack.new(options) |
| + | @app = stack.create |
| end | |
| def call(env) | |
| - | env['steam.mounting_point'] = @reader.mounting_point |
| - | @app.call(env) |
| + | dup._call(env) # thread-safe purpose |
| end | |
| - | protected |
| - | |
| - | def create_rack_app(reader) |
| - | Rack::Builder.new do |
| - | use Rack::Lint |
| - | |
| - | use BetterErrors::MiddlewareWrapper |
| - | |
| - | use Rack::Session::Cookie, { |
| - | key: 'steam.session', |
| - | path: '/', |
| - | expire_after: 2592000, |
| - | secret: 'uselessinlocal' |
| - | } |
| + | def _call(env) |
| + | set_request(env) |
| - | use ::Dragonfly::Middleware, :images |
| + | set_mounting_point(env) |
| - | use Rack::Static, { |
| - | urls: ['/images', '/fonts', '/samples', '/media'], |
| - | root: File.join(reader.mounting_point.path, 'public') |
| - | } |
| + | set_services(env) |
| - | use Favicon |
| - | use DynamicAssets, reader.mounting_point.path |
| - | |
| - | use Logging |
| + | @app.call(env) |
| + | end |
| - | use EntrySubmission |
| + | protected |
| - | use Path |
| - | use Locale |
| - | use Timezone |
| + | def set_request(env) |
| + | @request = Rack::Request.new(env) |
| + | env['steam.request'] = @request |
| + | end |
| - | use Page |
| - | use TemplatizedPage |
| + | def set_mounting_point(env) |
| + | # one single mounting point per site |
| + | @mounting_point = @reader.new_mounting_point(@request.host) |
| + | env['steam.mounting_point'] = @reader.mounting_point |
| + | end |
| - | run Renderer.new |
| - | end |
| + | def set_services(env) |
| + | env['steam.services'] = { |
| + | dragonfly: Locomotive::Steam::Services::Dragonfly.new(@mounting_point.path), |
| + | markdown: Locomotive::Steam::Services::Markdown.new, |
| + | external_api: Locomotive::Steam::Services::ExternalAPI.new |
| + | } |
| end | |
| end | |
locomotive/steam/server/dynamic_assets.rb b/lib/locomotive/steam/server/dynamic_assets.rb
+0
-33
| @@ | @@ -1,33 +0,0 @@ |
| - | module Locomotive::Steam |
| - | class Server |
| - | |
| - | class DynamicAssets < Middleware |
| - | |
| - | attr_reader :app, :sprockets, :regexp |
| - | |
| - | def initialize(app, site_path) |
| - | super(app) |
| - | |
| - | @regexp = /^\/(javascripts|stylesheets)\/(.*)$/ |
| - | |
| - | @sprockets = Locomotive::Mounter::Extensions::Sprockets.environment(site_path) |
| - | end |
| - | |
| - | def call(env) |
| - | if env['PATH_INFO'] =~ self.regexp |
| - | env['PATH_INFO'] = $2 |
| - | |
| - | begin |
| - | self.sprockets.call(env) |
| - | rescue Exception => e |
| - | raise Locomotive::Steam::DefaultException.new "Unable to serve a dynamic asset. Please check the logs.", e |
| - | end |
| - | else |
| - | app.call(env) |
| - | end |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/server/entry_submission.rb b/lib/locomotive/steam/server/entry_submission.rb
+0
-120
| @@ | @@ -1,120 +0,0 @@ |
| - | module Locomotive::Steam |
| - | class Server |
| - | |
| - | # Mimic the submission of a content entry |
| - | # |
| - | class EntrySubmission < Middleware |
| - | |
| - | def call(env) |
| - | self.set_accessors(env) |
| - | |
| - | if self.request.post? && env['PATH_INFO'] =~ /^\/entry_submissions\/(.*)/ |
| - | self.process_form($1) |
| - | |
| - | # puts "html? #{html?} / json? #{json?} / #{self.callback_url} / #{params.inspect}" |
| - | |
| - | if @entry.valid? |
| - | if self.html? |
| - | self.record_submitted_entry |
| - | self.redirect_to self.callback_url |
| - | elsif self.json? |
| - | self.json_response |
| - | end |
| - | else |
| - | if self.html? |
| - | if self.callback_url =~ /^http:\/\// |
| - | self.redirect_to self.callback_url |
| - | else |
| - | env['PATH_INFO'] = self.callback_url |
| - | self.liquid_assigns[@content_type.slug.singularize] = @entry |
| - | app.call(env) |
| - | end |
| - | elsif self.json? |
| - | self.json_response(422) |
| - | end |
| - | end |
| - | else |
| - | self.fetch_submitted_entry |
| - | |
| - | app.call(env) |
| - | end |
| - | end |
| - | |
| - | protected |
| - | |
| - | def record_submitted_entry |
| - | self.request.session[:now] ||= {} |
| - | self.request.session[:now][:submitted_entry] = [@content_type.slug, @entry._slug] |
| - | end |
| - | |
| - | def fetch_submitted_entry |
| - | if data = self.request.session[:now].try(:delete, :submitted_entry) |
| - | content_type = self.mounting_point.content_types[data.first.to_s] |
| - | |
| - | entry = (content_type.entries || []).detect { |e| e._slug == data.last } |
| - | |
| - | # do not keep track of the entry |
| - | content_type.entries.delete(entry) if entry |
| - | |
| - | # add it to the additional liquid assigns for the next liquid rendering |
| - | if entry |
| - | self.liquid_assigns[content_type.slug.singularize] = entry |
| - | end |
| - | end |
| - | end |
| - | |
| - | # Mimic the creation of a content entry with a minimal validation. |
| - | # |
| - | # @param [ String ] permalink The permalink (or slug) of the content type |
| - | # |
| - | # |
| - | def process_form(permalink) |
| - | permalink = permalink.split('.').first |
| - | |
| - | @content_type = self.mounting_point.content_types[permalink] |
| - | |
| - | raise "Unknown content type '#{@content_type.inspect}'" if @content_type.nil? |
| - | |
| - | attributes = self.params[:entry] || self.params[:content] || {} |
| - | |
| - | @entry = @content_type.build_entry(attributes) |
| - | |
| - | # if not valid, we do not need to keep track of the entry |
| - | @content_type.entries.delete(@entry) if !@entry.valid? |
| - | end |
| - | |
| - | def callback_url |
| - | (@entry.valid? ? params[:success_callback] : params[:error_callback]) || '/' |
| - | end |
| - | |
| - | # Build the JSON response |
| - | # |
| - | # @param [ Integer ] status The HTTP return code |
| - | # |
| - | # @return [ Array ] The rack response depending on the validation status and the requested format |
| - | # |
| - | def json_response(status = 200) |
| - | locale = self.mounting_point.default_locale |
| - | |
| - | if self.request.path =~ /^\/(#{self.mounting_point.locales.join('|')})+(\/|$)/ |
| - | locale = $1 |
| - | end |
| - | |
| - | hash = @entry.to_hash(false).tap do |_hash| |
| - | if !@entry.valid? |
| - | _hash['errors'] = @entry.errors.inject({}) do |memo, name| |
| - | memo[name] = ::I18n.t('errors.messages.blank', locale: locale) |
| - | memo |
| - | end |
| - | end |
| - | end |
| - | |
| - | [status, { 'Content-Type' => 'application/json' }, [ |
| - | { @content_type.slug.singularize => hash }.to_json |
| - | ]] |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/server/favicon.rb b/lib/locomotive/steam/server/favicon.rb
+0
-18
| @@ | @@ -1,18 +0,0 @@ |
| - | module Locomotive::Steam |
| - | class Server |
| - | |
| - | class Favicon < Middleware |
| - | |
| - | def call(env) |
| - | |
| - | if env['PATH_INFO'] == '/favicon.ico' |
| - | [200, { 'Content-Type' => 'image/vnd.microsoft.icon' }, ['']] |
| - | else |
| - | app.call(env) |
| - | end |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/server/locale.rb b/lib/locomotive/steam/server/locale.rb
+0
-42
| @@ | @@ -1,42 +0,0 @@ |
| - | module Locomotive::Steam |
| - | class Server |
| - | |
| - | # Set the locale from the path if possible or use the default one |
| - | # Examples: |
| - | # /fr/index => locale = :fr |
| - | # /fr/ => locale = :fr |
| - | # /index => locale = :en (default one) |
| - | # |
| - | class Locale < Middleware |
| - | |
| - | def call(env) |
| - | self.set_accessors(env) |
| - | |
| - | self.set_locale!(env) |
| - | |
| - | app.call(env) |
| - | end |
| - | |
| - | protected |
| - | |
| - | def set_locale!(env) |
| - | locale = self.mounting_point.default_locale |
| - | |
| - | if self.path =~ /^(#{self.mounting_point.locales.join('|')})+(\/|$)/ |
| - | locale = $1 |
| - | self.path = self.path.gsub($1 + $2, '') |
| - | self.path = 'index' if self.path.blank? |
| - | end |
| - | |
| - | Locomotive::Mounter.locale = locale |
| - | ::I18n.locale = locale |
| - | |
| - | self.log "Detecting locale #{locale.upcase}" |
| - | |
| - | env['steam.locale'] = locale |
| - | env['steam.path'] = self.path |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/server/logging.rb b/lib/locomotive/steam/server/logging.rb
+0
-32
| @@ | @@ -1,32 +0,0 @@ |
| - | module Locomotive::Steam |
| - | class Server |
| - | |
| - | # Track the request into the current logger |
| - | # |
| - | class Logging < Middleware |
| - | |
| - | def call(env) |
| - | now = Time.now |
| - | |
| - | log "Started #{env['REQUEST_METHOD'].upcase} \"#{env['PATH_INFO']}\" at #{now}".light_white |
| - | |
| - | app.call(env).tap do |response| |
| - | done_in_ms = ((Time.now - now) * 10000).truncate / 10.0 |
| - | log "Completed #{code_to_human(response.first)} in #{done_in_ms}ms\n\n".green |
| - | end |
| - | end |
| - | |
| - | protected |
| - | |
| - | def code_to_human(code) |
| - | case code.to_i |
| - | when 200 then '200 OK' |
| - | when 301 then '301 Found' |
| - | when 302 then '302 Found' |
| - | when 404 then '404 Not Found' |
| - | end |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/server/middleware.rb b/lib/locomotive/steam/server/middleware.rb
+0
-61
| @@ | @@ -1,61 +0,0 @@ |
| - | module Locomotive::Steam |
| - | class Server |
| - | |
| - | class Middleware |
| - | |
| - | attr_accessor :app, :request, :path, :liquid_assigns |
| - | |
| - | attr_accessor :mounting_point, :page, :content_entry |
| - | |
| - | def initialize(app = nil) |
| - | @app = app |
| - | end |
| - | |
| - | def call(env) |
| - | app.call(env) |
| - | end |
| - | |
| - | protected |
| - | |
| - | def set_accessors(env) |
| - | self.path = env['steam.path'] |
| - | self.request = Rack::Request.new(env) |
| - | self.mounting_point = env['steam.mounting_point'] |
| - | self.page = env['steam.page'] |
| - | self.content_entry = env['steam.content_entry'] |
| - | |
| - | env['steam.liquid_assigns'] ||= {} |
| - | self.liquid_assigns = env['steam.liquid_assigns'] |
| - | end |
| - | |
| - | def site |
| - | self.mounting_point.site |
| - | end |
| - | |
| - | def params |
| - | self.request.params.deep_symbolize_keys |
| - | end |
| - | |
| - | def html? |
| - | ['text/html', 'application/x-www-form-urlencoded'].include?(self.request.media_type) && |
| - | !self.request.xhr? && |
| - | !self.json? |
| - | end |
| - | |
| - | def json? |
| - | self.request.content_type == 'application/json' || File.extname(self.request.path) == '.json' |
| - | end |
| - | |
| - | def redirect_to(location, type = 301) |
| - | self.log "Redirected to #{location}" |
| - | [type, { 'Content-Type' => 'text/html', 'Location' => location }, []] |
| - | end |
| - | |
| - | def log(msg) |
| - | Locomotive::Steam::Logger.info msg |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/server/page.rb b/lib/locomotive/steam/server/page.rb
+0
-69
| @@ | @@ -1,69 +0,0 @@ |
| - | module Locomotive::Steam |
| - | class Server |
| - | |
| - | # Sanitize the path from the previous middleware in order |
| - | # to make it work for the renderer. |
| - | # |
| - | class Page < Middleware |
| - | |
| - | def call(env) |
| - | self.set_accessors(env) |
| - | |
| - | self.set_page!(env) |
| - | |
| - | app.call(env) |
| - | end |
| - | |
| - | protected |
| - | |
| - | def set_page!(env) |
| - | page = self.fetch_page |
| - | |
| - | if page |
| - | self.log "Found page \"#{page.title}\" [#{page.safe_fullpath}]" |
| - | end |
| - | |
| - | env['steam.page'] = page |
| - | end |
| - | |
| - | def fetch_page |
| - | |
| - | |
| - | matchers = self.path_combinations(self.path) |
| - | |
| - | pages = self.mounting_point.pages.values.find_all do |_page| |
| - | matchers.include?(_page.safe_fullpath) || |
| - | matchers.include?(_page.safe_fullpath.try(:underscore)) |
| - | end.sort_by { |p| p.position || Float::INFINITY } |
| - | |
| - | if pages.size > 1 |
| - | self.log "Found multiple pages: #{pages.collect(&:title).join(', ')}" |
| - | end |
| - | |
| - | pages.first |
| - | end |
| - | |
| - | def path_combinations(path) |
| - | self._path_combinations(path.split('/')) |
| - | end |
| - | |
| - | def _path_combinations(segments, can_include_template = true) |
| - | return nil if segments.empty? |
| - | |
| - | segment = segments.shift |
| - | |
| - | (can_include_template ? [segment, '*'] : [segment]).map do |_segment| |
| - | if (_combinations = _path_combinations(segments.clone, can_include_template && _segment != '*')) |
| - | [*_combinations].map do |_combination| |
| - | File.join(_segment, _combination) |
| - | end |
| - | else |
| - | [_segment] |
| - | end |
| - | end.flatten |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
locomotive/steam/server/path.rb b/lib/locomotive/steam/server/path.rb
+0
-34
| @@ | @@ -1,34 +0,0 @@ |
| - | module Locomotive::Steam |
| - | class Server |
| - | |
| - | # Sanitize the path from the previous middleware in order |
| - | # to make it work for the renderer. |
| - | # |
| - | class Path < Middleware |
| - | |
| - | def call(env) |
| - | self.set_accessors(env) |
| - | |
| - | self.set_path!(env) |
| - | |
| - | app.call(env) |
| - | end |
| - | |
| - | protected |
| - | |
| - | def set_path!(env) |
| - | path = env['PATH_INFO'].clone |
| - | |
| - | path.gsub!(/\.[a-zA-Z][a-zA-Z0-9]{2,}$/, '') |
| - | path.gsub!(/^\//, '') |
| - | path.gsub!(/^[A-Z]:\//, '') |
| - | |
| - | path = 'index' if path.blank? |
| - | |
| - | env['steam.path'] = path |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/server/renderer.rb b/lib/locomotive/steam/server/renderer.rb
+0
-118
| @@ | @@ -1,118 +0,0 @@ |
| - | module Locomotive::Steam |
| - | class Server |
| - | |
| - | class Renderer < Middleware |
| - | |
| - | def call(env) |
| - | self.set_accessors(env) |
| - | |
| - | if self.page |
| - | if self.page.redirect? |
| - | self.redirect_to(self.page.redirect_url, self.page.redirect_type) |
| - | else |
| - | type = self.page.response_type || 'text/html' |
| - | html = self.render_page |
| - | |
| - | self.log 'Rendered liquid page template' |
| - | |
| - | [200, { 'Content-Type' => type }, [html]] |
| - | end |
| - | else |
| - | [404, { 'Content-Type' => 'text/html' }, [self.render_404]] |
| - | end |
| - | end |
| - | |
| - | protected |
| - | |
| - | def render_page |
| - | context = self.locomotive_context |
| - | begin |
| - | self.page.render(context) |
| - | rescue Exception => e |
| - | raise RendererException.new(e, self.page.title, self.page.template, context) |
| - | end |
| - | end |
| - | |
| - | def render_404 |
| - | if self.page = self.mounting_point.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.mounting_point.default_locale.to_s, |
| - | 'locales' => self.mounting_point.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, |
| - | mounting_point: self.mounting_point, |
| - | inline_editor: false, |
| - | logger: Locomotive::Steam::Logger |
| - | } |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/server/templatized_page.rb b/lib/locomotive/steam/server/templatized_page.rb
+0
-32
| @@ | @@ -1,32 +0,0 @@ |
| - | module Locomotive::Steam |
| - | class Server |
| - | |
| - | class TemplatizedPage < Middleware |
| - | |
| - | def call(env) |
| - | self.set_accessors(env) |
| - | |
| - | if self.page && self.page.templatized? |
| - | self.set_content_entry!(env) |
| - | end |
| - | |
| - | app.call(env) |
| - | end |
| - | |
| - | protected |
| - | |
| - | def set_content_entry!(env) |
| - | %r(^#{self.page.safe_fullpath.gsub('*', '([^\/]+)')}$) =~ self.path |
| - | |
| - | permalink = $1 |
| - | |
| - | if content_entry = self.page.content_type.find_entry(permalink) |
| - | env['steam.content_entry'] = content_entry |
| - | else |
| - | env['steam.page'] = nil |
| - | end |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/server/timezone.rb b/lib/locomotive/steam/server/timezone.rb
+0
-18
| @@ | @@ -1,18 +0,0 @@ |
| - | module Locomotive::Steam |
| - | class Server |
| - | |
| - | # Set the timezone according to the settings of the site |
| - | # |
| - | class Timezone < Middleware |
| - | |
| - | def call(env) |
| - | self.set_accessors(env) |
| - | |
| - | Time.use_zone(site.try(:timezone) || 'UTC') do |
| - | app.call(env) |
| - | end |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/services.rb b/lib/locomotive/steam/services.rb
+1
-0
| @@ | @@ -0,0 +1 @@ |
| + | Dir[File.join(File.dirname(__FILE__), 'services', '*.rb')].each { |lib| require lib } |
| \ No newline at end of file | |
locomotive/steam/services/dragonfly.rb b/lib/locomotive/steam/services/dragonfly.rb
+49
-0
| @@ | @@ -0,0 +1,49 @@ |
| + | module Locomotive |
| + | module Steam |
| + | module Services |
| + | class Dragonfly |
| + | |
| + | attr_reader :path |
| + | |
| + | def initialize(path = nil) |
| + | @path = path |
| + | end |
| + | |
| + | def enabled? |
| + | !!self.enabled |
| + | end |
| + | |
| + | def resize_url(source, resize_string) |
| + | image = (case url_or_path = get_url_or_path(source) |
| + | when '', nil |
| + | Locomotive::Steam::Logger.error "Unable to resize on the fly: #{source.inspect}" |
| + | nil |
| + | when /^http:\/\// |
| + | app.fetch_url(url_or_path) |
| + | else |
| + | app.fetch_file(File.join([self.path, 'public', url_or_path].compact)) |
| + | end) |
| + | |
| + | # apply the conversion if possible |
| + | image ? image.thumb(resize_string).url : source |
| + | end |
| + | |
| + | def self.app |
| + | ::Dragonfly.app |
| + | end |
| + | |
| + | protected |
| + | |
| + | def get_url_or_path(source) |
| + | case source |
| + | when String then source.strip |
| + | when Hash then source['url'] || source[:url] |
| + | else |
| + | source.try(:url) |
| + | end |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/services/external_api.rb b/lib/locomotive/steam/services/external_api.rb
+46
-0
| @@ | @@ -0,0 +1,46 @@ |
| + | require 'uri' |
| + | |
| + | module Locomotive |
| + | module Steam |
| + | module Services |
| + | class ExternalAPI |
| + | |
| + | include ::HTTParty |
| + | |
| + | def consume(url, options = {}) |
| + | url = ::HTTParty.normalize_base_uri(url) |
| + | |
| + | uri = URI.parse(url) |
| + | options[:base_uri] = "#{uri.scheme}://#{uri.host}" |
| + | options[:base_uri] += ":#{uri.port}" if uri.port != 80 |
| + | path = uri.request_uri |
| + | |
| + | options.delete(:format) if options[:format] == 'default' |
| + | |
| + | username, password = options.delete(:username), options.delete(:password) |
| + | options[:basic_auth] = { username: username, password: password } if username |
| + | |
| + | path ||= '/' |
| + | |
| + | # Locomotive::Steam::Logger.debug "[WebService] consuming #{path}, #{options.inspect}" |
| + | |
| + | response = self.class.get(path, options) |
| + | |
| + | if response.code == 200 |
| + | _response = response.parsed_response |
| + | if _response.respond_to?(:underscore_keys) |
| + | _response.underscore_keys |
| + | else |
| + | _response.collect(&:underscore_keys) |
| + | end |
| + | else |
| + | Locomotive::Steam::Logger.error "[WebService] consumed #{path}, #{options.inspect}, response = #{response.inspect}" |
| + | nil |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/services/markdown.rb b/lib/locomotive/steam/services/markdown.rb
+29
-0
| @@ | @@ -0,0 +1,29 @@ |
| + | require 'redcarpet' |
| + | |
| + | module Locomotive |
| + | module Steam |
| + | module Services |
| + | class Markdown |
| + | |
| + | def render(text) |
| + | self.class.parser.render(text) |
| + | end |
| + | |
| + | def self.parser |
| + | @@markdown ||= Redcarpet::Markdown.new Redcarpet::Steam::HTML, { |
| + | autolink: true, |
| + | fenced_code: true, |
| + | generate_toc: true, |
| + | gh_blockcode: true, |
| + | hard_wrap: true, |
| + | no_intraemphasis: true, |
| + | strikethrough: true, |
| + | tables: true, |
| + | xhtml: true |
| + | } |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| + | end |
| \ No newline at end of file | |
locomotive/steam/standalone_server.rb b/lib/locomotive/steam/standalone_server.rb
+1
-1
| @@ | @@ -23,7 +23,7 @@ module Locomotive |
| Bundler.require 'initializers' | |
| # run the rack app | |
| - | super(reader, disable_listen: true) |
| + | super(reader, serve_assets: true) |
| end | |
| end | |
| end | |
locomotivecms_steam.gemspec
+9
-9
| @@ | @@ -29,15 +29,15 @@ Gem::Specification.new do |spec| |
| spec.add_development_dependency 'rack-test' | |
| spec.add_development_dependency 'i18n-spec' | |
| - | spec.add_dependency 'rack-cache', '~> 1.1' |
| - | spec.add_dependency 'sprockets', '~> 2.0' |
| - | spec.add_dependency 'sprockets-sass', '~> 1.0' |
| - | spec.add_dependency 'better_errors', '~> 1.0' |
| - | spec.add_dependency 'dragonfly', '~> 0.9' |
| - | spec.add_dependency 'activesupport', '~> 3.2' |
| - | spec.add_dependency 'listen', '~> 2.7' |
| - | spec.add_dependency 'will_paginate', '~> 3.0' |
| - | spec.add_dependency 'redcarpet', '~> 3.1' |
| + | spec.add_dependency 'rack-cache', '~> 1.1' |
| + | spec.add_dependency 'moneta', '~> 0.7.20' |
| + | spec.add_dependency 'sprockets', '~> 2.0' |
| + | spec.add_dependency 'sprockets-sass', '~> 1.0' |
| + | # spec.add_dependency 'better_errors', '~> 1.0' |
| + | spec.add_dependency 'dragonfly', '~> 1.0.3' |
| + | spec.add_dependency 'activesupport', '~> 3.2' # TODO: upgrade to 4.x |
| + | spec.add_dependency 'will_paginate', '~> 3.0' # TODO: move to kaminari |
| + | spec.add_dependency 'redcarpet', '~> 3.1' |
| spec.add_dependency 'locomotivecms_mounter' | |
| spec.add_dependency 'locomotivecms-solid' | |
spec/integration/server/basic_spec.rb
+0
-2
| @@ | @@ -13,9 +13,7 @@ describe Locomotive::Steam::Server do |
| end | |
| it 'shows the index page' do | |
| - | |
| get '/index' | |
| - | |
| last_response.body.should =~ /Upcoming events/ | |
| end | |
spec/support/helpers.rb
+4
-2
| @@ | @@ -6,7 +6,7 @@ module Spec |
| end | |
| def remove_logs | |
| - | FileUtils.rm_rf(File.expand_path('../../fixtures/default/log', __FILE__)) |
| + | # FileUtils.rm_rf(File.expand_path('../../fixtures/default/log', __FILE__)) |
| end | |
| def run_server | |
| @@ | @@ -15,7 +15,9 @@ module Spec |
| reader = Locomotive::Mounter::Reader::FileSystem.instance | |
| reader.run!(path: path) | |
| - | Locomotive::Steam::Server.new(reader, disable_listen: true) |
| + | require 'locomotive/steam/initializers' |
| + | |
| + | Locomotive::Steam::Server.new(reader) |
| end | |
| end | |