integrating Steam [WIP]
did
committed Mar 29, 2015
commit c0b0e9b3f090a88547221a3ffe6e57d3bdd825d7
Showing 58
changed files with
111 additions
and 3220 deletions
Gemfile
+4
-0
| @@ | @@ -13,6 +13,10 @@ gem 'rb-fsevent', '~> 0.9.1' |
| gem 'therubyracer' | |
| + | gem 'locomotivecms_steam', github: 'locomotivecms/steam', ref: '53a910eb6e', require: false |
| + | gem 'locomotivecms_coal', github: 'locomotivecms/coal', ref: '6ae10e3684', require: false |
| + | |
| + | |
| group :test do | |
| gem 'pry' | |
| gem 'coveralls', require: false | |
README.md
+1
-1
| @@ | @@ -37,7 +37,7 @@ Please, visit the documentation website of LocomotiveCMS. |
| #### Run the server with a default site | |
| - | $ bundle exec bin/wagon serve <path to the mounter gem>/spec/fixtures/default |
| + | $ bundle exec bin/wagon serve spec/fixtures/default |
| #### Push a site | |
locomotive/wagon.rb b/lib/locomotive/wagon.rb
+105
-72
| @@ | @@ -72,62 +72,28 @@ module Locomotive |
| # @param [ Hash ] options The options for the thin server (host, port) | |
| # | |
| def self.serve(path, options) | |
| - | if reader = self.require_mounter(path, true) |
| - | use_listen = !options[:disable_listen] |
| - | |
| - | if options[:force] |
| - | begin |
| - | self.stop(path) |
| - | sleep(2) # make sure we wait enough for the server process to stop |
| - | rescue |
| - | end |
| - | end |
| - | |
| - | # TODO: new feature -> pick the right Rack handler (Thin, Puma, ...etc) |
| - | server = self.thin_server(reader, options.slice(:host, :port, :disable_listen, :live_reload_port)) |
| + | self.require_steam(path) |
| - | if options[:daemonize] |
| - | # very important to get the parent pid in order to differenciate the sub process from the parent one |
| - | parent_pid = Process.pid |
| + | server = self.build_server(options) |
| + | use_listen = !options[:disable_listen] |
| - | # The Daemons gem closes all file descriptors when it daemonizes the process. So any logfiles that were opened before the Daemons block will be closed inside the forked process. |
| - | # So, close the current logger and set it up again when daemonized. |
| - | Locomotive::Wagon::Logger.close |
| - | |
| - | server.log_file = File.join(File.expand_path(path), 'log', 'server.log') |
| - | server.pid_file = File.join(File.expand_path(path), 'log', 'server.pid') |
| - | server.daemonize |
| - | |
| - | use_listen = Process.pid != parent_pid && !options[:disable_listen] |
| - | |
| - | if Process.pid != parent_pid |
| - | # A "new logger" inside the daemon. |
| - | Locomotive::Wagon::Logger.setup(path, false) |
| - | Locomotive::Mounter.logger = Locomotive::Wagon::Logger.instance.logger |
| - | end |
| - | end |
| + | self.stop(path, true) if options[:force] |
| - | # listen_thread = Thread.new do |
| - | Locomotive::Wagon::Listen.instance.start(reader) if use_listen |
| + | use_listen = self.daemonize(path, server, use_listen) if options[:daemonize] |
| - | server.start |
| - | # end |
| + | # TODO |
| + | # Locomotive::Wagon::Listen.instance.start(reader) if use_listen |
| - | # server_thread = Thread.new { server.start } |
| - | |
| - | # hit Control + C to stop |
| - | # Signal.trap('INT') { EventMachine.stop } |
| - | # Signal.trap('TERM') { EventMachine.stop } |
| - | |
| - | # listen_thread.join |
| - | # server_thread.join |
| - | end |
| + | server.start |
| end | |
| - | def self.stop(path) |
| + | def self.stop(path, force = false) |
| pid_file = File.join(File.expand_path(path), 'log', 'server.pid') | |
| pid = File.read(pid_file).to_i | |
| Process.kill('TERM', pid) | |
| + | |
| + | # make sure we wait enough for the server process to stop |
| + | sleep(2) if force |
| end | |
| # Generate components for the LocomotiveCMS site such as content types, snippets, pages. | |
| @@ | @@ -234,52 +200,119 @@ module Locomotive |
| Locomotive::Mounter::EngineApi.delete('/current_site.json') | |
| end | |
| - | # Load the Locomotive::Mounter lib and set it up (logger, ...etc). |
| - | # If the second parameter is set to true, then the method builds |
| - | # an instance of the reader from the path passed in first parameter. |
| - | # |
| - | # @param [ String ] path The path to the local site |
| - | # @param [ Boolean ] get_reader Tell if it builds an instance of the reader. |
| - | # @param [ Boolean ] require_misc Tell if it requires the gems inside the misc bundler group |
| - | # |
| - | # @param [ Object ] An instance of the reader is the get_reader parameter has been set. |
| - | # |
| - | def self.require_mounter(path, get_reader = false, require_misc = true) |
| - | Locomotive::Wagon::Logger.setup(path, false) |
| + | def self.require_steam(path, require_misc = true) |
| + | require 'locomotive/steam' |
| - | require 'locomotive/mounter' |
| + | Locomotive::Steam.configure do |config| |
| + | config.mode = :test |
| + | config.adapter = { name: :filesystem, path: path } |
| + | config.serve_assets = true |
| + | config.asset_path = File.expand_path(File.join(path, 'public')) |
| + | config.minify_assets = false |
| + | end |
| - | Locomotive::Mounter.logger = Locomotive::Wagon::Logger.instance.logger |
| + | Locomotive::Wagon::Logger.setup(path, false) |
| if require_misc | |
| require 'bundler' | |
| Bundler.require 'misc' | |
| end | |
| - | if get_reader |
| - | begin |
| - | reader = Locomotive::Mounter::Reader::FileSystem.instance |
| - | reader.run!(path: path) |
| - | reader |
| - | rescue Exception => e |
| - | raise Locomotive::Wagon::MounterException.new "Unable to read the local LocomotiveCMS site. Please check the logs.", e |
| - | end |
| + | # logger = Locomotive::Wagon::Logger.instance.logger |
| + | # logger.info "YEAAH" |
| + | |
| + | Locomotive::Common.reset |
| + | Locomotive::Common.configure do |config| |
| + | config_file = File.expand_path(File.join(path, 'log', 'wagon.log')) |
| + | config.notifier = Locomotive::Common::Logger.setup(config_file) |
| end | |
| end | |
| - | protected |
| + | # # Load the Locomotive::Mounter lib and set it up (logger, ...etc). |
| + | # # If the second parameter is set to true, then the method builds |
| + | # # an instance of the reader from the path passed in first parameter. |
| + | # # |
| + | # # @param [ String ] path The path to the local site |
| + | # # @param [ Boolean ] get_reader Tell if it builds an instance of the reader. |
| + | # # @param [ Boolean ] require_misc Tell if it requires the gems inside the misc bundler group |
| + | # # |
| + | # # @param [ Object ] An instance of the reader is the get_reader parameter has been set. |
| + | # # |
| + | # def self.require_mounter(path, get_reader = false, require_misc = true) |
| + | # Locomotive::Wagon::Logger.setup(path, false) |
| + | |
| + | # require 'locomotive/mounter' |
| + | |
| + | # Locomotive::Mounter.logger = Locomotive::Wagon::Logger.instance.logger |
| + | |
| + | # if require_misc |
| + | # require 'bundler' |
| + | # Bundler.require 'misc' |
| + | # end |
| + | |
| + | # if get_reader |
| + | # begin |
| + | # reader = Locomotive::Mounter::Reader::FileSystem.instance |
| + | # reader.run!(path: path) |
| + | # reader |
| + | # rescue Exception => e |
| + | # raise Locomotive::Wagon::MounterException.new "Unable to read the local LocomotiveCMS site. Please check the logs.", e |
| + | # end |
| + | # end |
| + | # end |
| - | def self.thin_server(reader, options) |
| - | require 'locomotive/wagon/server' |
| - | app = Locomotive::Wagon::Server.new(reader, options) |
| + | protected |
| + | def self.build_server(options) |
| # TODO: new feature -> pick the right Rack handler (Thin, Puma, ...etc) | |
| + | |
| + | require 'locomotive/steam/server' |
| require 'thin' | |
| + | |
| + | app = Locomotive::Steam::Server.to_app |
| + | |
| Thin::Server.new(options[:host], options[:port], { signals: true }, app).tap do |server| | |
| server.threaded = true | |
| end | |
| end | |
| + | def self.daemonize_server(server, path, use_listen) |
| + | if options[:daemonize] |
| + | # very important to get the parent pid in order to differenciate the sub process from the parent one |
| + | parent_pid = Process.pid |
| + | |
| + | # The Daemons gem closes all file descriptors when it daemonizes the process. So any logfiles that were opened before the Daemons block will be closed inside the forked process. |
| + | # So, close the current logger and set it up again when daemonized. |
| + | Locomotive::Wagon::Logger.close |
| + | |
| + | server.log_file = File.join(File.expand_path(path), 'log', 'server.log') |
| + | server.pid_file = File.join(File.expand_path(path), 'log', 'server.pid') |
| + | server.daemonize |
| + | |
| + | use_listen = Process.pid != parent_pid && !options[:disable_listen] |
| + | |
| + | if Process.pid != parent_pid |
| + | # A "new logger" inside the daemon. |
| + | Locomotive::Wagon::Logger.setup(path, false) |
| + | # Locomotive::Mounter.logger = Locomotive::Wagon::Logger.instance.logger |
| + | Locomotive::Common.configure do |config| |
| + | config.notifier = Locomotive::Wagon::Logger.instance.logger |
| + | end |
| + | end |
| + | end |
| + | end |
| + | |
| + | # def self.thin_server(reader, options) |
| + | # require 'locomotive/wagon/server' |
| + | # app = Locomotive::Wagon::Server.new(reader, options) |
| + | |
| + | # # TODO: new feature -> pick the right Rack handler (Thin, Puma, ...etc) |
| + | # require 'thin' |
| + | # Thin::Server.new(options[:host], options[:port], { signals: true }, app).tap do |server| |
| + | # server.threaded = true |
| + | # end |
| + | # end |
| + | |
| def self.validate_resources(resources, writers_or_readers) | |
| return if resources.nil? | |
locomotive/wagon/liquid.rb b/lib/locomotive/wagon/liquid.rb
+0
-21
| @@ | @@ -1,21 +0,0 @@ |
| - | require 'solid' |
| - | require 'locomotive/mounter' |
| - | require 'locomotive/wagon/liquid/scopeable' |
| - | require 'locomotive/wagon/liquid/drops/base' |
| - | require 'locomotive/wagon/liquid/tags/hybrid' |
| - | require 'locomotive/wagon/liquid/tags/path_helper' |
| - | |
| - | %w{. drops tags filters}.each do |dir| |
| - | Dir[File.join(File.dirname(__FILE__), 'liquid', dir, '*.rb')].each { |lib| require lib } |
| - | end |
| - | |
| - | # add to_liquid methods to main models from the mounter |
| - | %w{site page content_entry}.each do |name| |
| - | klass = "Locomotive::Mounter::Models::#{name.classify}".constantize |
| - | |
| - | klass.class_eval <<-EOV |
| - | def to_liquid |
| - | ::Locomotive::Wagon::Liquid::Drops::#{name.classify}.new(self) |
| - | end |
| - | EOV |
| - | end |
locomotive/wagon/liquid/drops/base.rb b/lib/locomotive/wagon/liquid/drops/base.rb
+0
-46
| @@ | @@ -1,46 +0,0 @@ |
| - | # Code taken from Mephisto sources (http://mephistoblog.com/) |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Drops |
| - | class Base < ::Liquid::Drop |
| - | |
| - | @@forbidden_attributes = %w{_id _version _index} |
| - | |
| - | def initialize(source) |
| - | @_source = source |
| - | end |
| - | |
| - | def id |
| - | (@_source.respond_to?(:id) ? @_source.id : nil) || 'new' |
| - | end |
| - | |
| - | # converts an array of records to an array of liquid drops |
| - | def self.liquify(*records, &block) |
| - | i = -1 |
| - | records = |
| - | records.inject [] do |all, r| |
| - | i+=1 |
| - | attrs = (block && block.arity == 1) ? [r] : [r, i] |
| - | all << (block ? block.call(*attrs) : r.to_liquid) |
| - | all |
| - | end |
| - | records.compact! |
| - | records |
| - | end |
| - | |
| - | protected |
| - | |
| - | def liquify(*records, &block) |
| - | self.class.liquify(*records, &block) |
| - | end |
| - | |
| - | def _source |
| - | @_source |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/drops/content_entry.rb b/lib/locomotive/wagon/liquid/drops/content_entry.rb
+0
-49
| @@ | @@ -1,49 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Drops |
| - | class ContentEntry < Base |
| - | |
| - | delegate :seo_title, :meta_keywords, :meta_description, to: :@_source |
| - | |
| - | def _label |
| - | @_label ||= @_source._label |
| - | end |
| - | |
| - | def _permalink |
| - | @_source._permalink.try(:parameterize) |
| - | end |
| - | |
| - | alias :_slug :_permalink |
| - | alias :_id :_permalink |
| - | |
| - | def next |
| - | self |
| - | end |
| - | |
| - | def previous |
| - | self |
| - | end |
| - | |
| - | def errors |
| - | (@_source.errors || []).inject({}) do |memo, name| |
| - | memo[name] = ::I18n.t('errors.messages.blank') |
| - | memo |
| - | end |
| - | end |
| - | |
| - | def before_method(meth) |
| - | return '' if @_source.nil? |
| - | |
| - | if not @@forbidden_attributes.include?(meth.to_s) |
| - | @_source.send(meth) |
| - | else |
| - | nil |
| - | end |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/drops/content_types.rb b/lib/locomotive/wagon/liquid/drops/content_types.rb
+0
-119
| @@ | @@ -1,119 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Drops |
| - | class ContentTypes < ::Liquid::Drop |
| - | |
| - | def before_method(meth) |
| - | type = self.mounting_point.content_types[meth.to_s] |
| - | ProxyCollection.new(type) |
| - | end |
| - | |
| - | end |
| - | |
| - | class ProxyCollection < ::Liquid::Drop |
| - | |
| - | include Scopeable |
| - | |
| - | def initialize(content_type) |
| - | @content_type = content_type |
| - | @collection = nil |
| - | end |
| - | |
| - | def all |
| - | self.collection |
| - | end |
| - | |
| - | def any |
| - | self.collection.any? |
| - | end |
| - | |
| - | def first |
| - | self.collection.first |
| - | end |
| - | |
| - | def last |
| - | self.collection.last |
| - | end |
| - | |
| - | def size |
| - | self.collection.size |
| - | end |
| - | |
| - | alias :length :size |
| - | alias :count :size |
| - | |
| - | def each(&block) |
| - | self.collection.each(&block) |
| - | end |
| - | |
| - | def public_submission_url |
| - | "/entry_submissions/#{@content_type.slug}" |
| - | end |
| - | |
| - | def api |
| - | { 'create' => "/entry_submissions/#{@content_type.slug}" } |
| - | end |
| - | |
| - | def before_method(meth) |
| - | if (meth.to_s =~ /^group_by_(.+)$/) == 0 |
| - | self.group_entries_by(@content_type, $1) |
| - | elsif (meth.to_s =~ /^(.+)_options$/) == 0 |
| - | self.select_options_for(@content_type, $1) |
| - | else |
| - | @content_type.send(meth) |
| - | end |
| - | end |
| - | |
| - | protected |
| - | |
| - | def group_entries_by(content_type, name) |
| - | field = @content_type.find_field(name) |
| - | |
| - | return {} if field.nil? || !%w(belongs_to select).include?(field.type.to_s) |
| - | |
| - | (@content_type.entries || []).group_by do |entry| |
| - | entry.send(name.to_sym) |
| - | end.to_a.collect do |group| |
| - | { name: group.first, entries: group.last }.with_indifferent_access |
| - | end |
| - | end |
| - | |
| - | def select_options_for(content_type, name) |
| - | field = @content_type.find_field(name) |
| - | |
| - | return {} if field.nil? || field.type.to_s != 'select' |
| - | |
| - | field.select_options.map(&:name) |
| - | end |
| - | |
| - | def paginate(options = {}) |
| - | @collection = self.collection.paginate(options) |
| - | { |
| - | collection: @collection, |
| - | current_page: @collection.current_page, |
| - | previous_page: @collection.previous_page, |
| - | next_page: @collection.next_page, |
| - | total_entries: @collection.total_entries, |
| - | total_pages: @collection.total_pages, |
| - | per_page: @collection.per_page |
| - | } |
| - | end |
| - | |
| - | def collection |
| - | return @collection unless @collection.blank? |
| - | |
| - | # define the default order_by if not set |
| - | if @context['with_scope'] && @context['with_scope']['order_by'].blank? && !%w(manually position).include?(@content_type.order_by) |
| - | field = @content_type.order_by || 'created_at' |
| - | direction = @content_type.order_direction || 'asc' |
| - | @context['with_scope']['order_by'] = "#{field}.#{direction}" |
| - | end |
| - | |
| - | @collection = apply_scope(@content_type.entries) |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
locomotive/wagon/liquid/drops/page.rb b/lib/locomotive/wagon/liquid/drops/page.rb
+0
-84
| @@ | @@ -1,84 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Drops |
| - | class Page < Base |
| - | |
| - | delegate :fullpath, :parent, :depth, :seo_title, :redirect_url, :meta_description, :meta_keywords, |
| - | :templatized?, :published?, :redirect?, :listed?, :handle, to: :@_source |
| - | |
| - | def title |
| - | title = @_source.templatized? ? @context['entry'].try(:_label) : nil |
| - | title || @_source.title |
| - | end |
| - | |
| - | def slug |
| - | slug = @_source.templatized? ? @context['entry'].try(:_slug).try(:singularize) : nil |
| - | slug || @_source.slug |
| - | end |
| - | |
| - | def is_layout? |
| - | @_source.is_layout |
| - | end |
| - | |
| - | def original_title |
| - | @_source.title |
| - | end |
| - | |
| - | def original_slug |
| - | @_source.slug |
| - | end |
| - | |
| - | def children |
| - | _children = @_source.children || [] |
| - | _children = _children.sort { |a, b| a.position.to_i <=> b.position.to_i } |
| - | @children ||= liquify(*_children) |
| - | end |
| - | |
| - | def content_type |
| - | ProxyCollection.new(@_source.content_type) if @_source.content_type |
| - | end |
| - | |
| - | def editable_elements |
| - | @editable_elements_hash ||= build_editable_elements_hash |
| - | end |
| - | |
| - | def breadcrumbs |
| - | # TODO |
| - | '' |
| - | end |
| - | |
| - | private |
| - | |
| - | def build_editable_elements_hash |
| - | {}.tap do |hash| |
| - | @_source.editable_elements.each do |el| |
| - | safe_slug = el.slug.parameterize.underscore |
| - | keys = el.block.try(:split, '/').try(:compact) || [] |
| - | |
| - | _hash = _build_editable_elements_hashes(hash, keys) |
| - | |
| - | _hash[safe_slug] = el.content |
| - | end |
| - | end |
| - | end |
| - | |
| - | def _build_editable_elements_hashes(hash, keys) |
| - | _hash = hash |
| - | |
| - | keys.each do |key| |
| - | safe_key = key.parameterize.underscore |
| - | |
| - | _hash[safe_key] = {} if _hash[safe_key].nil? |
| - | |
| - | _hash = _hash[safe_key] |
| - | end |
| - | |
| - | _hash |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
locomotive/wagon/liquid/drops/session_proxy.rb b/lib/locomotive/wagon/liquid/drops/session_proxy.rb
+0
-18
| @@ | @@ -1,18 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Drops |
| - | |
| - | class SessionProxy < ::Liquid::Drop |
| - | |
| - | def before_method(meth) |
| - | request = @context.registers[:request] |
| - | request.session[meth.to_sym] |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/drops/site.rb b/lib/locomotive/wagon/liquid/drops/site.rb
+0
-26
| @@ | @@ -1,26 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Drops |
| - | class Site < Base |
| - | include Scopeable |
| - | |
| - | delegate :name, :seo_title, :meta_description, :meta_keywords, to: :@_source |
| - | |
| - | def index |
| - | @index ||= self.mounting_point.pages['index'] |
| - | end |
| - | |
| - | def pages |
| - | liquify(*apply_scope(self.mounting_point.pages.values)) |
| - | end |
| - | |
| - | def domains |
| - | @_source.domains |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
locomotive/wagon/liquid/errors.rb b/lib/locomotive/wagon/liquid/errors.rb
+0
-17
| @@ | @@ -1,17 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | class PageNotFound < ::Liquid::Error; end |
| - | |
| - | class PageNotTranslated < ::Liquid::Error; end |
| - | |
| - | class ContentEntryNotTranslated < ::Liquid::Error; end |
| - | |
| - | class UnknownConditionInScope < ::Liquid::Error; end |
| - | |
| - | class UnknownConditionInScope < ::Liquid::Error; end |
| - | |
| - | class ConnectionRefused < ::Liquid::Error; end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/filters/date.rb b/lib/locomotive/wagon/liquid/filters/date.rb
+0
-136
| @@ | @@ -1,136 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Filters |
| - | module Date |
| - | |
| - | def parse_date_time(input, format = nil) |
| - | return '' if input.blank? |
| - | |
| - | format ||= I18n.t('time.formats.default') |
| - | date_time = ::DateTime._strptime(input, format) |
| - | |
| - | if date_time |
| - | ::Time.zone.local(date_time[:year], date_time[:mon], date_time[:mday], date_time[:hour], date_time[:min], date_time[:sec] || 0) |
| - | else |
| - | ::Time.zone.parse(input) rescue '' |
| - | end |
| - | end |
| - | |
| - | def parse_date(input, format) |
| - | return '' if input.blank? |
| - | |
| - | format ||= I18n.t('date.formats.default') |
| - | date = ::Date._strptime(input, format) |
| - | |
| - | if date |
| - | ::Date.new(date[:year], date[:mon], date[:mday]) |
| - | else |
| - | ::Date.parse(value) rescue '' |
| - | end |
| - | end |
| - | |
| - | def localized_date(input, *args) |
| - | return '' if input.blank? |
| - | |
| - | format, locale = args |
| - | |
| - | locale ||= I18n.locale |
| - | format ||= I18n.t('date.formats.default', locale: locale) |
| - | |
| - | if input.is_a?(String) |
| - | begin |
| - | fragments = ::Date._strptime(input, format) |
| - | input = ::Date.new(fragments[:year], fragments[:mon], fragments[:mday]) |
| - | rescue |
| - | input = Time.zone.parse(input) |
| - | end |
| - | end |
| - | |
| - | return input.to_s unless input.respond_to?(:strftime) |
| - | |
| - | I18n.l input, format: format, locale: locale |
| - | end |
| - | |
| - | alias :format_date :localized_date |
| - | |
| - | def distance_of_time_in_words(input, from_time = Time.zone.now, include_seconds = false) |
| - | return '' if input.blank? |
| - | |
| - | # make sure we deals with instances of Time |
| - | to_time = to_time(input) |
| - | from_time = to_time(from_time) |
| - | |
| - | from_time = from_time.to_time if from_time.respond_to?(:to_time) |
| - | to_time = to_time.to_time if to_time.respond_to?(:to_time) |
| - | distance_in_minutes = (((to_time - from_time).abs)/60).round |
| - | distance_in_seconds = ((to_time - from_time).abs).round |
| - | |
| - | ::I18n.with_options({ scope: :'datetime.distance_in_words' }) do |locale| |
| - | |
| - | case distance_in_minutes |
| - | when 0..1 |
| - | return distance_in_minutes == 0 ? |
| - | locale.t(:less_than_x_minutes, count: 1) : |
| - | locale.t(:x_minutes, count: distance_in_minutes) unless include_seconds |
| - | |
| - | case distance_in_seconds |
| - | when 0..4 then locale.t :less_than_x_seconds, count: 5 |
| - | when 5..9 then locale.t :less_than_x_seconds, count: 10 |
| - | when 10..19 then locale.t :less_than_x_seconds, count: 20 |
| - | when 20..39 then locale.t :half_a_minute |
| - | when 40..59 then locale.t :less_than_x_minutes, count: 1 |
| - | else locale.t :x_minutes, count: 1 |
| - | end |
| - | |
| - | when 2..44 then locale.t :x_minutes, count: distance_in_minutes |
| - | when 45..89 then locale.t :about_x_hours, count: 1 |
| - | when 90..1439 then locale.t :about_x_hours, count: (distance_in_minutes.to_f / 60.0).round |
| - | when 1440..2519 then locale.t :x_days, count: 1 |
| - | when 2520..43199 then locale.t :x_days, count: (distance_in_minutes.to_f / 1440.0).round |
| - | when 43200..86399 then locale.t :about_x_months, count: 1 |
| - | when 86400..525599 then locale.t :x_months, count: (distance_in_minutes.to_f / 43200.0).round |
| - | else |
| - | fyear = from_time.year |
| - | fyear += 1 if from_time.month >= 3 |
| - | tyear = to_time.year |
| - | tyear -= 1 if to_time.month < 3 |
| - | leap_years = (fyear > tyear) ? 0 : (fyear..tyear).count{|x| ::Date.leap?(x)} |
| - | minute_offset_for_leap_year = leap_years * 1440 |
| - | # Discount the leap year days when calculating year distance. |
| - | # e.g. if there are 20 leap year days between 2 dates having the same day |
| - | # and month then the based on 365 days calculation |
| - | # the distance in years will come out to over 80 years when in written |
| - | # english it would read better as about 80 years. |
| - | minutes_with_offset = distance_in_minutes - minute_offset_for_leap_year |
| - | remainder = (minutes_with_offset % 525600) |
| - | distance_in_years = (minutes_with_offset / 525600) |
| - | if remainder < 131400 |
| - | locale.t(:about_x_years, count: distance_in_years) |
| - | elsif remainder < 394200 |
| - | locale.t(:over_x_years, count: distance_in_years) |
| - | else |
| - | locale.t(:almost_x_years, count: distance_in_years + 1) |
| - | end |
| - | end |
| - | end |
| - | end |
| - | |
| - | private |
| - | |
| - | def to_time(input) |
| - | case input |
| - | when Date then input.to_time |
| - | when String then Time.zone.parse(input) |
| - | else |
| - | input |
| - | end |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_filter(Date) |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/filters/html.rb b/lib/locomotive/wagon/liquid/filters/html.rb
+0
-188
| @@ | @@ -1,188 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Filters |
| - | module Html |
| - | |
| - | # Returns a link tag that browsers and news readers can use to auto-detect an RSS or ATOM feed. |
| - | # input: url of the feed |
| - | # example: |
| - | # {{ '/foo/bar' | auto_discovery_link_tag: 'rel:alternate', 'type:application/atom+xml', 'title:A title' }} |
| - | def auto_discovery_link_tag(input, *args) |
| - | options = args_to_options(args) |
| - | |
| - | rel = options[:rel] || 'alternate' |
| - | type = options[:type] || MIME::Types.type_for('rss').first |
| - | title = options[:title] || 'RSS' |
| - | |
| - | %{<link rel="#{rel}" type="#{type}" title="#{title}" href="#{input}" />} |
| - | end |
| - | |
| - | # Write the url of a theme stylesheet |
| - | # input: name of the css file |
| - | def stylesheet_url(input) |
| - | return '' if input.nil? |
| - | |
| - | if input =~ /^https?:/ |
| - | input |
| - | else |
| - | input = "/stylesheets/#{input}" unless input =~ /^\// |
| - | input = "#{input}.css" unless input.ends_with?('.css') |
| - | input |
| - | end |
| - | end |
| - | |
| - | # Write the link to a stylesheet resource |
| - | # input: url of the css file |
| - | def stylesheet_tag(input, media = 'screen') |
| - | return '' if input.nil? |
| - | |
| - | input = stylesheet_url(input) |
| - | |
| - | %{<link href="#{input}" media="#{media}" rel="stylesheet" type="text/css" />} |
| - | end |
| - | |
| - | # Write the url to javascript resource |
| - | # input: name of the javascript file |
| - | def javascript_url(input) |
| - | return '' if input.nil? |
| - | |
| - | input = "/javascripts/#{input}" unless input =~ /^(\/|https?:)/ |
| - | |
| - | input = "#{input}.js" unless input.ends_with?('.js') |
| - | |
| - | input |
| - | end |
| - | |
| - | # Write the link to javascript resource |
| - | # input: url of the javascript file |
| - | def javascript_tag(input) |
| - | return '' if input.nil? |
| - | |
| - | input = javascript_url(input) |
| - | |
| - | %{<script src="#{input}" type="text/javascript"></script>} |
| - | end |
| - | |
| - | # Write an image tag |
| - | # input: url of the image OR asset drop |
| - | def image_tag(input, *args) |
| - | image_options = inline_options(args_to_options(args)) |
| - | |
| - | "<img src=\"#{get_url_from_asset(input)}\" #{image_options}>" |
| - | end |
| - | |
| - | # Write a theme image tag |
| - | # input: name of file including folder |
| - | # example: 'about/myphoto.jpg' | theme_image # <img src="images/about/myphoto.jpg" /> |
| - | def theme_image_tag(input, *args) |
| - | image_options = inline_options(args_to_options(args)) |
| - | "<img src=\"#{theme_image_url(input)}\" #{image_options}/>" |
| - | end |
| - | |
| - | def theme_image_url(input) |
| - | return '' if input.nil? |
| - | |
| - | input = "images/#{input}" unless input.starts_with?('/') |
| - | |
| - | File.join('/', input) |
| - | end |
| - | |
| - | def image_format(input, *args) |
| - | format = args_to_options(args).first |
| - | "#{input}.#{format}" |
| - | end |
| - | |
| - | # Embed a flash movie into a page |
| - | # input: url of the flash movie OR asset drop |
| - | # width: width (in pixel or in %) of the embedded movie |
| - | # height: height (in pixel or in %) of the embedded movie |
| - | def flash_tag(input, *args) |
| - | path = get_url_from_asset(input) |
| - | embed_options = inline_options(args_to_options(args)) |
| - | %{ |
| - | <object #{embed_options}> |
| - | <param name="movie" value="#{path}" /> |
| - | <embed src="#{path}" #{embed_options}/> |
| - | </embed> |
| - | </object> |
| - | }.gsub(/ >/, '>').strip |
| - | end |
| - | |
| - | # Render the navigation for a paginated collection |
| - | def default_pagination(paginate, *args) |
| - | return '' if paginate['parts'].empty? |
| - | |
| - | options = args_to_options(args) |
| - | |
| - | previous_label = options[:previous_label] || I18n.t('pagination.previous') |
| - | next_label = options[:next_label] || I18n.t('pagination.next') |
| - | |
| - | previous_link = (if paginate['previous'].blank? |
| - | "<span class=\"disabled prev_page\">#{previous_label}</span>" |
| - | else |
| - | "<a href=\"#{absolute_url(paginate['previous']['url'])}\" class=\"prev_page\">#{previous_label}</a>" |
| - | end) |
| - | |
| - | links = "" |
| - | paginate['parts'].each do |part| |
| - | links << (if part['is_link'] |
| - | "<a href=\"#{absolute_url(part['url'])}\">#{part['title']}</a>" |
| - | elsif part['hellip_break'] |
| - | "<span class=\"gap\">#{part['title']}</span>" |
| - | else |
| - | "<span class=\"current\">#{part['title']}</span>" |
| - | end) |
| - | end |
| - | |
| - | next_link = (if paginate['next'].blank? |
| - | "<span class=\"disabled next_page\">#{next_label}</span>" |
| - | else |
| - | "<a href=\"#{absolute_url(paginate['next']['url'])}\" class=\"next_page\">#{next_label}</a>" |
| - | end) |
| - | |
| - | %{<div class="pagination #{options[:css]}"> |
| - | #{previous_link} |
| - | #{links} |
| - | #{next_link} |
| - | </div>} |
| - | end |
| - | |
| - | protected |
| - | |
| - | # Convert an array of properties ('key:value') into a hash |
| - | # Ex: ['width:50', 'height:100'] => { :width => '50', :height => '100' } |
| - | def args_to_options(*args) |
| - | options = {} |
| - | args.flatten.each do |a| |
| - | if (a =~ /^(.*):(.*)$/) |
| - | options[$1.to_sym] = $2 |
| - | end |
| - | end |
| - | options |
| - | end |
| - | |
| - | # Write options (Hash) into a string according to the following pattern: |
| - | # <key1>="<value1>", <key2>="<value2", ...etc |
| - | def inline_options(options = {}) |
| - | return '' if options.empty? |
| - | (options.stringify_keys.to_a.collect { |a, b| "#{a}=\"#{b}\"" }).join(' ') << ' ' |
| - | end |
| - | |
| - | # Get the path to be used in html tags such as image_tag, flash_tag, ...etc |
| - | # input: url (String) OR asset drop |
| - | def get_url_from_asset(input) |
| - | input.respond_to?(:url) ? input.url : input |
| - | end |
| - | |
| - | def absolute_url(url) |
| - | url =~ /^\// ? url : "/#{url}" |
| - | end |
| - | end |
| - | |
| - | ::Liquid::Template.register_filter(Html) |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/filters/misc.rb b/lib/locomotive/wagon/liquid/filters/misc.rb
+0
-49
| @@ | @@ -1,49 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Filters |
| - | module Misc |
| - | |
| - | # was called modulo at first |
| - | def str_modulo(word, index, modulo) |
| - | (index.to_i + 1) % modulo == 0 ? word : '' |
| - | end |
| - | |
| - | # Get the nth element of the passed in array |
| - | def index(array, position) |
| - | array.at(position) if array.respond_to?(:at) |
| - | end |
| - | |
| - | def default(input, value) |
| - | input.blank? ? value : input |
| - | end |
| - | |
| - | def random(input) |
| - | rand(input.to_i) |
| - | end |
| - | |
| - | # map/collect on a given property (support to_f, to_i) |
| - | def map(input, property) |
| - | flatten_if_necessary(input).map do |e| |
| - | e = e.call if e.is_a?(Proc) |
| - | |
| - | if property == "to_liquid" |
| - | e |
| - | elsif property == "to_f" |
| - | e.to_f |
| - | elsif property == "to_i" |
| - | e.to_i |
| - | elsif e.respond_to?(:[]) |
| - | e[property] |
| - | end |
| - | end |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_filter(Misc) |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/filters/resize.rb b/lib/locomotive/wagon/liquid/filters/resize.rb
+0
-18
| @@ | @@ -1,18 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Filters |
| - | module Resize |
| - | |
| - | def resize(input, resize_string) |
| - | Locomotive::Wagon::Dragonfly.instance.resize_url(input, resize_string) |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_filter(Resize) |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/filters/text.rb b/lib/locomotive/wagon/liquid/filters/text.rb
+0
-55
| @@ | @@ -1,55 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Filters |
| - | module Text |
| - | |
| - | # right justify and padd a string |
| - | def rjust(input, integer, padstr = '') |
| - | input.to_s.rjust(integer, padstr) |
| - | end |
| - | |
| - | # left justify and padd a string |
| - | def ljust(input, integer, padstr = '') |
| - | input.to_s.ljust(integer, padstr) |
| - | end |
| - | |
| - | def underscore(input) |
| - | input.to_s.gsub(' ', '_').gsub('/', '_').underscore |
| - | end |
| - | |
| - | def dasherize(input) |
| - | input.to_s.gsub(' ', '-').gsub('/', '-').dasherize |
| - | end |
| - | |
| - | # alias newline_to_br |
| - | def multi_line(input) |
| - | input.to_s.gsub("\n", '<br/>') |
| - | end |
| - | |
| - | def concat(input, *args) |
| - | result = input.to_s |
| - | args.flatten.each { |a| result << a.to_s } |
| - | result |
| - | end |
| - | |
| - | def encode(input) |
| - | Rack::Utils.escape(input) |
| - | end |
| - | |
| - | def textile(input) |
| - | ::RedCloth.new(input).to_html |
| - | end |
| - | |
| - | def markdown(input) |
| - | Locomotive::Wagon::Markdown.render(input) |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_filter(Text) |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/filters/translate.rb b/lib/locomotive/wagon/liquid/filters/translate.rb
+0
-28
| @@ | @@ -1,28 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Filters |
| - | module Translate |
| - | |
| - | def translate(key, locale = nil, scope = nil) |
| - | locale ||= I18n.locale.to_s |
| - | if scope.blank? |
| - | translation = @context.registers[:mounting_point].translations[key.to_s] |
| - | |
| - | if translation |
| - | translation.get(locale) || translation.get(Locomotive::Mounter.locale.to_s) |
| - | else |
| - | "[unknown translation key: #{key}]" |
| - | end |
| - | else |
| - | I18n.t(key, scope: scope.split('.'), locale: locale) |
| - | end |
| - | end |
| - | end |
| - | |
| - | ::Liquid::Template.register_filter(Translate) |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/patches.rb b/lib/locomotive/wagon/liquid/patches.rb
+0
-47
| @@ | @@ -1,47 +0,0 @@ |
| - | module Liquid |
| - | |
| - | class Drop |
| - | |
| - | def mounting_point |
| - | @context.registers[:mounting_point] |
| - | end |
| - | |
| - | def site |
| - | @context.registers[:site] |
| - | end |
| - | |
| - | end |
| - | |
| - | class Template |
| - | |
| - | # creates a new <tt>Template</tt> object from liquid source code |
| - | def parse_with_utf8(source, context = {}) |
| - | if RUBY_VERSION =~ /1\.9/ |
| - | source = source.force_encoding('UTF-8') if source.present? |
| - | end |
| - | self.parse_without_utf8(source, context) |
| - | end |
| - | |
| - | alias_method_chain :parse, :utf8 |
| - | |
| - | end |
| - | |
| - | module StandardFilters |
| - | |
| - | private |
| - | |
| - | def to_number(obj) |
| - | case obj |
| - | when Numeric |
| - | obj |
| - | when String |
| - | (obj.strip =~ /^\d+\.\d+$/) ? obj.to_f : obj.to_i |
| - | when DateTime, Date, Time |
| - | obj.to_time.to_i |
| - | else |
| - | 0 |
| - | end |
| - | end |
| - | end |
| - | |
| - | end |
locomotive/wagon/liquid/scopeable.rb b/lib/locomotive/wagon/liquid/scopeable.rb
+0
-151
| @@ | @@ -1,151 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Scopeable |
| - | |
| - | def apply_scope(entries) |
| - | if @context['with_scope'].blank? |
| - | entries |
| - | else |
| - | # extract the conditions |
| - | _conditions = @context['with_scope'].clone.delete_if { |k, _| %w(order_by per_page page).include?(k) } |
| - | |
| - | # build the chains of conditions |
| - | conditions = _conditions.map { |name, value| Condition.new(name, value) } |
| - | |
| - | Locomotive::Wagon::Logger.info "[with_scope] conditions: #{conditions.map(&:to_s).join(', ')}" |
| - | |
| - | # get only the entries matching ALL the conditions |
| - | _entries = entries.find_all do |content| |
| - | accepted = true |
| - | |
| - | conditions.each do |_condition| |
| - | unless _condition.matches?(content) |
| - | accepted = false |
| - | break # no to go further |
| - | end |
| - | end |
| - | |
| - | accepted |
| - | end |
| - | |
| - | self._apply_scope_order(_entries, @context['with_scope']['order_by']) |
| - | end |
| - | end |
| - | |
| - | def _apply_scope_order(entries, order_by) |
| - | return entries if order_by.blank? |
| - | |
| - | name, direction = order_by.split(/[\s\.]/).map(&:to_sym) |
| - | |
| - | Locomotive::Wagon::Logger.info "[with_scope] order_by #{name} #{direction || 'asc'}" |
| - | |
| - | if direction == :asc || direction.nil? |
| - | entries.sort { |a, b| a.send(name) <=> b.send(name) } |
| - | else |
| - | entries.sort { |a, b| b.send(name) <=> a.send(name) } |
| - | end |
| - | end |
| - | |
| - | class Condition |
| - | |
| - | OPERATORS = %w(all gt gte in lt lte ne nin size) |
| - | |
| - | attr_accessor :name, :operator, :right_operand |
| - | |
| - | def initialize(name, value) |
| - | self.name, self.right_operand = name, value |
| - | |
| - | self.name = :_slug if %w(id _id).include?(name.to_s) |
| - | |
| - | self.process_right_operand |
| - | |
| - | # default value |
| - | self.operator = :== |
| - | |
| - | self.decode_operator_based_on_name |
| - | end |
| - | |
| - | def matches?(entry) |
| - | value = self.get_value(entry) |
| - | |
| - | self.decode_operator_based_on_value(value) |
| - | |
| - | case self.operator |
| - | when :== then value == self.right_operand |
| - | when :ne then value != self.right_operand |
| - | when :matches then self.right_operand =~ value |
| - | when :gt then value > self.right_operand |
| - | when :gte then value >= self.right_operand |
| - | when :lt then value < self.right_operand |
| - | when :lte then value <= self.right_operand |
| - | when :size then value.size == self.right_operand |
| - | when :all then [*self.right_operand].contains?(value) |
| - | when :in, :nin |
| - | _matches = if value.is_a?(Array) |
| - | [*value].contains?([*self.right_operand]) |
| - | else |
| - | [*self.right_operand].include?(value) |
| - | end |
| - | self.operator == :in ? _matches : !_matches |
| - | else |
| - | raise UnknownConditionInScope.new("#{self.operator} is unknown or not implemented.") |
| - | end |
| - | end |
| - | |
| - | def to_s |
| - | "#{name} #{operator} #{self.right_operand.to_s}" |
| - | end |
| - | |
| - | protected |
| - | |
| - | def get_value(entry) |
| - | value = entry.send(self.name) |
| - | |
| - | if value.respond_to?(:_slug) |
| - | # belongs_to |
| - | value._slug |
| - | elsif value.respond_to?(:map) |
| - | # many_to_many or tags ? |
| - | value.map { |v| v.respond_to?(:_slug) ? v._slug : v } |
| - | else |
| - | value |
| - | end |
| - | end |
| - | |
| - | def process_right_operand |
| - | if self.right_operand.respond_to?(:_slug) |
| - | # belongs_to |
| - | self.right_operand = self.right_operand._slug |
| - | elsif self.right_operand.respond_to?(:map) && self.right_operand.first.respond_to?(:_slug) |
| - | # many_to_many |
| - | self.right_operand = self.right_operand.map do |entry| |
| - | entry.try(&:_slug) |
| - | end |
| - | end |
| - | end |
| - | |
| - | def decode_operator_based_on_name |
| - | if name =~ /^([a-z0-9_-]+)\.(#{OPERATORS.join('|')})$/ |
| - | self.name = $1.to_sym |
| - | self.operator = $2.to_sym |
| - | end |
| - | |
| - | if self.right_operand.is_a?(Regexp) |
| - | self.operator = :matches |
| - | end |
| - | end |
| - | |
| - | def decode_operator_based_on_value(value) |
| - | case value |
| - | when Array |
| - | self.operator = :in if self.operator == :== |
| - | end |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/consume.rb b/lib/locomotive/wagon/liquid/tags/consume.rb
+0
-100
| @@ | @@ -1,100 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | # Consume web services as easy as pie directly in liquid ! |
| - | # |
| - | # Usage: |
| - | # |
| - | # {% consume blog from 'http://nocoffee.tumblr.com/api/read.json?num=3', username: 'john', password: 'easy', format: 'json', expires_in: 3000 %} |
| - | # {% for post in blog.posts %} |
| - | # {{ post.title }} |
| - | # {% endfor %} |
| - | # {% endconsume %} |
| - | # |
| - | class Consume < ::Liquid::Block |
| - | |
| - | Syntax = /(#{::Liquid::VariableSignature}+)\s*from\s*(#{::Liquid::QuotedString}|#{::Liquid::VariableSignature}+)(.*)?/ |
| - | |
| - | def initialize(tag_name, markup, tokens, options) |
| - | if markup =~ Syntax |
| - | @target = $1 |
| - | |
| - | self.prepare_url($2) |
| - | self.prepare_api_arguments($3) |
| - | else |
| - | raise ::Liquid::SyntaxError.new(options[:locale].t("errors.syntax.consume"), options[:line]) |
| - | end |
| - | |
| - | @local_cache_key = self.hash |
| - | |
| - | super |
| - | end |
| - | |
| - | def render(context) |
| - | self.set_api_options(context) |
| - | |
| - | if instance_variable_defined? :@variable_name |
| - | @url = context[@variable_name] |
| - | end |
| - | render_all_without_cache(context) |
| - | end |
| - | |
| - | protected |
| - | |
| - | def prepare_url(token) |
| - | if token.match(::Liquid::QuotedString) |
| - | @url = token.gsub(/['"]/, '') |
| - | elsif token.match(::Liquid::VariableSignature) |
| - | @variable_name = token |
| - | else |
| - | raise ::Liquid::SyntaxError.new("Syntax Error in 'consume' - Valid syntax: consume <var> from \"<url>\" [username: value, password: value]") |
| - | end |
| - | end |
| - | |
| - | def prepare_api_arguments(string) |
| - | string = string.gsub(/^(\s*,)/, '').strip |
| - | @api_arguments = Solid::Arguments.parse(string) |
| - | end |
| - | |
| - | def set_api_options(context) |
| - | @api_options = @api_arguments.interpolate(context).first || {} |
| - | @expires_in = @api_options.delete(:expires_in) || 0 |
| - | end |
| - | |
| - | def cached_response |
| - | @@local_cache ||= {} |
| - | @@local_cache[@local_cache_key] |
| - | end |
| - | |
| - | def cached_response=(response) |
| - | @@local_cache ||= {} |
| - | @@local_cache[@local_cache_key] = response |
| - | end |
| - | |
| - | def render_all_without_cache(context) |
| - | context.stack do |
| - | begin |
| - | context.scopes.last[@target.to_s] = Locomotive::Wagon::Httparty::Webservice.consume(@url, @api_options) |
| - | self.cached_response = context.scopes.last[@target.to_s] |
| - | rescue Timeout::Error |
| - | context.scopes.last[@target.to_s] = self.cached_response |
| - | rescue ::Liquid::Error => e |
| - | raise e |
| - | rescue => e |
| - | liquid_e = ::Liquid::Error.new(e.message, line) |
| - | liquid_e.set_backtrace(e.backtrace) |
| - | raise liquid_e |
| - | end |
| - | |
| - | render_all(@nodelist, context) |
| - | end |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('consume', Consume) |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/csrf.rb b/lib/locomotive/wagon/liquid/tags/csrf.rb
+0
-34
| @@ | @@ -1,34 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | module Csrf |
| - | |
| - | class Param < ::Liquid::Tag |
| - | |
| - | def render(context) |
| - | %{<input type="hidden" name="authenticity_token" value="helloworld" />} |
| - | end |
| - | |
| - | end |
| - | |
| - | class Meta < ::Liquid::Tag |
| - | |
| - | def render(context) |
| - | %{ |
| - | <meta name="csrf-param" content="authenticity_token" /> |
| - | <meta name="csrf-token" content="helloworld" /> |
| - | } |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('csrf_param', Csrf::Param) |
| - | ::Liquid::Template.register_tag('csrf_meta', Csrf::Meta) |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/editable.rb b/lib/locomotive/wagon/liquid/tags/editable.rb
+0
-6
| @@ | @@ -1,6 +0,0 @@ |
| - | require 'locomotive/wagon/liquid/tags/editable/base' |
| - | require 'locomotive/wagon/liquid/tags/editable/text' |
| - | require 'locomotive/wagon/liquid/tags/editable/short_text' |
| - | require 'locomotive/wagon/liquid/tags/editable/long_text' |
| - | require 'locomotive/wagon/liquid/tags/editable/file' |
| - | require 'locomotive/wagon/liquid/tags/editable/control' |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/editable/base.rb b/lib/locomotive/wagon/liquid/tags/editable/base.rb
+0
-50
| @@ | @@ -1,50 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | module Editable |
| - | class Base < ::Liquid::Block |
| - | |
| - | Syntax = /(#{::Liquid::QuotedFragment})(\s*,\s*#{::Liquid::Expression}+)?/ |
| - | |
| - | def initialize(tag_name, markup, tokens, options) |
| - | if markup =~ Syntax |
| - | @slug = $1.gsub(/[\"\']/, '') |
| - | @_options = {} |
| - | markup.scan(::Liquid::TagAttributes) { |key, value| @_options[key.to_sym] = value.gsub(/^'/, '').gsub(/'$/, '') } |
| - | else |
| - | raise ::Liquid::SyntaxError.new(options[:locale].t("errors.syntax.#{tag_name}"), options[:line]) |
| - | end |
| - | |
| - | super |
| - | end |
| - | |
| - | def render(context) |
| - | current_page = context.registers[:page] |
| - | |
| - | element = current_page.find_editable_element(self.current_block_name(context), @slug) |
| - | |
| - | if element.present? |
| - | render_element(context, element) |
| - | else |
| - | super |
| - | end |
| - | end |
| - | |
| - | protected |
| - | |
| - | def render_element(context, element) |
| - | element.content |
| - | end |
| - | |
| - | def current_block_name(context) |
| - | context['block'].try(:name) |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/editable/control.rb b/lib/locomotive/wagon/liquid/tags/editable/control.rb
+0
-19
| @@ | @@ -1,19 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | module Editable |
| - | class Control < Base |
| - | |
| - | def render(context) |
| - | super |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('editable_control', Control) |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/editable/file.rb b/lib/locomotive/wagon/liquid/tags/editable/file.rb
+0
-15
| @@ | @@ -1,15 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | module Editable |
| - | class File < Base |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('editable_file', File) |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/editable/long_text.rb b/lib/locomotive/wagon/liquid/tags/editable/long_text.rb
+0
-15
| @@ | @@ -1,15 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | module Editable |
| - | class LongText < ShortText |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('editable_long_text', LongText) |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/editable/short_text.rb b/lib/locomotive/wagon/liquid/tags/editable/short_text.rb
+0
-20
| @@ | @@ -1,20 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | module Editable |
| - | class ShortText < Base |
| - | |
| - | def render(context) |
| - | Locomotive::Wagon::Logger.warn " [#{self.current_block_name(context)}/#{@slug}] The editable_{short|long}_text tags are deprecated. Use editable_text instead.".colorize(:orange) |
| - | super(context) |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('editable_short_text', ShortText) |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/editable/text.rb b/lib/locomotive/wagon/liquid/tags/editable/text.rb
+0
-15
| @@ | @@ -1,15 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | module Editable |
| - | class Text < Base |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('editable_text', Text) |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/extends.rb b/lib/locomotive/wagon/liquid/tags/extends.rb
+0
-25
| @@ | @@ -1,25 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | class Extends < ::Liquid::Extends |
| - | |
| - | def parse_parent_template |
| - | mounting_point = @options[:mounting_point] |
| - | |
| - | page = if @template_name == 'parent' |
| - | @options[:page].parent |
| - | else |
| - | mounting_point.pages[@template_name] |
| - | end |
| - | |
| - | ::Liquid::Template.parse(page.source, { mounting_point: mounting_point, page: page }) |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('extends', Extends) |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/fetch_page.rb b/lib/locomotive/wagon/liquid/tags/fetch_page.rb
+0
-41
| @@ | @@ -1,41 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | |
| - | # Fetch a page from its handle and assign it to a liquid variable. |
| - | # |
| - | # Usage: |
| - | # |
| - | # {% fetch_page 'about_us' as a_page %} |
| - | # <p>{{ a_page.title }}</p> |
| - | # |
| - | class FetchPage < ::Liquid::Tag |
| - | |
| - | Syntax = /(#{::Liquid::VariableSignature}+)\s+as\s+(#{::Liquid::VariableSignature}+)/ |
| - | |
| - | def initialize(tag_name, markup, tokens, context) |
| - | if markup =~ Syntax |
| - | @handle = $1 |
| - | @var = $2 |
| - | else |
| - | raise SyntaxError.new("Syntax Error in 'fetch_page' - Valid syntax: fetch_page page_handle as variable") |
| - | end |
| - | |
| - | super |
| - | end |
| - | |
| - | def render(context) |
| - | mounting_point = context.registers[:mounting_point] |
| - | context.scopes.last[@var] = mounting_point.pages.values.find { |_page| _page.handle == @handle } |
| - | '' |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('fetch_page', FetchPage) |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/google_analytics.rb b/lib/locomotive/wagon/liquid/tags/google_analytics.rb
+0
-28
| @@ | @@ -1,28 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | class GoogleAnalytics < ::Liquid::Tag |
| - | |
| - | Syntax = /(#{::Liquid::Expression}+)?/ |
| - | |
| - | def initialize(tag_name, markup, tokens, options) |
| - | if markup =~ Syntax |
| - | @account_id = $1.gsub('\'', '') |
| - | else |
| - | raise ::Liquid::SyntaxError.new(options[:locale].t("errors.syntax.google_analytics"), options[:line]) |
| - | end |
| - | |
| - | super |
| - | end |
| - | |
| - | def render(context) |
| - | "<!-- google analytics for #{@account_id} -->" |
| - | end |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('google_analytics', GoogleAnalytics) |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/hybrid.rb b/lib/locomotive/wagon/liquid/tags/hybrid.rb
+0
-27
| @@ | @@ -1,27 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | class Hybrid < ::Liquid::Block |
| - | def parse(tokens) |
| - | nesting = 0 |
| - | tokens.each do |token| |
| - | next unless token =~ IsTag |
| - | if token =~ FullToken |
| - | if nesting == 0 && $1 == block_delimiter |
| - | @render_as_block = true |
| - | super |
| - | return |
| - | elsif $1 == block_name |
| - | nesting += 1 |
| - | elsif $1 == block_delimiter |
| - | nesting -= 1 |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/inline_editor.rb b/lib/locomotive/wagon/liquid/tags/inline_editor.rb
+0
-16
| @@ | @@ -1,16 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | class InlineEditor < ::Liquid::Tag |
| - | |
| - | def render(context) |
| - | '' |
| - | end |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('inline_editor', InlineEditor) |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/link_to.rb b/lib/locomotive/wagon/liquid/tags/link_to.rb
+0
-56
| @@ | @@ -1,56 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | class LinkTo < Hybrid |
| - | |
| - | Syntax = /(#{::Liquid::Expression}+)(#{::Liquid::TagAttributes}?)/ |
| - | |
| - | include PathHelper |
| - | |
| - | def initialize(tag_name, markup, tokens, options) |
| - | if markup =~ Syntax |
| - | @handle = $1 |
| - | @_options = {} |
| - | markup.scan(::Liquid::TagAttributes) do |key, value| |
| - | @_options[key] = value |
| - | end |
| - | else |
| - | raise ::Liquid::SyntaxError.new(options[:locale].t("errors.syntax.link_to"), options[:line]) |
| - | end |
| - | |
| - | super |
| - | end |
| - | |
| - | def render(context) |
| - | render_path(context) do |page, path| |
| - | label = label_from_page(page) |
| - | |
| - | if @render_as_block |
| - | context.scopes.last['target'] = page |
| - | label = super.html_safe |
| - | end |
| - | |
| - | %{<a href="#{path}">#{label}</a>} |
| - | end |
| - | end |
| - | |
| - | protected |
| - | |
| - | def label_from_page(page) |
| - | ::Locomotive::Mounter.with_locale(@_options['locale']) do |
| - | if page.templatized? |
| - | page.content_entry._label |
| - | else |
| - | page.title |
| - | end |
| - | end |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('link_to', LinkTo) |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/locale_switcher.rb b/lib/locomotive/wagon/liquid/tags/locale_switcher.rb
+0
-106
| @@ | @@ -1,106 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | # Display the links to change the locale of the current page |
| - | # |
| - | # Usage: |
| - | # |
| - | # {% locale_switcher %} => <div id="locale-switcher"><a href="/features" class="current en">Features</a><a href="/fr/fonctionnalites" class="fr">Fonctionnalités</a></div> |
| - | # |
| - | # {% locale_switcher label: locale, sep: ' - ' } |
| - | # |
| - | # options: |
| - | # - label: iso (de, fr, en, ...etc), locale (Deutsch, Français, English, ...etc), title (page title) |
| - | # - sep: piece of html code separating 2 locales |
| - | # |
| - | # notes: |
| - | # - "iso" is the default choice for label |
| - | # - " | " is the default separating code |
| - | # |
| - | class LocaleSwitcher < ::Liquid::Tag |
| - | |
| - | Syntax = /(#{::Liquid::Expression}+)?/ |
| - | |
| - | def initialize(tag_name, markup, tokens, options) |
| - | @_options = { label: 'iso', sep: ' | ' } |
| - | |
| - | if markup =~ Syntax |
| - | markup.scan(::Liquid::TagAttributes) { |key, value| @_options[key.to_sym] = value.gsub(/"|'/, '') } |
| - | |
| - | @_options[:exclude] = Regexp.new(@_options[:exclude]) if @_options[:exclude] |
| - | else |
| - | raise ::Liquid::SyntaxError.new(options[:locale].t("errors.syntax.locale_switcher"), options[:line]) |
| - | end |
| - | |
| - | super |
| - | end |
| - | |
| - | def render(context) |
| - | @site, @page = context.registers[:site], context.registers[:page] |
| - | @default_locale = context.registers[:mounting_point].default_locale |
| - | |
| - | output = %(<div id="locale-switcher">) |
| - | |
| - | output += @site.locales.collect do |locale| |
| - | Locomotive::Mounter.with_locale(locale) do |
| - | fullpath = localized_fullpath(locale) |
| - | |
| - | if @page.templatized? |
| - | permalink = context['entry']._permalink |
| - | |
| - | if permalink |
| - | fullpath.gsub!('*', permalink) |
| - | else |
| - | fullpath = '404' |
| - | end |
| - | end |
| - | |
| - | css = link_class(locale, context['locale']) |
| - | |
| - | %(<a href="/#{fullpath}" class="#{css}">#{link_label(locale)}</a>) |
| - | end |
| - | end.join(@_options[:sep]) |
| - | |
| - | output += %(</div>) |
| - | end |
| - | |
| - | private |
| - | |
| - | def link_class(locale, current_locale) |
| - | css = [locale] |
| - | css << 'current' if locale.to_s == current_locale.to_s |
| - | css.join(' ') |
| - | end |
| - | |
| - | def link_label(locale) |
| - | case @_options[:label] |
| - | when 'iso' then locale |
| - | when 'locale' then I18n.t("locomotive.locales.#{locale}") |
| - | when 'title' then @page.title # FIXME: this returns nil if the page has not been translated in the locale |
| - | else |
| - | locale |
| - | end |
| - | end |
| - | |
| - | def localized_fullpath(locale) |
| - | return nil if @page.fullpath_translations.blank? |
| - | |
| - | fullpath = @page.safe_fullpath || @page.fullpath_or_default |
| - | |
| - | if locale.to_s == @default_locale.to_s # no need to specify the locale |
| - | @page.index? ? '' : fullpath |
| - | elsif @page.index? # avoid /en/index or /fr/index, prefer /en or /fr instead |
| - | locale |
| - | else |
| - | File.join(locale, fullpath) |
| - | end |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('locale_switcher', LocaleSwitcher) |
| - | end |
| - | end |
| - | end |
| - | end |
locomotive/wagon/liquid/tags/model_form.rb b/lib/locomotive/wagon/liquid/tags/model_form.rb
+0
-67
| @@ | @@ -1,67 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | |
| - | # Display the form html tag with the appropriate hidden fields in order to create |
| - | # a content entry from a public site. |
| - | # It handles callbacks, csrf and target url out of the box. |
| - | # |
| - | # Usage: |
| - | # |
| - | # {% model_form 'newsletter_addresses' %} |
| - | # <input type='text' name='content[email]' /> |
| - | # <input type='submit' value='Add' /> |
| - | # {% endform_form %} |
| - | # |
| - | # {% model_form 'newsletter_addresses', class: 'a-css-class', success: 'http://www.google.fr', error: '/error' %}...{% endform_form %} |
| - | # |
| - | class ModelForm < Solid::Block |
| - | |
| - | tag_name :model_form |
| - | |
| - | def display(*options, &block) |
| - | name = options.shift |
| - | options = options.shift || {} |
| - | |
| - | form_attributes = { method: 'POST', enctype: 'multipart/form-data' }.merge(options.slice(:id, :class)) |
| - | |
| - | html_content_tag :form, |
| - | content_type_html(name) + callbacks_html(options) + yield, |
| - | form_attributes |
| - | end |
| - | |
| - | def content_type_html(name) |
| - | html_tag :input, type: 'hidden', name: 'content_type_slug', value: name |
| - | end |
| - | |
| - | def callbacks_html(options) |
| - | options.slice(:success, :error).map do |(name, value)| |
| - | html_tag :input, type: 'hidden', name: "#{name}_callback", value: value |
| - | end.join('') |
| - | end |
| - | |
| - | private |
| - | |
| - | def html_content_tag(name, content, options = {}) |
| - | "<#{name} #{inline_options(options)}>#{content}</#{name}>" |
| - | end |
| - | |
| - | def html_tag(name, options = {}) |
| - | "<#{name} #{inline_options(options)} />" |
| - | end |
| - | |
| - | # Write options (Hash) into a string according to the following pattern: |
| - | # <key1>="<value1>", <key2>="<value2", ...etc |
| - | def inline_options(options = {}) |
| - | return '' if options.empty? |
| - | (options.stringify_keys.to_a.collect { |a, b| "#{a}=\"#{b}\"" }).join(' ') |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/nav.rb b/lib/locomotive/wagon/liquid/tags/nav.rb
+0
-287
| @@ | @@ -1,287 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | |
| - | # Display the children pages of the site, current page or the parent page. If not precised, nav is applied on the current page. |
| - | # The html output is based on the ul/li tags. |
| - | # |
| - | # Usage: |
| - | # |
| - | # {% nav site %} => <ul class="nav"><li class="on"><a href="/features">Features</a></li></ul> |
| - | # |
| - | # {% nav site, no_wrapper: true, exclude: 'contact|about', id: 'main-nav', class: 'nav', active_class: 'on' } |
| - | # |
| - | class Nav < ::Liquid::Tag |
| - | |
| - | Syntax = /(#{::Liquid::Expression}+)?/ |
| - | |
| - | attr_accessor :current_page, :mounting_point |
| - | |
| - | def initialize(tag_name, markup, tokens, options) |
| - | if markup =~ Syntax |
| - | @source = ($1 || 'page').gsub(/"|'/, '') |
| - | |
| - | self.set_options(markup, options) |
| - | else |
| - | raise ::Liquid::SyntaxError.new(options[:locale].t("errors.syntax.nav"), options[:line]) |
| - | end |
| - | |
| - | super |
| - | end |
| - | |
| - | def render(context) |
| - | self.set_accessors_from_context(context) |
| - | |
| - | entries = self.fetch_entries |
| - | output = self.build_entries_output(entries) |
| - | |
| - | if self.no_wrapper? |
| - | output |
| - | else |
| - | self.render_tag(:nav, id: @_options[:id], css: @_options[:class]) do |
| - | self.render_tag(:ul) { output } |
| - | end |
| - | end |
| - | end |
| - | |
| - | protected |
| - | |
| - | # Build recursively the links of all the pages. |
| - | # |
| - | # @param [ Array ] entries List of pages |
| - | # |
| - | # @return [ String ] The final HTML output |
| - | # |
| - | def build_entries_output(entries, depth = 1) |
| - | output = [] |
| - | |
| - | entries.each_with_index do |page, index| |
| - | css = [] |
| - | css << 'first' if index == 0 |
| - | css << 'last' if index == entries.size - 1 |
| - | |
| - | output << self.render_entry_link(page, css.join(' '), depth) |
| - | end |
| - | |
| - | output.join("\n") |
| - | end |
| - | |
| - | # Get all the children of a source: site (index page), parent or page. |
| - | # |
| - | # @return [ Array ] List of pages |
| - | # |
| - | def fetch_entries |
| - | children = (case @source |
| - | when 'site' then self.mounting_point.pages['index'] |
| - | when 'parent' then self.current_page.parent || self.current_page |
| - | when 'page' then self.current_page |
| - | else |
| - | self.mounting_point.pages[@source] |
| - | end).children.try(:clone) || [] |
| - | |
| - | children.delete_if { |p| !include_page?(p) } |
| - | end |
| - | |
| - | # Determine whether or not a page should be a part of the menu. |
| - | # |
| - | # @param [ Object ] page The page |
| - | # |
| - | # @return [ Boolean ] True if the page can be included or not |
| - | # |
| - | def include_page?(page) |
| - | if !page.listed? || page.templatized? || !page.published? |
| - | false |
| - | elsif @_options[:exclude] |
| - | (page.fullpath =~ @_options[:exclude]).nil? |
| - | else |
| - | true |
| - | end |
| - | end |
| - | |
| - | # Determine wether or not a page is currently the displayed one. |
| - | # |
| - | # @param [ Object ] page The page |
| - | # |
| - | # @return [ Boolean ] |
| - | # |
| - | def page_selected?(page) |
| - | self.current_page.fullpath =~ /^#{page.fullpath}(\/.*)?$/ |
| - | end |
| - | |
| - | # Determine if the children of a page have to be rendered or not. |
| - | # It depends on the depth passed in the option. |
| - | # |
| - | # @param [ Object ] page The page |
| - | # @param [ Integer ] depth The current depth |
| - | # |
| - | # @return [ Boolean ] True if the children have to be rendered. |
| - | # |
| - | def render_children_for_page?(page, depth) |
| - | depth.succ <= @_options[:depth].to_i && |
| - | (page.children || []).select { |child| self.include_page?(child) }.any? |
| - | end |
| - | |
| - | # Return the label of an entry. It may use or not the template |
| - | # given by the snippet option. |
| - | # |
| - | # @param [ Object ] page The page |
| - | # |
| - | # @return [ String ] The label in HTML |
| - | # |
| - | def entry_label(page) |
| - | icon = @_options[:icon] ? '<span></span>' : '' |
| - | title = @_options[:liquid_render] ? @_options[:liquid_render].render('page' => page) : page.title |
| - | |
| - | if icon.blank? |
| - | title |
| - | elsif @_options[:icon] == 'after' |
| - | "#{title} #{icon}" |
| - | else |
| - | "#{icon} #{title}" |
| - | end |
| - | end |
| - | |
| - | # Return the localized url of an entry (page). |
| - | # |
| - | # @param [ Object ] page The page |
| - | # |
| - | # @return [ String ] The localized url |
| - | # |
| - | def entry_url(page) |
| - | if ::I18n.locale.to_s == self.mounting_point.default_locale.to_s |
| - | "/#{page.fullpath}" |
| - | else |
| - | "/#{::I18n.locale}/#{page.fullpath}" |
| - | end |
| - | end |
| - | |
| - | # Return the css of an entry (page). |
| - | # |
| - | # @param [ Object ] page The page |
| - | # @param [ String ] css The extra css |
| - | # |
| - | # @return [ String ] The css |
| - | # |
| - | def entry_css(page, css = '') |
| - | _css = 'link' |
| - | _css += " #{page} #{@_options[:active_class]}" if self.page_selected?(page) |
| - | |
| - | (_css + " #{css}").strip |
| - | end |
| - | |
| - | # Return the HTML output of a page and its children if requested. |
| - | # |
| - | # @param [ Object ] page The page |
| - | # @param [ String ] css The current css to apply to the entry |
| - | # @param [ Integer] depth Used to know if the children has to be added or not. |
| - | # |
| - | # @return [ String ] The HTML output |
| - | # |
| - | def render_entry_link(page, css, depth) |
| - | url = self.entry_url(page) |
| - | label = self.entry_label(page) |
| - | css = self.entry_css(page, css) |
| - | options = '' |
| - | |
| - | if self.render_children_for_page?(page, depth) && self.bootstrap? |
| - | url = '#' |
| - | label += %{ <b class="caret"></b>} |
| - | css += ' dropdown' |
| - | options = %{ class="dropdown-toggle" data-toggle="dropdown"} |
| - | end |
| - | |
| - | self.render_tag(:li, id: "#{page.slug.to_s.dasherize}-link", css: css) do |
| - | children_output = depth.succ <= @_options[:depth].to_i ? self.render_entry_children(page, depth.succ) : '' |
| - | %{<a href="#{url}"#{options}>#{label}</a>} + children_output |
| - | end |
| - | end |
| - | |
| - | # Recursively create a nested unordered list for the depth specified. |
| - | # |
| - | # @param [ Array ] entries The children of the page |
| - | # @param [ Integer ] depth The current depth |
| - | # |
| - | # @return [ String ] The HTML code |
| - | # |
| - | def render_entry_children(page, depth) |
| - | entries = (page.children || []).select { |child| self.include_page?(child) } |
| - | css = self.bootstrap? ? 'dropdown-menu' : '' |
| - | |
| - | unless entries.empty? |
| - | self.render_tag(:ul, id: "#{@_options[:id]}-#{page.slug.to_s.dasherize}", css: css) do |
| - | self.build_entries_output(entries, depth) |
| - | end |
| - | else |
| - | '' |
| - | end |
| - | end |
| - | |
| - | # Set the value (default or assigned by the tag) of the options. |
| - | # |
| - | def set_options(markup, options) |
| - | @_options = { id: 'nav', class: '', active_class: 'on', bootstrap: false, no_wrapper: false } |
| - | |
| - | markup.scan(::Liquid::TagAttributes) { |key, value| @_options[key.to_sym] = value.gsub(/"|'/, '') } |
| - | |
| - | @_options[:exclude] = Regexp.new(@_options[:exclude]) if @_options[:exclude] |
| - | |
| - | if @_options[:snippet] |
| - | if template = self.parse_snippet_template(options, @_options[:snippet]) |
| - | @_options[:liquid_render] = template |
| - | end |
| - | end |
| - | end |
| - | |
| - | # Avoid to call context.registers to get the current page |
| - | # and the mounting point. |
| - | # |
| - | def set_accessors_from_context(context) |
| - | self.current_page = context.registers[:page] |
| - | self.mounting_point = context.registers[:mounting_point] |
| - | end |
| - | |
| - | # Parse the template of the snippet give in option of the tag. |
| - | # If the template_name contains a liquid tag or drop, it will |
| - | # be used an inline template. |
| - | # |
| - | def parse_snippet_template(context, template_name) |
| - | source = if template_name.include?('{') |
| - | template_name |
| - | else |
| - | context[:mounting_point].snippets[template_name].try(:source) |
| - | end |
| - | |
| - | source ? ::Liquid::Template.parse(source) : nil |
| - | end |
| - | |
| - | # Render any kind HTML tags. The content of the tag comes from |
| - | # the block. |
| - | # |
| - | # @param [ String ] tag_name Name of the HTML tag (li, ul, div, ...etc). |
| - | # @param [ String ] html_options Id, class, ..etc |
| - | # |
| - | # @return [ String ] The HTML |
| - | # |
| - | def render_tag(tag_name, html_options = {}, &block) |
| - | options = [''] |
| - | options << %{id="#{html_options[:id]}"} if html_options[:id].present? |
| - | options << %{class="#{html_options[:css]}"} if html_options[:css].present? |
| - | |
| - | %{<#{tag_name}#{options.join(' ')}>#{yield}</#{tag_name}>} |
| - | end |
| - | |
| - | def bootstrap? |
| - | @_options[:bootstrap].to_bool |
| - | end |
| - | |
| - | def no_wrapper? |
| - | @_options[:no_wrapper].to_bool |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('nav', Nav) |
| - | end |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/paginate.rb b/lib/locomotive/wagon/liquid/tags/paginate.rb
+0
-105
| @@ | @@ -1,105 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | |
| - | # Paginate a collection |
| - | # |
| - | # Usage: |
| - | # |
| - | # {% paginate contents.projects by 5 %} |
| - | # {% for project in paginate.collection %} |
| - | # {{ project.name }} |
| - | # {% endfor %} |
| - | # {% endpaginate %} |
| - | # |
| - | |
| - | class Paginate < ::Liquid::Block |
| - | |
| - | Syntax = /(#{::Liquid::Expression}+)\s+by\s+([0-9]+)/ |
| - | |
| - | def initialize(tag_name, markup, tokens, options) |
| - | if markup =~ Syntax |
| - | @collection_name = $1 |
| - | @per_page = $2.to_i |
| - | else |
| - | raise ::Liquid::SyntaxError.new(options[:locale].t("errors.syntax.paginate"), options[:line]) |
| - | end |
| - | |
| - | super |
| - | end |
| - | |
| - | def render(context) |
| - | context.stack do |
| - | collection = context[@collection_name] |
| - | |
| - | raise ::Liquid::ArgumentError.new("Cannot paginate array '#{@collection_name}'. Not found.") if collection.nil? |
| - | |
| - | pagination = collection.send(:paginate, { |
| - | :page => context['current_page'], |
| - | :per_page => @per_page }).stringify_keys! |
| - | |
| - | page_count, current_page = pagination['total_pages'], pagination['current_page'] |
| - | |
| - | path = sanitize_path(context['fullpath']) |
| - | |
| - | pagination['previous'] = link(I18n.t('pagination.previous'), current_page - 1, path) if pagination['previous_page'] |
| - | pagination['next'] = link(I18n.t('pagination.next'), current_page + 1, path) if pagination['next_page'] |
| - | pagination['parts'] = [] |
| - | |
| - | hellip_break = false |
| - | |
| - | if page_count > 1 |
| - | 1.upto(page_count) do |page| |
| - | if current_page == page |
| - | pagination['parts'] << no_link(page) |
| - | elsif page == 1 |
| - | pagination['parts'] << link(page, page, path) |
| - | elsif page == page_count - 1 |
| - | pagination['parts'] << link(page, page, path) |
| - | elsif page <= current_page - window_size or page >= current_page + window_size |
| - | next if hellip_break |
| - | pagination['parts'] << no_link('…') |
| - | hellip_break = true |
| - | next |
| - | else |
| - | pagination['parts'] << link(page, page, path) |
| - | end |
| - | |
| - | hellip_break = false |
| - | end |
| - | end |
| - | |
| - | context['paginate'] = pagination |
| - | |
| - | render_all(@nodelist, context) |
| - | end |
| - | end |
| - | |
| - | private |
| - | |
| - | def sanitize_path(path) |
| - | _path = path.gsub(/page=[0-9]+&?/, '').gsub(/_pjax=true&?/, '') |
| - | _path = _path.slice(0..-2) if _path.last == '?' || _path.last == '&' |
| - | _path |
| - | end |
| - | |
| - | def window_size |
| - | 3 |
| - | end |
| - | |
| - | def no_link(title) |
| - | { 'title' => title, 'is_link' => false, 'hellip_break' => title == '…' } |
| - | end |
| - | |
| - | def link(title, page, path) |
| - | _path = %(#{path}#{path.include?('?') ? '&' : '?'}page=#{page}) |
| - | { 'title' => title, 'url' => _path, 'is_link' => true } |
| - | end |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('paginate', Paginate) |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/path_helper.rb b/lib/locomotive/wagon/liquid/tags/path_helper.rb
+0
-97
| @@ | @@ -1,97 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | |
| - | module PathHelper |
| - | |
| - | def render_path(context, &block) |
| - | site = context.registers[:site] |
| - | |
| - | if page = self.retrieve_page_from_handle(context) |
| - | path = self.public_page_fullpath(context, page) |
| - | |
| - | if block_given? |
| - | block.call page, path |
| - | else |
| - | path |
| - | end |
| - | else |
| - | raise Liquid::PageNotTranslated.new(%{[link_to] Unable to find a page for the #{@handle}. Wrong handle or missing template for your content.}) |
| - | end |
| - | end |
| - | |
| - | protected |
| - | |
| - | def retrieve_page_from_handle(context) |
| - | mounting_point = context.registers[:mounting_point] |
| - | |
| - | context.scopes.reverse_each do |scope| |
| - | handle = scope[@handle] || @handle |
| - | |
| - | page = case handle |
| - | when Locomotive::Mounter::Models::Page then handle |
| - | when Liquid::Drops::Page then handle.instance_variable_get(:@_source) |
| - | when String then fetch_page(mounting_point, handle) |
| - | when Liquid::Drops::ContentEntry then fetch_page(mounting_point, handle.instance_variable_get(:@_source), true) |
| - | when Locomotive::Mounter::Models::ContentEntry then fetch_page(mounting_point, handle, true) |
| - | else |
| - | nil |
| - | end |
| - | |
| - | return page unless page.nil? |
| - | end |
| - | |
| - | nil |
| - | end |
| - | |
| - | def fetch_page(mounting_point, handle, templatized = false) |
| - | ::Locomotive::Mounter.with_locale(@_options['locale']) do |
| - | if templatized |
| - | page = mounting_point.pages.values.find do |_page| |
| - | _page.templatized? && |
| - | _page.content_type.slug == handle.content_type.slug && |
| - | (@_options['with'].nil? || _page.handle == @_options['with']) |
| - | end |
| - | |
| - | page.content_entry = handle if page |
| - | |
| - | page |
| - | else |
| - | mounting_point.pages.values.find { |_page| _page.handle == handle } |
| - | end |
| - | end |
| - | end |
| - | |
| - | def public_page_fullpath(context, page) |
| - | mounting_point = context.registers[:mounting_point] |
| - | locale = @_options['locale'] || ::I18n.locale |
| - | |
| - | if !page.translated_in?(locale) |
| - | title = page.title_translations.values.compact.first |
| - | raise Liquid::PageNotTranslated.new(%{the "#{title}" page is not translated in #{locale.upcase}}) |
| - | end |
| - | |
| - | fullpath = ::Locomotive::Mounter.with_locale(locale) do |
| - | page.fullpath.clone |
| - | end |
| - | |
| - | fullpath = "#{locale}/#{fullpath}" if locale.to_s != mounting_point.default_locale.to_s |
| - | |
| - | if page.templatized? |
| - | if page.content_entry._slug.nil? |
| - | title = %{#{page.content_entry.content_type.name.singularize} "#{page.content_entry.send(page.content_entry.content_type.label_field_name)}"} |
| - | raise Liquid::ContentEntryNotTranslated.new(%{the #{title} slug is not translated in #{locale.upcase}}) |
| - | end |
| - | fullpath.gsub!(/(content[_-]type[_-]template|template)/, page.content_entry._slug) |
| - | end |
| - | |
| - | File.join('/', fullpath) |
| - | end |
| - | |
| - | end |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
locomotive/wagon/liquid/tags/path_to.rb b/lib/locomotive/wagon/liquid/tags/path_to.rb
+0
-36
| @@ | @@ -1,36 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | |
| - | class PathTo < ::Liquid::Tag |
| - | |
| - | include PathHelper |
| - | |
| - | Syntax = /(#{::Liquid::Expression}+)(#{::Liquid::TagAttributes}?)/ |
| - | |
| - | def initialize(tag_name, markup, tokens, context) |
| - | if markup =~ Syntax |
| - | @handle = $1 |
| - | @_options = {} |
| - | markup.scan(::Liquid::TagAttributes) do |key, value| |
| - | @_options[key] = value |
| - | end |
| - | else |
| - | raise SyntaxError.new("Syntax Error in 'path_to' - Valid syntax: path_to <page|page_handle|content_entry>(, locale: [fr|de|...], with: <page_handle>") |
| - | end |
| - | |
| - | super |
| - | end |
| - | |
| - | def render(context) |
| - | render_path(context) |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('path_to', PathTo) |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/seo.rb b/lib/locomotive/wagon/liquid/tags/seo.rb
+0
-74
| @@ | @@ -1,74 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | module SEO |
| - | |
| - | class Base < ::Liquid::Tag |
| - | |
| - | def render(context) |
| - | %{ |
| - | #{self.render_title(context)} |
| - | #{self.render_metadata(context)} |
| - | } |
| - | end |
| - | |
| - | protected |
| - | |
| - | def render_title(context) |
| - | title = self.value_for(:seo_title, context) |
| - | title = context.registers[:site].name if title.blank? |
| - | |
| - | %{ |
| - | <title>#{title}</title> |
| - | } |
| - | end |
| - | |
| - | def render_metadata(context) |
| - | %{ |
| - | <meta name="description" content="#{self.value_for(:meta_description, context)}" /> |
| - | <meta name="keywords" content="#{self.value_for(:meta_keywords, context)}" /> |
| - | } |
| - | end |
| - | |
| - | # Removes whitespace and quote characters from the input |
| - | def sanitized_string(string) |
| - | string ? string.strip.gsub(/"/, '') : '' |
| - | end |
| - | |
| - | def value_for(attribute, context) |
| - | object = self.metadata_object(context) |
| - | value = object.try(attribute.to_sym).blank? ? context.registers[:site].send(attribute.to_sym) : object.send(attribute.to_sym) |
| - | self.sanitized_string(value) |
| - | end |
| - | |
| - | def metadata_object(context) |
| - | context['content_instance'] || context['page'] |
| - | end |
| - | end |
| - | |
| - | class Title < Base |
| - | |
| - | def render(context) |
| - | self.render_title(context) |
| - | end |
| - | |
| - | end |
| - | |
| - | class Metadata < Base |
| - | |
| - | def render(context) |
| - | self.render_metadata(context) |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('seo', SEO::Base) |
| - | ::Liquid::Template.register_tag('seo_title', SEO::Title) |
| - | ::Liquid::Template.register_tag('seo_metadata', SEO::Metadata) |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/session_assign.rb b/lib/locomotive/wagon/liquid/tags/session_assign.rb
+0
-41
| @@ | @@ -1,41 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | |
| - | # Assign sets a variable in your session. |
| - | # |
| - | # {% session_assign foo = 'monkey' %} |
| - | # |
| - | # You can then use the variable later in the page. |
| - | # |
| - | # {{ session.foo }} |
| - | # |
| - | class SessionAssign < ::Liquid::Tag |
| - | Syntax = /(#{::Liquid::VariableSignature}+)\s*=\s*(#{::Liquid::QuotedFragment}+)/ |
| - | |
| - | def initialize(tag_name, markup, tokens, options) |
| - | if markup =~ Syntax |
| - | @to = $1 |
| - | @from = $2 |
| - | else |
| - | raise ::Liquid::SyntaxError.new(options[:locale].t("errors.syntax.session_assign"), options[:line]) |
| - | end |
| - | |
| - | super |
| - | end |
| - | |
| - | def render(context) |
| - | request = context.registers[:request] |
| - | |
| - | request.session[@to.to_sym] = context[@from] |
| - | '' |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('session_assign', SessionAssign) |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/snippet.rb b/lib/locomotive/wagon/liquid/tags/snippet.rb
+0
-63
| @@ | @@ -1,63 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | |
| - | class Snippet < ::Liquid::Include |
| - | |
| - | def render(context) |
| - | name = @template_name.gsub(/[\"\']/, '') |
| - | snippet = context.registers[:mounting_point].snippets[name] |
| - | |
| - | raise ::Liquid::StandardError.new("Unknown snippet \"#{name}\"") if snippet.nil? |
| - | |
| - | partial = self.parse_template(snippet) |
| - | |
| - | variable = context[@variable_name || @template_name[1..-2]] |
| - | |
| - | context.stack do |
| - | @attributes.each do |key, value| |
| - | context[key] = context[value] |
| - | end |
| - | |
| - | output = (if variable.is_a?(Array) |
| - | variable.collect do |variable| |
| - | context[@template_name[1..-2]] = variable |
| - | partial.render(context) |
| - | end |
| - | else |
| - | context[@template_name[1..-2]] = variable |
| - | partial.render(context) |
| - | end) |
| - | |
| - | Locomotive::Wagon::Logger.info " Rendered snippet #{name}" |
| - | |
| - | output |
| - | end |
| - | end |
| - | |
| - | protected |
| - | |
| - | def parse_template(snippet) |
| - | begin |
| - | ::Liquid::Template.parse(snippet.source) |
| - | rescue ::Liquid::Error => e |
| - | # do it again on the raw source instead so that the error line matches |
| - | # the source file. |
| - | begin |
| - | ::Liquid::Template.parse(snippet.template.raw_source) |
| - | rescue ::Liquid::Error => e |
| - | e.backtrace.unshift "#{snippet.template.filepath}:#{e.line + 1}:in `#{snippet.name}'" |
| - | e.line = self.line - 1 |
| - | raise e |
| - | end |
| - | end |
| - | end |
| - | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('include', Snippet) |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/liquid/tags/with_scope.rb b/lib/locomotive/wagon/liquid/tags/with_scope.rb
+0
-48
| @@ | @@ -1,48 +0,0 @@ |
| - | module Locomotive |
| - | module Wagon |
| - | module Liquid |
| - | module Tags |
| - | |
| - | class WithScope < Solid::Block |
| - | |
| - | OPERATORS = %w(all exists gt gte in lt lte ne nin size near within) |
| - | |
| - | SYMBOL_OPERATORS_REGEXP = /(\w+\.(#{OPERATORS.join('|')})){1}\s*\:/ |
| - | |
| - | # register the tag |
| - | tag_name :with_scope |
| - | |
| - | def initialize(tag_name, arguments_string, tokens, context = {}) |
| - | # convert symbol operators into valid ruby code |
| - | arguments_string.gsub!(SYMBOL_OPERATORS_REGEXP, ':"\1" =>') |
| - | |
| - | super(tag_name, arguments_string, tokens, context) |
| - | end |
| - | |
| - | def display(options = {}, &block) |
| - | current_context.stack do |
| - | current_context['with_scope'] = self.decode(options) |
| - | yield |
| - | end |
| - | end |
| - | |
| - | protected |
| - | |
| - | def decode(options) |
| - | HashWithIndifferentAccess.new.tap do |hash| |
| - | options.each do |key, value| |
| - | hash[key] = (case value |
| - | # regexp inside a string |
| - | when /^\/[^\/]*\/$/ then Regexp.new(value[1..-2]) |
| - | else |
| - | value |
| - | end) |
| - | end |
| - | end |
| - | end |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/server.rb b/lib/locomotive/wagon/server.rb
+0
-86
| @@ | @@ -1,86 +0,0 @@ |
| - | require 'rack-livereload' |
| - | require 'better_errors' |
| - | require 'coffee_script' |
| - | |
| - | require 'locomotive/wagon/listen' |
| - | require 'locomotive/wagon/server/middleware' |
| - | require 'locomotive/wagon/server/favicon' |
| - | require 'locomotive/wagon/server/dynamic_assets' |
| - | require 'locomotive/wagon/server/logging' |
| - | require 'locomotive/wagon/server/entry_submission' |
| - | require 'locomotive/wagon/server/path' |
| - | require 'locomotive/wagon/server/locale' |
| - | require 'locomotive/wagon/server/page' |
| - | require 'locomotive/wagon/server/timezone' |
| - | require 'locomotive/wagon/server/templatized_page' |
| - | require 'locomotive/wagon/server/renderer' |
| - | |
| - | require 'locomotive/wagon/liquid' |
| - | require 'locomotive/wagon/misc' |
| - | |
| - | module Locomotive::Wagon |
| - | class Server |
| - | |
| - | attr_reader :options |
| - | |
| - | def initialize(reader, options = {}) |
| - | Locomotive::Wagon::Dragonfly.setup!(reader.mounting_point.path) |
| - | |
| - | Sprockets::Sass.add_sass_functions = false |
| - | |
| - | @reader = reader |
| - | @options = options |
| - | @app = self.create_rack_app(@reader, @options) |
| - | |
| - | BetterErrors.application_root = reader.mounting_point.path |
| - | end |
| - | |
| - | def call(env) |
| - | env['wagon.mounting_point'] = @reader.mounting_point |
| - | @app.call(env) |
| - | end |
| - | |
| - | protected |
| - | |
| - | def create_rack_app(reader, options) |
| - | Rack::Builder.new do |
| - | use Rack::LiveReload, live_reload_port: options[:live_reload_port] if options[:live_reload_port] |
| - | |
| - | use Rack::Lint |
| - | |
| - | use BetterErrors::MiddlewareWrapper |
| - | |
| - | use Rack::Session::Cookie, { |
| - | key: 'wagon.session', |
| - | path: '/', |
| - | expire_after: 2592000, |
| - | secret: 'uselessinlocal' |
| - | } |
| - | |
| - | use ::Dragonfly::Middleware, :images |
| - | |
| - | use Rack::Static, { |
| - | urls: ['/images', '/fonts', '/samples', '/media'], |
| - | root: File.join(reader.mounting_point.path, 'public') |
| - | } |
| - | |
| - | use Favicon |
| - | use DynamicAssets, reader.mounting_point.path |
| - | |
| - | use Logging |
| - | |
| - | use EntrySubmission |
| - | |
| - | use Path |
| - | use Locale |
| - | use Timezone |
| - | |
| - | use Page |
| - | use TemplatizedPage |
| - | |
| - | run Renderer.new |
| - | end |
| - | end |
| - | |
| - | end |
| - | end |
locomotive/wagon/server/dynamic_assets.rb b/lib/locomotive/wagon/server/dynamic_assets.rb
+0
-33
| @@ | @@ -1,33 +0,0 @@ |
| - | module Locomotive::Wagon |
| - | 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::Wagon::DefaultException.new "Unable to serve a dynamic asset. Please check the logs.", e |
| - | end |
| - | else |
| - | app.call(env) |
| - | end |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
locomotive/wagon/server/entry_submission.rb b/lib/locomotive/wagon/server/entry_submission.rb
+0
-151
| @@ | @@ -1,151 +0,0 @@ |
| - | module Locomotive::Wagon |
| - | class Server |
| - | |
| - | # Mimic the submission of a content entry |
| - | # |
| - | class EntrySubmission < Middleware |
| - | |
| - | def call(env) |
| - | self.set_accessors(env) |
| - | |
| - | if slug = get_content_type_slug(env) |
| - | self.process_form(slug) |
| - | |
| - | self.navigation_behavior(env) |
| - | else |
| - | self.fetch_submitted_entry |
| - | |
| - | app.call(env) |
| - | end |
| - | end |
| - | |
| - | # Render or redirect depending on: |
| - | # - the status of the content entry (valid or not) |
| - | # - the presence of a callback or not |
| - | # - the type of response asked by the browser (html or json) |
| - | # |
| - | def navigation_behavior(env) |
| - | if @entry.valid? |
| - | navigation_success(env) |
| - | else |
| - | navigation_error(env) |
| - | end |
| - | end |
| - | |
| - | def navigation_success(env) |
| - | if self.html? |
| - | self.record_submitted_entry |
| - | self.redirect_to success_location |
| - | elsif self.json? |
| - | self.json_response |
| - | end |
| - | end |
| - | |
| - | def navigation_error(env) |
| - | if self.html? |
| - | if error_location =~ %r(^http://) |
| - | self.redirect_to error_location |
| - | else |
| - | env['PATH_INFO'] = error_location |
| - | self.liquid_assigns[@content_type.slug.singularize] = @entry |
| - | app.call(env) |
| - | end |
| - | elsif self.json? |
| - | self.json_response(422) |
| - | end |
| - | end |
| - | |
| - | protected |
| - | |
| - | def success_location; location(:success); end |
| - | def error_location; location(:error); end |
| - | |
| - | def location(state) |
| - | params[:"#{state}_callback"] || (entry_submissions_path? ? '/' : path_info) |
| - | end |
| - | |
| - | def entry_submissions_path? |
| - | !(path_info =~ %r(^/entry_submissions/)).nil? |
| - | end |
| - | |
| - | # Get the slug (or permalink) of the content type either from the PATH_INFO variable (old way) |
| - | # or from the presence of the content_type_slug param (model_form tag). |
| - | # |
| - | def get_content_type_slug(env) |
| - | if request.post? && (path_info =~ %r(^/entry_submissions/(.*)) || params[:content_type_slug]) |
| - | $1 || params[:content_type_slug] |
| - | end |
| - | end |
| - | |
| - | # Record in session the newly "persisted" content entry. |
| - | # |
| - | def record_submitted_entry |
| - | session[:now] ||= {} |
| - | session[:now][:submitted_entry] = [@content_type.slug, @entry._slug] |
| - | end |
| - | |
| - | def fetch_submitted_entry |
| - | if data = 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 ] slug The slug (or permalink) of the content type |
| - | # |
| - | # |
| - | def process_form(slug) |
| - | slug = slug.split('.').first |
| - | |
| - | @content_type = self.mounting_point.content_types[slug] |
| - | |
| - | 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 |
| - | |
| - | # 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' }, [hash.to_json]] |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/server/favicon.rb b/lib/locomotive/wagon/server/favicon.rb
+0
-17
| @@ | @@ -1,17 +0,0 @@ |
| - | module Locomotive::Wagon |
| - | 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/wagon/server/locale.rb b/lib/locomotive/wagon/server/locale.rb
+0
-42
| @@ | @@ -1,42 +0,0 @@ |
| - | module Locomotive::Wagon |
| - | 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['wagon.locale'] = locale |
| - | env['wagon.path'] = self.path |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/server/logging.rb b/lib/locomotive/wagon/server/logging.rb
+0
-32
| @@ | @@ -1,32 +0,0 @@ |
| - | module Locomotive::Wagon |
| - | 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/wagon/server/middleware.rb b/lib/locomotive/wagon/server/middleware.rb
+0
-63
| @@ | @@ -1,63 +0,0 @@ |
| - | module Locomotive::Wagon |
| - | class Server |
| - | |
| - | class Middleware |
| - | |
| - | extend Forwardable |
| - | def_delegators :request, :path_info, :session |
| - | |
| - | 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.request = Rack::Request.new(env) |
| - | self.path = env['wagon.path'] |
| - | self.mounting_point = env['wagon.mounting_point'] |
| - | self.page = env['wagon.page'] |
| - | self.content_entry = env['wagon.content_entry'] |
| - | |
| - | env['wagon.liquid_assigns'] ||= {} |
| - | self.liquid_assigns = env['wagon.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::Wagon::Logger.info msg |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/server/page.rb b/lib/locomotive/wagon/server/page.rb
+0
-67
| @@ | @@ -1,67 +0,0 @@ |
| - | module Locomotive::Wagon |
| - | 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['wagon.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/wagon/server/path.rb b/lib/locomotive/wagon/server/path.rb
+0
-34
| @@ | @@ -1,34 +0,0 @@ |
| - | module Locomotive::Wagon |
| - | 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['wagon.path'] = path |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/server/renderer.rb b/lib/locomotive/wagon/server/renderer.rb
+0
-118
| @@ | @@ -1,118 +0,0 @@ |
| - | module Locomotive::Wagon |
| - | 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::Wagon::Liquid::Drops::ContentTypes.new, |
| - | 'contents' => Locomotive::Wagon::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::Wagon::Liquid::Drops::SessionProxy.new, |
| - | 'wagon' => 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::Wagon::Logger |
| - | } |
| - | end |
| - | |
| - | end |
| - | |
| - | end |
| - | end |
locomotive/wagon/server/templatized_page.rb b/lib/locomotive/wagon/server/templatized_page.rb
+0
-32
| @@ | @@ -1,32 +0,0 @@ |
| - | module Locomotive::Wagon |
| - | 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['wagon.content_entry'] = content_entry |
| - | else |
| - | env['wagon.page'] = nil |
| - | end |
| - | end |
| - | |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/wagon/server/timezone.rb b/lib/locomotive/wagon/server/timezone.rb
+0
-18
| @@ | @@ -1,18 +0,0 @@ |
| - | module Locomotive::Wagon |
| - | 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/wagon/version.rb b/lib/locomotive/wagon/version.rb
+1
-1
| @@ | @@ -1,5 +1,5 @@ |
| module Locomotive | |
| module Wagon | |
| - | VERSION = '1.5.3' |
| + | VERSION = '2.0.0-alpha' |
| end | |
| end | |
locomotivecms_wagon.gemspec
+0
-10
| @@ | @@ -20,12 +20,6 @@ Gem::Specification.new do |gem| |
| gem.add_dependency 'thor' | |
| gem.add_dependency 'thin', '~> 1.6.1' | |
| - | gem.add_dependency 'activesupport', '~> 3.2.18' |
| - | gem.add_dependency 'locomotivecms-solid', '~> 0.2.2.1' |
| - | gem.add_dependency 'RedCloth', '~> 4.2.8' |
| - | gem.add_dependency 'redcarpet', '~> 3.0.0' |
| - | gem.add_dependency 'dragonfly', '~> 0.9.12' |
| - | gem.add_dependency 'rack-cache', '~> 1.1' |
| gem.add_dependency 'better_errors', '~> 1.0.1' | |
| gem.add_dependency 'rubyzip', '~> 1.1.0' | |
| gem.add_dependency 'netrc', '~> 0.7.7' | |
| @@ | @@ -33,10 +27,6 @@ Gem::Specification.new do |gem| |
| gem.add_dependency 'listen', '~> 2.7.5' | |
| gem.add_dependency 'rack-livereload', '~> 0.3.15' | |
| - | gem.add_dependency 'httmultiparty', '0.3.10' |
| - | gem.add_dependency 'will_paginate', '~> 3.0.3' |
| - | gem.add_dependency 'locomotivecms_mounter', '~> 1.5.2' |
| - | |
| gem.add_dependency 'faker', '~> 0.9.5' | |
| gem.add_development_dependency 'rake', '~> 10.0.4' | |