consume liquid tag
did
committed Feb 02, 2015
commit 182fecbc9144a0da9132f05063f40b9d2d4ead1a
Showing 31
changed files with
1118 additions
and 901 deletions
locomotive/steam.rb b/lib/locomotive/steam.rb
+1
-0
| @@ | @@ -2,6 +2,7 @@ |
| # require 'locomotive/decorators' | |
| require 'locomotive/common' | |
| + | require_relative 'steam/core_ext' |
| require_relative 'steam/exceptions' | |
| require_relative 'steam/decorators' | |
| require_relative 'steam/configuration' | |
locomotive/steam/liquid.rb b/lib/locomotive/steam/liquid.rb
+3
-3
| @@ | @@ -5,10 +5,10 @@ require 'solid' |
| require_relative 'liquid/errors' | |
| require_relative 'liquid/patches' | |
| require_relative 'liquid/drops/base' | |
| - | # require_relative 'liquid/tags/hybrid' |
| - | # require_relative 'liquid/tags/path_helper' |
| + | require_relative 'liquid/tags/hybrid' |
| + | require_relative 'liquid/tags/path_helper' |
| # %w{. drops tags filters}.each do |dir| | |
| - | %w{. filters}.each do |dir| |
| + | %w{. filters tags}.each do |dir| |
| Dir[File.join(File.dirname(__FILE__), 'liquid', dir, '*.rb')].each { |lib| require lib } | |
| end | |
locomotive/steam/liquid/tags/consume.rb b/lib/locomotive/steam/liquid/tags/consume.rb
+86
-76
| @@ | @@ -1,104 +1,114 @@ |
| module Locomotive | |
| - | module Liquid |
| + | module Steam |
| + | 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, context) |
| - | if markup =~ Syntax |
| - | @target = $1 |
| - | |
| - | self.prepare_url($2) |
| - | self.prepare_api_arguments($3) |
| - | else |
| - | raise ::Liquid::SyntaxError.new("Syntax Error in 'consume' - Valid syntax: consume <var> from \"<url>\" [username: value, password: value]") |
| - | end |
| + | # 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, options) |
| + | if markup =~ Syntax |
| + | @target = $1 |
| + | |
| + | self.prepare_url($2) |
| + | self.prepare_api_arguments($3) |
| + | else |
| + | raise ::Liquid::SyntaxError.new("Syntax Error in 'consume' - Valid syntax: consume <var> from \"<url>\" [username: value, password: value]") |
| + | end |
| - | @local_cache_key = self.hash |
| + | @local_cache_key = self.hash |
| - | super |
| - | end |
| + | super |
| + | end |
| - | def render(context) |
| - | self.set_api_options(context) |
| + | def render(context) |
| + | self.set_api_options(context) |
| - | if instance_variable_defined? :@variable_name |
| - | @url = context[@variable_name] |
| - | end |
| + | if instance_variable_defined? :@variable_name |
| + | @url = context[@variable_name] |
| + | end |
| - | render_all_and_cache_it(context) |
| - | end |
| + | render_all_and_cache_it(context) |
| + | end |
| - | protected |
| + | 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]") |
| + | 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 | |
| - | end |
| - | def prepare_api_arguments(string) |
| - | string = string.gsub(/^(\s*,)/, '').strip |
| - | @api_arguments = Solid::Arguments.parse(string) |
| - | 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 ? @api_arguments.interpolate(context).first || {} : {} |
| - | @expires_in = @api_options.delete(:expires_in) || 0 |
| - | end |
| + | def set_api_options(context) |
| + | @api_options = @api_arguments ? @api_arguments.interpolate(context).first || {} : {} |
| + | @expires_in = @api_options.delete(:expires_in) || 0 |
| + | end |
| - | def page_fragment_cache_key(url) |
| - | Digest::SHA1.hexdigest(@target.to_s + url) |
| - | end |
| + | def page_fragment_cache_key(url) |
| + | Digest::SHA1.hexdigest(@target.to_s + url) |
| + | end |
| - | def cached_response |
| - | @@local_cache ||= {} |
| - | @@local_cache[@local_cache_key] |
| - | 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 cached_response=(response) |
| + | @@local_cache ||= {} |
| + | @@local_cache[@local_cache_key] = response |
| + | end |
| - | def render_all_and_cache_it(context) |
| - | Rails.cache.fetch(page_fragment_cache_key(@url), expires_in: @expires_in, force: @expires_in == 0) do |
| - | self.render_all_without_cache(context) |
| + | def render_all_and_cache_it(context) |
| + | cache_service(context).fetch(page_fragment_cache_key(@url), expires_in: @expires_in, force: @expires_in == 0) do |
| + | self.render_all_without_cache(context) |
| + | end |
| end | |
| - | end |
| - | def render_all_without_cache(context) |
| - | context.stack do |
| - | begin |
| - | context.scopes.last[@target.to_s] = Locomotive::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 |
| + | def render_all_without_cache(context) |
| + | context.stack do |
| + | begin |
| + | context.scopes.last[@target.to_s] = service(context).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 |
| + | end |
| + | |
| + | @body.render(context) |
| end | |
| + | end |
| - | render_all(@nodelist, context) |
| + | def service(context) |
| + | context.registers[:services].external_api |
| end | |
| + | |
| + | def cache_service(context) |
| + | context.registers[:services].cache |
| + | end |
| + | |
| end | |
| + | ::Liquid::Template.register_tag('consume', Consume) |
| end | |
| - | |
| - | ::Liquid::Template.register_tag('consume', Consume) |
| end | |
| end | |
| end | |
locomotive/steam/liquid/tags/csrf.rb b/lib/locomotive/steam/liquid/tags/csrf.rb
+26
-24
| @@ | @@ -1,40 +1,42 @@ |
| module Locomotive | |
| - | module Liquid |
| - | module Tags |
| - | module Csrf |
| + | module Steam |
| + | module Liquid |
| + | module Tags |
| + | module Csrf |
| - | class Param < ::Liquid::Tag |
| + | class Param < ::Liquid::Tag |
| - | def render(context) |
| - | controller = context.registers[:controller] |
| - | name = controller.send(:request_forgery_protection_token).to_s |
| - | value = controller.send(:form_authenticity_token) |
| + | def render(context) |
| + | controller = context.registers[:controller] |
| + | name = controller.send(:request_forgery_protection_token).to_s |
| + | value = controller.send(:form_authenticity_token) |
| + | |
| + | %(<input type="hidden" name="#{name}" value="#{value}">) |
| + | end |
| - | %(<input type="hidden" name="#{name}" value="#{value}">) |
| end | |
| - | end |
| + | class Meta < ::Liquid::Tag |
| - | class Meta < ::Liquid::Tag |
| + | def render(context) |
| + | controller = context.registers[:controller] |
| + | name = controller.send(:request_forgery_protection_token).to_s |
| + | value = controller.send(:form_authenticity_token) |
| - | def render(context) |
| - | controller = context.registers[:controller] |
| - | name = controller.send(:request_forgery_protection_token).to_s |
| - | value = controller.send(:form_authenticity_token) |
| + | %{ |
| + | <meta name="csrf-param" content="#{name}"> |
| + | <meta name="csrf-token" content="#{value}"> |
| + | } |
| + | end |
| - | %{ |
| - | <meta name="csrf-param" content="#{name}"> |
| - | <meta name="csrf-token" content="#{value}"> |
| - | } |
| end | |
| end | |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('csrf_param', Csrf::Param) |
| - | ::Liquid::Template.register_tag('csrf_meta', Csrf::Meta) |
| + | ::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 | |
| + | end |
locomotive/steam/liquid/tags/editable.rb b/lib/locomotive/steam/liquid/tags/editable.rb
+4
-4
| @@ | @@ -1,4 +1,4 @@ |
| - | require 'locomotive/liquid/tags/editable/base' |
| - | require 'locomotive/liquid/tags/editable/text' |
| - | require 'locomotive/liquid/tags/editable/file' |
| - | require 'locomotive/liquid/tags/editable/control' |
| \ No newline at end of file | |
| + | # require 'locomotive/liquid/tags/editable/base' |
| + | # require 'locomotive/liquid/tags/editable/text' |
| + | # require 'locomotive/liquid/tags/editable/file' |
| + | # require 'locomotive/liquid/tags/editable/control' |
locomotive/steam/liquid/tags/extends.rb b/lib/locomotive/steam/liquid/tags/extends.rb
+31
-29
| @@ | @@ -1,47 +1,49 @@ |
| module Locomotive | |
| - | module Liquid |
| - | module Tags |
| - | class Extends < ::Liquid::Extends |
| + | module Steam |
| + | module Liquid |
| + | module Tags |
| + | class Extends < ::Liquid::Extends |
| - | def prepare_parsing |
| - | super |
| + | def prepare_parsing |
| + | super |
| - | parent_page = @context[:parent_page] |
| + | parent_page = @context[:parent_page] |
| - | @context[:page].merge_editable_elements_from_page(parent_page) |
| + | @context[:page].merge_editable_elements_from_page(parent_page) |
| - | @context[:snippets] = parent_page.snippet_dependencies |
| - | @context[:templates] = ([*parent_page.template_dependencies] + [parent_page.id]).compact |
| - | end |
| + | @context[:snippets] = parent_page.snippet_dependencies |
| + | @context[:templates] = ([*parent_page.template_dependencies] + [parent_page.id]).compact |
| + | end |
| - | private |
| + | private |
| - | def parse_parent_template |
| - | if @template_name == 'parent' |
| - | @context[:parent_page] = @context[:cached_parent] || @context[:page].parent |
| - | else |
| - | locale = ::Mongoid::Fields::I18n.locale |
| + | def parse_parent_template |
| + | if @template_name == 'parent' |
| + | @context[:parent_page] = @context[:cached_parent] || @context[:page].parent |
| + | else |
| + | locale = ::Mongoid::Fields::I18n.locale |
| - | @context[:parent_page] = @context[:cached_pages].try(:[], @template_name) || |
| - | @context[:site].pages.where("fullpath.#{locale}" => @template_name).first |
| - | end |
| + | @context[:parent_page] = @context[:cached_pages].try(:[], @template_name) || |
| + | @context[:site].pages.where("fullpath.#{locale}" => @template_name).first |
| + | end |
| - | raise PageNotFound.new("Page with fullpath '#{@template_name}' was not found") if @context[:parent_page].nil? |
| + | raise PageNotFound.new("Page with fullpath '#{@template_name}' was not found") if @context[:parent_page].nil? |
| - | # be sure to work with a copy of the parent template otherwise there will be conflicts |
| - | parent_template = @context[:parent_page].template.try(:clone) |
| + | # be sure to work with a copy of the parent template otherwise there will be conflicts |
| + | parent_template = @context[:parent_page].template.try(:clone) |
| - | raise PageNotTranslated.new("Page with fullpath '#{@template_name}' was not translated") if parent_template.nil? |
| + | raise PageNotTranslated.new("Page with fullpath '#{@template_name}' was not translated") if parent_template.nil? |
| - | # force the page to restore the original version of its template (from the serialized version) |
| - | @context[:parent_page].instance_variable_set(:@template, nil) |
| + | # force the page to restore the original version of its template (from the serialized version) |
| + | @context[:parent_page].instance_variable_set(:@template, nil) |
| + | |
| + | parent_template |
| + | end |
| - | parent_template |
| end | |
| + | ::Liquid::Template.register_tag('extends', Extends) |
| end | |
| - | |
| - | ::Liquid::Template.register_tag('extends', Extends) |
| end | |
| end | |
| - | end |
| \ No newline at end of file | |
| + | end |
locomotive/steam/liquid/tags/fetch_page.rb b/lib/locomotive/steam/liquid/tags/fetch_page.rb
+27
-25
| @@ | @@ -1,36 +1,38 @@ |
| module Locomotive | |
| - | module Liquid |
| - | module Tags |
| + | module Steam |
| + | 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 |
| + | # 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}+)/ |
| + | 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") |
| + | 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 | |
| - | super |
| + | def render(context) |
| + | context.scopes.last[@var] = context.registers[:site].pages.where(handle: @handle).first |
| + | '' |
| + | end |
| end | |
| - | def render(context) |
| - | context.scopes.last[@var] = context.registers[:site].pages.where(handle: @handle).first |
| - | '' |
| - | end |
| + | ::Liquid::Template.register_tag('fetch_page', FetchPage) |
| end | |
| - | |
| - | ::Liquid::Template.register_tag('fetch_page', FetchPage) |
| end | |
| end | |
| - | end |
| \ No newline at end of file | |
| + | end |
locomotive/steam/liquid/tags/google_analytics.rb b/lib/locomotive/steam/liquid/tags/google_analytics.rb
+28
-26
| @@ | @@ -1,39 +1,41 @@ |
| module Liquid | |
| - | module Locomotive |
| - | module Tags |
| - | class GoogleAnalytics < ::Liquid::Tag |
| + | module Steam |
| + | module Locomotive |
| + | module Tags |
| + | class GoogleAnalytics < ::Liquid::Tag |
| - | Syntax = /(#{::Liquid::Expression}+)?/ |
| + | Syntax = /(#{::Liquid::Expression}+)?/ |
| - | def initialize(tag_name, markup, tokens, context) |
| - | if markup =~ Syntax |
| - | @account_id = $1.gsub('\'', '') |
| - | else |
| - | raise ::Liquid::SyntaxError.new("Syntax Error in 'google_analytics' - Valid syntax: google_analytics <account_id>") |
| - | end |
| + | def initialize(tag_name, markup, tokens, context) |
| + | if markup =~ Syntax |
| + | @account_id = $1.gsub('\'', '') |
| + | else |
| + | raise ::Liquid::SyntaxError.new("Syntax Error in 'google_analytics' - Valid syntax: google_analytics <account_id>") |
| + | end |
| - | super |
| - | end |
| + | super |
| + | end |
| - | def render(context) |
| - | %{ |
| - | <script type="text/javascript"> |
| + | def render(context) |
| + | %{ |
| + | <script type="text/javascript"> |
| - | var _gaq = _gaq || []; |
| - | _gaq.push(['_setAccount', '#{@account_id}']); |
| - | _gaq.push(['_trackPageview']); |
| + | var _gaq = _gaq || []; |
| + | _gaq.push(['_setAccount', '#{@account_id}']); |
| + | _gaq.push(['_trackPageview']); |
| - | (function() \{ |
| - | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; |
| - | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; |
| - | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); |
| - | \})(); |
| + | (function() \{ |
| + | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; |
| + | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; |
| + | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); |
| + | \})(); |
| - | </script>} |
| + | </script>} |
| + | end |
| end | |
| - | end |
| - | ::Liquid::Template.register_tag('google_analytics', GoogleAnalytics) |
| + | ::Liquid::Template.register_tag('google_analytics', GoogleAnalytics) |
| + | end |
| end | |
| end | |
| end | |
locomotive/steam/liquid/tags/hybrid.rb b/lib/locomotive/steam/liquid/tags/hybrid.rb
+23
-17
| @@ | @@ -1,25 +1,31 @@ |
| module Locomotive | |
| - | 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 |
| + | module Steam |
| + | 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 | |
| + | end |
locomotive/steam/liquid/tags/inherited_block.rb b/lib/locomotive/steam/liquid/tags/inherited_block.rb
+20
-18
| @@ | @@ -1,31 +1,33 @@ |
| module Locomotive | |
| - | module Liquid |
| - | module Tags |
| - | class InheritedBlock < ::Liquid::InheritedBlock |
| + | module Steam |
| + | module Liquid |
| + | module Tags |
| + | class InheritedBlock < ::Liquid::InheritedBlock |
| - | def end_tag |
| - | super |
| + | def end_tag |
| + | super |
| - | if !self.contains_super?(@nodelist) # then disable all editable_elements coming from the parent block too and not used |
| - | @context[:page].disable_parent_editable_elements(@name) unless @context[:page].nil? |
| + | if !self.contains_super?(@nodelist) # then disable all editable_elements coming from the parent block too and not used |
| + | @context[:page].disable_parent_editable_elements(@name) unless @context[:page].nil? |
| + | end |
| end | |
| - | end |
| - | protected |
| + | protected |
| - | def contains_super?(nodelist) |
| - | nodelist.any? do |node| |
| - | if node.is_a?(::Liquid::Variable) && node.name == 'block.super' |
| - | true |
| - | elsif node.respond_to?(:nodelist) && !node.nodelist.nil? && !node.is_a?(Locomotive::Liquid::Tags::InheritedBlock) |
| - | contains_super?(node.nodelist) |
| + | def contains_super?(nodelist) |
| + | nodelist.any? do |node| |
| + | if node.is_a?(::Liquid::Variable) && node.name == 'block.super' |
| + | true |
| + | elsif node.respond_to?(:nodelist) && !node.nodelist.nil? && !node.is_a?(Locomotive::Liquid::Tags::InheritedBlock) |
| + | contains_super?(node.nodelist) |
| + | end |
| end | |
| end | |
| + | |
| end | |
| + | ::Liquid::Template.register_tag('block', InheritedBlock) |
| end | |
| - | |
| - | ::Liquid::Template.register_tag('block', InheritedBlock) |
| end | |
| end | |
| - | end |
| \ No newline at end of file | |
| + | end |
locomotive/steam/liquid/tags/inline_editor.rb b/lib/locomotive/steam/liquid/tags/inline_editor.rb
+0
-40
| @@ | @@ -1,40 +0,0 @@ |
| - | module Liquid |
| - | module Locomotive |
| - | module Tags |
| - | class InlineEditor < ::Liquid::Tag |
| - | |
| - | def render(context) |
| - | if context.registers[:current_locomotive_account] && context.registers[:inline_editor] |
| - | |
| - | plugins = 'common/ui,common/format,common/table,common/list,common/link,common/highlighteditables,common/block,common/undo,common/contenthandler,common/paste,common/commands,common/abbr,common/align,common/horizontalruler,common/image,custom/locomotive_media,custom/inputcontrol' |
| - | |
| - | controller = context.registers[:controller] |
| - | controller.instance_variable_set(:@plugins, plugins) |
| - | |
| - | page = context.registers[:page].to_presenter.as_json_for_html_view |
| - | page['lang'] = context['locale'] |
| - | |
| - | html = <<-HTML |
| - | %meta{ content: true, name: 'inline-editor' } |
| - | |
| - | = stylesheet_link_tag 'aloha/css/aloha.css' |
| - | = javascript_include_tag 'locomotive/aloha', :'data-aloha-plugins' => @plugins |
| - | |
| - | %script{ type: 'text/javascript' } |
| - | :plain |
| - | Aloha.ready(function() \{ |
| - | window.parent.application_view.set_page(#{controller.view_context.escape_json page.to_json.html_safe}); |
| - | \}); |
| - | HTML |
| - | |
| - | Haml::Engine.new(html.gsub(/\n+/, "\n").gsub(/^\s{14}/, ''), escape_html: true).render(controller.view_context) |
| - | else |
| - | '' |
| - | end |
| - | end |
| - | end |
| - | |
| - | ::Liquid::Template.register_tag('inline_editor', InlineEditor) |
| - | end |
| - | end |
| - | end |
| \ No newline at end of file | |
locomotive/steam/liquid/tags/javascript.rb b/lib/locomotive/steam/liquid/tags/javascript.rb
+16
-11
| @@ | @@ -1,16 +1,21 @@ |
| module Locomotive | |
| - | module Liquid |
| - | module Tags |
| - | class Javascript < ::Liquid::Block |
| - | |
| - | include ActionView::Helpers::JavaScriptHelper |
| - | include ActionView::Helpers::TagHelper |
| - | |
| - | def render(context) |
| - | javascript_tag super |
| + | module Steam |
| + | module Liquid |
| + | module Tags |
| + | class Javascript < ::Liquid::Block |
| + | |
| + | # TODO |
| + | # include ActionView::Helpers::JavaScriptHelper |
| + | # include ActionView::Helpers::TagHelper |
| + | |
| + | def render(context) |
| + | javascript_tag super |
| + | end |
| end | |
| + | |
| + | ::Liquid::Template.register_tag('javascript', Javascript) |
| + | |
| end | |
| - | ::Liquid::Template.register_tag('javascript', Javascript) |
| end | |
| end | |
| - | end |
| \ No newline at end of file | |
| + | end |
locomotive/steam/liquid/tags/link_to.rb b/lib/locomotive/steam/liquid/tags/link_to.rb
+28
-26
| @@ | @@ -1,43 +1,45 @@ |
| module Locomotive | |
| - | module Liquid |
| - | module Tags |
| - | class LinkTo < Hybrid |
| + | module Steam |
| + | module Liquid |
| + | module Tags |
| + | class LinkTo < Hybrid |
| - | include PathHelper |
| - | include ActionView::Helpers::UrlHelper |
| + | include PathHelper |
| + | # include ActionView::Helpers::UrlHelper |
| - | def render(context) |
| - | render_path(context) do |page, path| |
| - | label = label_from_page(page) |
| + | 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 |
| + | if @render_as_block |
| + | context.scopes.last['target'] = page |
| + | label = super.html_safe |
| + | end |
| - | link_to label, path |
| + | link_to label, path |
| + | end |
| end | |
| - | end |
| - | def wrong_syntax! |
| - | raise SyntaxError.new("Syntax Error in 'link_to' - Valid syntax: link_to page_handle, locale es (locale is optional)") |
| - | end |
| + | def wrong_syntax! |
| + | raise SyntaxError.new("Syntax Error in 'link_to' - Valid syntax: link_to page_handle, locale es (locale is optional)") |
| + | end |
| - | protected |
| + | protected |
| - | def label_from_page(page) |
| - | ::Mongoid::Fields::I18n.with_locale(@options['locale']) do |
| - | if page.templatized? |
| - | page.content_entry._label |
| - | else |
| - | page.title |
| + | def label_from_page(page) |
| + | ::Mongoid::Fields::I18n.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 | |
| - | |
| - | ::Liquid::Template.register_tag('link_to', LinkTo) |
| end | |
| end | |
| end | |
locomotive/steam/liquid/tags/locale_switcher.rb b/lib/locomotive/steam/liquid/tags/locale_switcher.rb
+67
-65
| @@ | @@ -1,83 +1,85 @@ |
| module Locomotive | |
| - | 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, context) |
| - | @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("Syntax Error in 'locale_switcher' - Valid syntax: locale_switcher <options>") |
| + | module Steam |
| + | 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, context) |
| + | @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("Syntax Error in 'locale_switcher' - Valid syntax: locale_switcher <options>") |
| + | end |
| + | |
| + | super |
| end | |
| - | super |
| - | end |
| + | def render(context) |
| + | @site, @page = context.registers[:site], context.registers[:page] |
| - | def render(context) |
| - | @site, @page = context.registers[:site], context.registers[:page] |
| + | output = %(<div id="locale-switcher">) |
| - | output = %(<div id="locale-switcher">) |
| + | output += @site.locales.collect do |locale| |
| + | ::Mongoid::Fields::I18n.with_locale(locale) do |
| + | fullpath = @site.localized_page_fullpath(@page, locale) |
| - | output += @site.locales.collect do |locale| |
| - | ::Mongoid::Fields::I18n.with_locale(locale) do |
| - | fullpath = @site.localized_page_fullpath(@page, locale) |
| + | if @page.templatized? |
| + | fullpath.gsub!('content_type_template', context['entry']._permalink) |
| + | end |
| - | if @page.templatized? |
| - | fullpath.gsub!('content_type_template', context['entry']._permalink) |
| - | end |
| + | css = link_class(locale, context['locale']) |
| - | css = link_class(locale, context['locale']) |
| - | |
| - | %(<a href="/#{fullpath}" class="#{css}">#{link_label(locale)}</a>) |
| - | end |
| - | end.join(@options[:sep]) |
| + | %(<a href="/#{fullpath}" class="#{css}">#{link_label(locale)}</a>) |
| + | end |
| + | end.join(@options[:sep]) |
| - | output += %(</div>) |
| - | end |
| + | output += %(</div>) |
| + | end |
| - | private |
| + | private |
| - | def link_class(locale, current_locale) |
| - | css = [locale] |
| - | css << 'current' if locale == current_locale |
| - | css.join(' ') |
| - | end |
| + | def link_class(locale, current_locale) |
| + | css = [locale] |
| + | css << 'current' if locale == current_locale |
| + | 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 |
| + | 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 | |
| + | |
| end | |
| + | ::Liquid::Template.register_tag('locale_switcher', LocaleSwitcher) |
| end | |
| - | |
| - | ::Liquid::Template.register_tag('locale_switcher', LocaleSwitcher) |
| end | |
| end | |
| - | end |
| \ No newline at end of file | |
| + | end |
locomotive/steam/liquid/tags/model_form.rb b/lib/locomotive/steam/liquid/tags/model_form.rb
+70
-68
| @@ | @@ -1,75 +1,77 @@ |
| module Locomotive | |
| - | 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) + csrf_html + 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 csrf_html |
| - | name = controller.send(:request_forgery_protection_token).to_s |
| - | value = controller.send(:form_authenticity_token) |
| - | |
| - | html_tag :input, type: 'hidden', name: name, value: value |
| - | 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 |
| + | module Steam |
| + | 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) + csrf_html + 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 csrf_html |
| + | name = controller.send(:request_forgery_protection_token).to_s |
| + | value = controller.send(:form_authenticity_token) |
| + | |
| + | html_tag :input, type: 'hidden', name: name, value: value |
| + | 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 controller |
| + | current_context.registers[:controller] |
| + | end |
| + | |
| + | 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 |
| - | private |
| - | |
| - | def controller |
| - | current_context.registers[:controller] |
| - | end |
| - | |
| - | 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 |
| \ No newline at end of file | |
| + | end |
locomotive/steam/liquid/tags/nav.rb b/lib/locomotive/steam/liquid/tags/nav.rb
+123
-121
| @@ | @@ -1,164 +1,166 @@ |
| module Locomotive | |
| - | 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. |
| - | # |
| - | # Passing through depth will control how many nested children are output |
| - | # |
| - | # 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}+)?/ |
| - | |
| - | def initialize(tag_name, markup, tokens, context) |
| - | if markup =~ Syntax |
| - | @source = ($1 || 'page').gsub(/"|'/, '') |
| - | @options = { id: 'nav', depth: 1, class: '', active_class: 'on', bootstrap: false } |
| - | markup.scan(::Liquid::TagAttributes) { |key, value| @options[key.to_sym] = value.gsub(/"|'/, '') } |
| - | |
| - | @options[:exclude] = Regexp.new(@options[:exclude]) if @options[:exclude] |
| - | |
| - | @options[:add_attributes] = [] |
| - | if @options[:snippet] |
| - | template = @options[:snippet].include?('{') ? @options[:snippet] : context[:site].snippets.where(slug: @options[:snippet] ).try(:first).try(:template) |
| - | unless template.blank? |
| - | @options[:liquid_render] = ::Liquid::Template.parse(template) |
| - | @options[:add_attributes] = ['editable_elements'] |
| + | module Steam |
| + | 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. |
| + | # |
| + | # Passing through depth will control how many nested children are output |
| + | # |
| + | # 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}+)?/ |
| + | |
| + | def initialize(tag_name, markup, tokens, context) |
| + | if markup =~ Syntax |
| + | @source = ($1 || 'page').gsub(/"|'/, '') |
| + | @options = { id: 'nav', depth: 1, class: '', active_class: 'on', bootstrap: false } |
| + | markup.scan(::Liquid::TagAttributes) { |key, value| @options[key.to_sym] = value.gsub(/"|'/, '') } |
| + | |
| + | @options[:exclude] = Regexp.new(@options[:exclude]) if @options[:exclude] |
| + | |
| + | @options[:add_attributes] = [] |
| + | if @options[:snippet] |
| + | template = @options[:snippet].include?('{') ? @options[:snippet] : context[:site].snippets.where(slug: @options[:snippet] ).try(:first).try(:template) |
| + | unless template.blank? |
| + | @options[:liquid_render] = ::Liquid::Template.parse(template) |
| + | @options[:add_attributes] = ['editable_elements'] |
| + | end |
| end | |
| + | |
| + | else |
| + | raise ::Liquid::SyntaxError.new("Syntax Error in 'nav' - Valid syntax: nav <page|site> <options>") |
| end | |
| - | else |
| - | raise ::Liquid::SyntaxError.new("Syntax Error in 'nav' - Valid syntax: nav <page|site> <options>") |
| + | super |
| end | |
| - | super |
| - | end |
| + | def render(context) |
| + | children_output = [] |
| - | def render(context) |
| - | children_output = [] |
| + | entries = fetch_entries(context) |
| - | entries = fetch_entries(context) |
| + | entries.each_with_index do |p, index| |
| + | css = [] |
| + | css << 'first' if index == 0 |
| + | css << 'last' if index == entries.size - 1 |
| - | entries.each_with_index do |p, index| |
| - | css = [] |
| - | css << 'first' if index == 0 |
| - | css << 'last' if index == entries.size - 1 |
| + | children_output << render_entry_link(context, p, css.join(' '), 1) |
| + | end |
| - | children_output << render_entry_link(context, p, css.join(' '), 1) |
| - | end |
| + | output = children_output.join("\n") |
| - | output = children_output.join("\n") |
| + | if @options[:no_wrapper] != 'true' |
| + | list_class = !@options[:class].blank? ? %( class="#{@options[:class]}") : '' |
| + | output = %{<nav id="#{@options[:id]}"#{list_class}><ul>\n#{output}</ul></nav>} |
| + | end |
| - | if @options[:no_wrapper] != 'true' |
| - | list_class = !@options[:class].blank? ? %( class="#{@options[:class]}") : '' |
| - | output = %{<nav id="#{@options[:id]}"#{list_class}><ul>\n#{output}</ul></nav>} |
| + | output |
| end | |
| - | output |
| - | end |
| + | private |
| - | private |
| + | # Determines root node for the list |
| + | def fetch_entries(context) |
| + | @site, @page = context.registers[:site], context.registers[:page] |
| - | # Determines root node for the list |
| - | def fetch_entries(context) |
| - | @site, @page = context.registers[:site], context.registers[:page] |
| + | children = (case @source |
| + | when 'site' then @site.pages.root.minimal_attributes(@options[:add_attributes]).first # start from home page |
| + | when 'parent' then @page.parent || @page |
| + | when 'page' then @page |
| + | else |
| + | @site.pages.fullpath(@source).minimal_attributes(@options[:add_attributes]).first |
| + | end).children_with_minimal_attributes(@options[:add_attributes]).to_a |
| - | children = (case @source |
| - | when 'site' then @site.pages.root.minimal_attributes(@options[:add_attributes]).first # start from home page |
| - | when 'parent' then @page.parent || @page |
| - | when 'page' then @page |
| - | else |
| - | @site.pages.fullpath(@source).minimal_attributes(@options[:add_attributes]).first |
| - | end).children_with_minimal_attributes(@options[:add_attributes]).to_a |
| + | children.delete_if { |p| !include_page?(p) } |
| + | end |
| - | children.delete_if { |p| !include_page?(p) } |
| - | end |
| + | # Returns a list element, a link to the page and its children |
| + | def render_entry_link(context, page, css, depth) |
| + | selected = @page.fullpath =~ /^#{page.fullpath}(\/.*)?$/ ? " #{@options[:active_class]}" : '' |
| - | # Returns a list element, a link to the page and its children |
| - | def render_entry_link(context, page, css, depth) |
| - | selected = @page.fullpath =~ /^#{page.fullpath}(\/.*)?$/ ? " #{@options[:active_class]}" : '' |
| + | icon = @options[:icon] ? '<span></span>' : '' |
| + | title = render_title(context, page) |
| + | label = %{#{icon if @options[:icon] != 'after' }#{title}#{icon if @options[:icon] == 'after' }} |
| - | icon = @options[:icon] ? '<span></span>' : '' |
| - | title = render_title(context, page) |
| - | label = %{#{icon if @options[:icon] != 'after' }#{title}#{icon if @options[:icon] == 'after' }} |
| + | link_options = caret = '' |
| + | href = File.join('/', @site.localized_page_fullpath(page)) |
| - | link_options = caret = '' |
| - | href = File.join('/', @site.localized_page_fullpath(page)) |
| + | if render_children_for_page?(page, depth) && bootstrap? |
| + | css += ' dropdown' |
| + | link_options = %{ class="dropdown-toggle" data-toggle="dropdown"} |
| + | href = '#' |
| + | caret = %{ <b class="caret"></b>} |
| + | end |
| + | |
| + | output = %{<li id="#{page.slug.to_s.dasherize}-link" class="link#{selected} #{css}">} |
| + | output << %{<a href="#{href}"#{link_options}>#{label}#{caret}</a>} |
| + | output << render_entry_children(context, page, depth.succ) if (depth.succ <= @options[:depth].to_i) |
| + | output << %{</li>} |
| - | if render_children_for_page?(page, depth) && bootstrap? |
| - | css += ' dropdown' |
| - | link_options = %{ class="dropdown-toggle" data-toggle="dropdown"} |
| - | href = '#' |
| - | caret = %{ <b class="caret"></b>} |
| + | output.strip |
| end | |
| - | output = %{<li id="#{page.slug.to_s.dasherize}-link" class="link#{selected} #{css}">} |
| - | output << %{<a href="#{href}"#{link_options}>#{label}#{caret}</a>} |
| - | output << render_entry_children(context, page, depth.succ) if (depth.succ <= @options[:depth].to_i) |
| - | output << %{</li>} |
| + | def render_children_for_page?(page, depth) |
| + | depth.succ <= @options[:depth].to_i && page.children.reject { |c| !include_page?(c) }.any? |
| + | end |
| - | output.strip |
| - | end |
| + | # Recursively creates a nested unordered list for the depth specified |
| + | def render_entry_children(context, page, depth) |
| + | output = %{} |
| - | def render_children_for_page?(page, depth) |
| - | depth.succ <= @options[:depth].to_i && page.children.reject { |c| !include_page?(c) }.any? |
| - | end |
| + | children = page.children_with_minimal_attributes(@options[:add_attributes]).reject { |c| !include_page?(c) } |
| + | if children.present? |
| + | output = %{<ul id="#{@options[:id]}-#{page.slug.to_s.dasherize}" class="#{bootstrap? ? 'dropdown-menu' : ''}">} |
| + | children.each do |c, page| |
| + | css = [] |
| + | css << 'first' if children.first == c |
| + | css << 'last' if children.last == c |
| - | # Recursively creates a nested unordered list for the depth specified |
| - | def render_entry_children(context, page, depth) |
| - | output = %{} |
| + | output << render_entry_link(context, c, css.join(' '), depth) |
| + | end |
| + | output << %{</ul>} |
| + | end |
| - | children = page.children_with_minimal_attributes(@options[:add_attributes]).reject { |c| !include_page?(c) } |
| - | if children.present? |
| - | output = %{<ul id="#{@options[:id]}-#{page.slug.to_s.dasherize}" class="#{bootstrap? ? 'dropdown-menu' : ''}">} |
| - | children.each do |c, page| |
| - | css = [] |
| - | css << 'first' if children.first == c |
| - | css << 'last' if children.last == c |
| + | output |
| + | end |
| - | output << render_entry_link(context, c, css.join(' '), depth) |
| + | def render_title(context, page) |
| + | if @options[:liquid_render] |
| + | context.stack do |
| + | context['page'] = page |
| + | @options[:liquid_render].render(context) |
| + | end |
| + | else |
| + | page.title |
| end | |
| - | output << %{</ul>} |
| end | |
| - | output |
| - | end |
| - | |
| - | def render_title(context, page) |
| - | if @options[:liquid_render] |
| - | context.stack do |
| - | context['page'] = page |
| - | @options[:liquid_render].render(context) |
| + | # Determines whether or not a page should be a part of the menu |
| + | def include_page?(page) |
| + | if !page.listed? || page.templatized? || !page.published? |
| + | false |
| + | elsif @options[:exclude] |
| + | (page.fullpath =~ @options[:exclude]).nil? |
| + | else |
| + | true |
| end | |
| - | else |
| - | page.title |
| end | |
| - | end |
| - | # Determines whether or not a page should be a part of the menu |
| - | def include_page?(page) |
| - | if !page.listed? || page.templatized? || !page.published? |
| - | false |
| - | elsif @options[:exclude] |
| - | (page.fullpath =~ @options[:exclude]).nil? |
| - | else |
| - | true |
| + | def bootstrap? |
| + | @options[:bootstrap] == 'true' |
| end | |
| - | end |
| - | def bootstrap? |
| - | @options[:bootstrap] == 'true' |
| end | |
| + | ::Liquid::Template.register_tag('nav', Nav) |
| end | |
| - | |
| - | ::Liquid::Template.register_tag('nav', Nav) |
| end | |
| end | |
| end | |
locomotive/steam/liquid/tags/paginate.rb b/lib/locomotive/steam/liquid/tags/paginate.rb
+90
-91
| @@ | @@ -1,114 +1,113 @@ |
| module Locomotive | |
| - | |
| - | module Liquid |
| - | |
| + | module Steam |
| + | 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, context) |
| - | if markup =~ Syntax |
| - | @collection_name = $1 |
| - | @per_page = $2.to_i |
| - | @options = { } |
| - | markup.scan(::Liquid::TagAttributes) { |key, value| @options[key.to_sym] = value.gsub(/^'/, '').gsub(/'$/, '') } |
| - | @window_size = @options[:window_size] ? @options[:window_size].to_i : 3 |
| - | else |
| - | raise ::Liquid::SyntaxError.new("Syntax Error in 'paginate' - Valid syntax: paginate <collection> by <number>") |
| - | end |
| + | # 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, context) |
| + | if markup =~ Syntax |
| + | @collection_name = $1 |
| + | @per_page = $2.to_i |
| + | @options = { } |
| + | markup.scan(::Liquid::TagAttributes) { |key, value| @options[key.to_sym] = value.gsub(/^'/, '').gsub(/'$/, '') } |
| + | @window_size = @options[:window_size] ? @options[:window_size].to_i : 3 |
| + | else |
| + | raise ::Liquid::SyntaxError.new("Syntax Error in 'paginate' - Valid syntax: paginate <collection> by <number>") |
| + | end |
| - | super |
| - | end |
| + | super |
| + | end |
| - | def render(context) |
| - | context.stack do |
| - | collection = context[@collection_name] |
| + | def render(context) |
| + | context.stack do |
| + | collection = context[@collection_name] |
| - | raise ::Liquid::ArgumentError.new("Cannot paginate array '#{@collection_name}'. Not found.") if collection.nil? |
| + | raise ::Liquid::ArgumentError.new("Cannot paginate array '#{@collection_name}'. Not found.") if collection.nil? |
| - | if collection.is_a? Array |
| - | pagination = Kaminari.paginate_array(collection).page(context['current_page']).per(@per_page).to_liquid.stringify_keys |
| - | else |
| - | pagination = collection.send(:paginate, { |
| - | page: context['current_page'], |
| - | per_page: @per_page |
| - | }).to_liquid.stringify_keys |
| - | end |
| - | 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) |
| + | if collection.is_a? Array |
| + | pagination = Kaminari.paginate_array(collection).page(context['current_page']).per(@per_page).to_liquid.stringify_keys |
| + | else |
| + | pagination = collection.send(:paginate, { |
| + | page: context['current_page'], |
| + | per_page: @per_page |
| + | }).to_liquid.stringify_keys |
| + | end |
| + | 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 | |
| - | |
| - | hellip_break = false |
| end | |
| - | end |
| - | context['paginate'] = pagination |
| + | context['paginate'] = pagination |
| - | render_all(@nodelist, context) |
| + | render_all(@nodelist, context) |
| + | end |
| end | |
| - | end |
| - | private |
| + | 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 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 |
| - | @window_size |
| - | end |
| + | def window_size |
| + | @window_size |
| + | end |
| - | def no_link(title) |
| - | { 'title' => title, 'is_link' => false, 'hellip_break' => title == '…' } |
| - | 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 } |
| + | 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 | |
| - | ::Liquid::Template.register_tag('paginate', Paginate) |
| end | |
| - | |
| end | |
| - | |
| end | |
locomotive/steam/liquid/tags/path_helper.rb b/lib/locomotive/steam/liquid/tags/path_helper.rb
+58
-56
| @@ | @@ -1,84 +1,86 @@ |
| module Locomotive | |
| - | module Liquid |
| - | module Tags |
| - | module PathHelper |
| + | module Steam |
| + | module Liquid |
| + | module Tags |
| + | module PathHelper |
| - | Syntax = /(#{::Liquid::Expression}+)(#{::Liquid::TagAttributes}?)/ |
| + | 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 |
| + | 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 |
| + | self.wrong_syntax! |
| end | |
| - | else |
| - | self.wrong_syntax! |
| - | end |
| - | super |
| - | end |
| + | super |
| + | end |
| - | def render_path(context, &block) |
| - | site = context.registers[:site] |
| + | def render_path(context, &block) |
| + | site = context.registers[:site] |
| - | if page = self.retrieve_page_from_handle(site, context) |
| - | path = self.public_page_fullpath(site, page) |
| + | if page = self.retrieve_page_from_handle(site, context) |
| + | path = self.public_page_fullpath(site, page) |
| - | if block_given? |
| - | block.call page, path |
| + | if block_given? |
| + | block.call page, path |
| + | else |
| + | path |
| + | end |
| else | |
| - | path |
| + | '' # no page found |
| end | |
| - | else |
| - | '' # no page found |
| end | |
| - | end |
| - | protected |
| + | protected |
| - | def retrieve_page_from_handle(site, context) |
| - | handle = context[@handle] || @handle |
| + | def retrieve_page_from_handle(site, context) |
| + | handle = context[@handle] || @handle |
| - | case handle |
| - | when Locomotive::Page then handle |
| - | when Locomotive::Liquid::Drops::Page then handle.instance_variable_get(:@_source) |
| - | when String then fetch_page(site, handle) |
| - | when Locomotive::ContentEntry then fetch_page(site, handle, true) |
| - | when Locomotive::Liquid::Drops::ContentEntry then fetch_page(site, handle.instance_variable_get(:@_source), true) |
| - | else |
| - | nil |
| + | case handle |
| + | when Locomotive::Page then handle |
| + | when Locomotive::Liquid::Drops::Page then handle.instance_variable_get(:@_source) |
| + | when String then fetch_page(site, handle) |
| + | when Locomotive::ContentEntry then fetch_page(site, handle, true) |
| + | when Locomotive::Liquid::Drops::ContentEntry then fetch_page(site, handle.instance_variable_get(:@_source), true) |
| + | else |
| + | nil |
| + | end |
| end | |
| - | end |
| - | def fetch_page(site, handle, templatized = false) |
| - | ::Mongoid::Fields::I18n.with_locale(self.locale) do |
| - | if templatized |
| - | criteria = site.pages.where(target_klass_name: handle.class.to_s, templatized: true) |
| - | criteria = criteria.where(handle: @options['with']) if @options['with'] |
| - | criteria.first.tap do |page| |
| - | page.content_entry = handle if page |
| + | def fetch_page(site, handle, templatized = false) |
| + | ::Mongoid::Fields::I18n.with_locale(self.locale) do |
| + | if templatized |
| + | criteria = site.pages.where(target_klass_name: handle.class.to_s, templatized: true) |
| + | criteria = criteria.where(handle: @options['with']) if @options['with'] |
| + | criteria.first.tap do |page| |
| + | page.content_entry = handle if page |
| + | end |
| + | else |
| + | site.pages.where(handle: handle).first |
| end | |
| - | else |
| - | site.pages.where(handle: handle).first |
| end | |
| end | |
| - | end |
| - | def public_page_fullpath(site, page) |
| - | fullpath = site.localized_page_fullpath(page, self.locale) |
| + | def public_page_fullpath(site, page) |
| + | fullpath = site.localized_page_fullpath(page, self.locale) |
| + | |
| + | if page.templatized? |
| + | fullpath.gsub!('content_type_template', page.content_entry._slug) |
| + | end |
| - | if page.templatized? |
| - | fullpath.gsub!('content_type_template', page.content_entry._slug) |
| + | File.join('/', fullpath) |
| end | |
| - | File.join('/', fullpath) |
| - | end |
| + | def locale |
| + | @options['locale'] || I18n.locale |
| + | end |
| - | def locale |
| - | @options['locale'] || I18n.locale |
| end | |
| - | |
| end | |
| end | |
| end | |
locomotive/steam/liquid/tags/path_to.rb b/lib/locomotive/steam/liquid/tags/path_to.rb
+13
-11
| @@ | @@ -1,21 +1,23 @@ |
| module Locomotive | |
| - | module Liquid |
| - | module Tags |
| - | class PathTo < ::Liquid::Tag |
| + | module Steam |
| + | module Liquid |
| + | module Tags |
| + | class PathTo < ::Liquid::Tag |
| - | include PathHelper |
| + | include PathHelper |
| - | def render(context) |
| - | render_path(context) |
| - | end |
| + | def render(context) |
| + | render_path(context) |
| + | end |
| + | |
| + | def wrong_syntax! |
| + | raise SyntaxError.new("Syntax Error in 'path_to' - Valid syntax: path_to <page|page_handle|content_entry>(, locale: [fr|de|...], with: <page_handle>") |
| + | end |
| - | def wrong_syntax! |
| - | raise SyntaxError.new("Syntax Error in 'path_to' - Valid syntax: path_to <page|page_handle|content_entry>(, locale: [fr|de|...], with: <page_handle>") |
| end | |
| + | ::Liquid::Template.register_tag('path_to', PathTo) |
| end | |
| - | |
| - | ::Liquid::Template.register_tag('path_to', PathTo) |
| end | |
| end | |
| end | |
locomotive/steam/liquid/tags/seo.rb b/lib/locomotive/steam/liquid/tags/seo.rb
+58
-56
| @@ | @@ -1,72 +1,74 @@ |
| module Locomotive | |
| - | 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)}"> |
| - | } |
| + | module Steam |
| + | 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 charactets 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_entry'] || context['page'] |
| + | end |
| end | |
| - | # Removes whitespace and quote charactets 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_entry'] || context['page'] |
| - | end |
| - | end |
| + | class Title < Base |
| - | class Title < Base |
| + | def render(context) |
| + | self.render_title(context) |
| + | end |
| - | def render(context) |
| - | self.render_title(context) |
| end | |
| - | end |
| + | class Metadata < Base |
| - | class Metadata < Base |
| + | def render(context) |
| + | self.render_metadata(context) |
| + | end |
| - | def render(context) |
| - | self.render_metadata(context) |
| 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 | |
| - | |
| - | ::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 |
| \ No newline at end of file | |
| + | end |
locomotive/steam/liquid/tags/session_assign.rb b/lib/locomotive/steam/liquid/tags/session_assign.rb
+29
-27
| @@ | @@ -1,39 +1,41 @@ |
| module Locomotive | |
| - | module Liquid |
| - | module Tags |
| + | module Steam |
| + | 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}+)/ |
| + | # 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, context) |
| - | if markup =~ Syntax |
| - | @to = $1 |
| - | @from = $2 |
| - | else |
| - | raise ::Liquid::SyntaxError.new("Syntax Error in 'session_assign' - Valid syntax: assign [var] = [source]") |
| + | def initialize(tag_name, markup, tokens, context) |
| + | if markup =~ Syntax |
| + | @to = $1 |
| + | @from = $2 |
| + | else |
| + | raise ::Liquid::SyntaxError.new("Syntax Error in 'session_assign' - Valid syntax: assign [var] = [source]") |
| + | end |
| + | |
| + | super |
| end | |
| - | super |
| - | end |
| + | def render(context) |
| + | controller = context.registers[:controller] |
| - | def render(context) |
| - | controller = context.registers[:controller] |
| + | controller.session[@to.to_sym] = context[@from] |
| + | '' |
| + | end |
| - | controller.session[@to.to_sym] = context[@from] |
| - | '' |
| end | |
| + | ::Liquid::Template.register_tag('session_assign', SessionAssign) |
| end | |
| - | |
| - | ::Liquid::Template.register_tag('session_assign', SessionAssign) |
| end | |
| end | |
| - | end |
| \ No newline at end of file | |
| + | end |
locomotive/steam/liquid/tags/snippet.rb b/lib/locomotive/steam/liquid/tags/snippet.rb
+51
-49
| @@ | @@ -1,75 +1,77 @@ |
| module Locomotive | |
| - | module Liquid |
| - | module Tags |
| + | module Steam |
| + | module Liquid |
| + | module Tags |
| - | class Snippet < ::Liquid::Include |
| + | class Snippet < ::Liquid::Include |
| - | attr_accessor :slug |
| - | attr_accessor :partial |
| + | attr_accessor :slug |
| + | attr_accessor :partial |
| - | def initialize(tag_name, markup, tokens, context) |
| - | super |
| + | def initialize(tag_name, markup, tokens, context) |
| + | super |
| - | @slug = @template_name.gsub(/['"]/o, '') |
| + | @slug = @template_name.gsub(/['"]/o, '') |
| - | if @context[:snippets].present? |
| - | (@context[:snippets] << @slug).uniq! |
| - | else |
| - | @context[:snippets] = [@slug] |
| - | end |
| + | if @context[:snippets].present? |
| + | (@context[:snippets] << @slug).uniq! |
| + | else |
| + | @context[:snippets] = [@slug] |
| + | end |
| - | if @context[:site].present? |
| - | snippet = @context[:site].snippets.where(slug: @slug).first |
| - | self.refresh(snippet) if snippet |
| + | if @context[:site].present? |
| + | snippet = @context[:site].snippets.where(slug: @slug).first |
| + | self.refresh(snippet) if snippet |
| + | end |
| end | |
| - | end |
| - | def render(context) |
| - | return '' if @partial.nil? |
| + | def render(context) |
| + | return '' if @partial.nil? |
| - | variable = context[@variable_name || @template_name[1..-2]] |
| + | variable = context[@variable_name || @template_name[1..-2]] |
| - | context.stack do |
| - | @attributes.each do |key, value| |
| - | context[key] = context[value] |
| - | end |
| + | context.stack do |
| + | @attributes.each do |key, value| |
| + | context[key] = context[value] |
| + | end |
| - | output = (if variable.is_a?(Array) |
| - | variable.collect do |variable| |
| + | 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 |
| - | else |
| - | context[@template_name[1..-2]] = variable |
| - | @partial.render(context) |
| - | end) |
| + | end) |
| - | output |
| + | output |
| + | end |
| end | |
| - | end |
| - | def refresh(snippet, context = {}) |
| - | if snippet.destroyed? |
| - | @snippet_id = nil |
| - | @partial = nil |
| - | else |
| - | @snippet_id = snippet.id |
| - | @partial = ::Liquid::Template.parse(snippet.template, context.merge(@context)) |
| - | @partial.root.context.clear |
| + | def refresh(snippet, context = {}) |
| + | if snippet.destroyed? |
| + | @snippet_id = nil |
| + | @partial = nil |
| + | else |
| + | @snippet_id = snippet.id |
| + | @partial = ::Liquid::Template.parse(snippet.template, context.merge(@context)) |
| + | @partial.root.context.clear |
| + | end |
| end | |
| - | end |
| - | def nodelist |
| - | if @partial |
| - | @partial.root.nodelist |
| - | else |
| - | [] |
| + | def nodelist |
| + | if @partial |
| + | @partial.root.nodelist |
| + | else |
| + | [] |
| + | end |
| end | |
| + | |
| end | |
| + | ::Liquid::Template.register_tag('include', Snippet) |
| end | |
| - | |
| - | ::Liquid::Template.register_tag('include', Snippet) |
| end | |
| end | |
| end | |
locomotive/steam/liquid/tags/with_scope.rb b/lib/locomotive/steam/liquid/tags/with_scope.rb
+45
-43
| @@ | @@ -1,65 +1,67 @@ |
| module Locomotive | |
| - | module Liquid |
| - | module Tags |
| + | module Steam |
| + | module Liquid |
| + | module Tags |
| - | # Filter a collection |
| - | # |
| - | # Usage: |
| - | # |
| - | # {% with_scope main_developer: 'John Doe', providers.in: ['acme'], started_at.le: today, active: true %} |
| - | # {% for project in contents.projects %} |
| - | # {{ project.name }} |
| - | # {% endfor %} |
| - | # {% endwith_scope %} |
| - | # |
| + | # Filter a collection |
| + | # |
| + | # Usage: |
| + | # |
| + | # {% with_scope main_developer: 'John Doe', providers.in: ['acme'], started_at.le: today, active: true %} |
| + | # {% for project in contents.projects %} |
| + | # {{ project.name }} |
| + | # {% endfor %} |
| + | # {% endwith_scope %} |
| + | # |
| - | class WithScope < Solid::Block |
| + | class WithScope < Solid::Block |
| - | OPERATORS = %w(all exists gt gte in lt lte ne nin size near within) |
| + | OPERATORS = %w(all exists gt gte in lt lte ne nin size near within) |
| - | SYMBOL_OPERATORS_REGEXP = /(\w+\.(#{OPERATORS.join('|')})){1}\s*\:/ |
| + | SYMBOL_OPERATORS_REGEXP = /(\w+\.(#{OPERATORS.join('|')})){1}\s*\:/ |
| - | # register the tag |
| - | tag_name :with_scope |
| + | # 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" =>') |
| + | 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 |
| + | super(tag_name, arguments_string, tokens, context) |
| + | end |
| - | def display(options = {}, &block) |
| - | current_context.stack do |
| - | current_context['with_scope'] = self.decode(options) |
| - | yield |
| + | def display(options = {}, &block) |
| + | current_context.stack do |
| + | current_context['with_scope'] = self.decode(options) |
| + | yield |
| + | end |
| end | |
| - | end |
| - | protected |
| + | protected |
| - | def decode(options) |
| - | HashWithIndifferentAccess.new.tap do |hash| |
| - | options.each do |key, value| |
| - | _key, _operator = key.to_s.split('.') |
| + | def decode(options) |
| + | HashWithIndifferentAccess.new.tap do |hash| |
| + | options.each do |key, value| |
| + | _key, _operator = key.to_s.split('.') |
| - | # _slug instead of _permalink |
| - | _key = '_slug' if _key == '_permalink' |
| + | # _slug instead of _permalink |
| + | _key = '_slug' if _key == '_permalink' |
| - | # key to h4s symbol |
| - | _key = _key.to_s.to_sym.send(_operator.to_sym) if _operator |
| + | # key to h4s symbol |
| + | _key = _key.to_s.to_sym.send(_operator.to_sym) if _operator |
| - | hash[_key] = (case value |
| - | # regexp inside a string |
| - | when /^\/[^\/]*\/$/ then Regexp.new(value[1..-2]) |
| - | else |
| - | value |
| - | end) |
| + | 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 | |
| end | |
locomotive/steam/services.rb b/lib/locomotive/steam/services.rb
+8
-0
| @@ | @@ -38,6 +38,14 @@ module Locomotive |
| Services::Translator.new(repositories.translation, I18n.locale) | |
| end | |
| + | register :external_api do |
| + | Services::ExternalAPI.new |
| + | end |
| + | |
| + | register :cache do |
| + | Services::NoCache.new |
| + | end |
| + | |
| register :markdown do | |
| Services::Markdown.new | |
| end | |
locomotive/steam/services/external_api.rb b/lib/locomotive/steam/services/external_api.rb
+28
-14
| @@ | @@ -9,36 +9,50 @@ module Locomotive |
| include ::HTTParty | |
| def consume(url, options = {}) | |
| - | url = ::HTTParty.normalize_base_uri(url) |
| - | |
| - | uri = URI.parse(url) |
| - | options[:base_uri] = "#{uri.scheme}://#{uri.host}" |
| - | options[:base_uri] += ":#{uri.port}" if uri.port != 80 |
| - | path = uri.request_uri |
| + | options[:base_uri], path = extract_base_uri_and_path(url) |
| options.delete(:format) if options[:format] == 'default' | |
| + | # auth ? |
| username, password = options.delete(:username), options.delete(:password) | |
| options[:basic_auth] = { username: username, password: password } if username | |
| - | path ||= '/' |
| + | perform_request_to(path, options) |
| + | end |
| + | |
| + | private |
| - | # Locomotive::Common::Logger.debug "[WebService] consuming #{path}, #{options.inspect}" |
| + | def extract_base_uri_and_path(url) |
| + | url = HTTParty.normalize_base_uri(url) |
| - | response = self.class.get(path, options) |
| + | uri = URI.parse(url) |
| + | path = uri.request_uri || '/' |
| + | base_uri = "#{uri.scheme}://#{uri.host}" |
| + | base_uri += ":#{uri.port}" if uri.port != 80 |
| + | |
| + | [base_uri, path] |
| + | end |
| + | |
| + | def perform_request_to(path, options) |
| + | # [DEBUG] puts "[WebService] consuming #{path}, #{options.inspect}" |
| + | |
| + | # sanitize the options |
| + | options[:format] = options[:format].gsub(/[\'\"]/, '').to_sym if options.has_key?(:format) |
| + | options[:headers] = { 'User-Agent' => 'LocomotiveCMS' } if options[:with_user_agent] |
| + | |
| + | response = self.class.get(path, options) |
| + | parsed_response = response.parsed_response |
| if response.code == 200 | |
| - | _response = response.parsed_response |
| - | if _response.respond_to?(:underscore_keys) |
| - | _response.underscore_keys |
| + | if parsed_response.respond_to?(:underscore_keys) |
| + | parsed_response.underscore_keys |
| else | |
| - | _response.collect(&:underscore_keys) |
| + | parsed_response.collect(&:underscore_keys) |
| end | |
| else | |
| Locomotive::Common::Logger.error "[WebService] consumed #{path}, #{options.inspect}, response = #{response.inspect}" | |
| nil | |
| end | |
| - | |
| end | |
| end | |
locomotive/steam/services/no_cache.rb b/lib/locomotive/steam/services/no_cache.rb
+15
-0
| @@ | @@ -0,0 +1,15 @@ |
| + | module Locomotive |
| + | module Steam |
| + | module Services |
| + | |
| + | class NoCache |
| + | |
| + | def fetch(key, options = {}, &block) |
| + | block.call |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
spec/integration/services/external_api_spec.rb
+18
-0
| @@ | @@ -0,0 +1,18 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Services::ExternalAPI do |
| + | |
| + | let(:service) { Locomotive::Steam::Services::ExternalAPI.new } |
| + | |
| + | describe '#consume' do |
| + | |
| + | let(:url) { 'https://api.github.com/users/did/repos' } |
| + | let(:options) { { format: "'json'", with_user_agent: true } } |
| + | |
| + | subject { service.consume(url, options) } |
| + | |
| + | it { expect(subject.size).to_not eq 0 } |
| + | |
| + | end |
| + | |
| + | end |
spec/support.rb
+2
-1
| @@ | @@ -1,4 +1,5 @@ |
| require_relative 'support/helpers' | |
| + | require_relative 'support/liquid' |
| require_relative 'support/matchers/hash' | |
| require_relative 'support/examples/matching_locale' | |
| - | require_relative 'support/examples/locale_file' |
| \ No newline at end of file | |
| + | require_relative 'support/examples/locale_file' |
spec/support/liquid.rb
+3
-0
| @@ | @@ -0,0 +1,3 @@ |
| + | def render_template(template, context) |
| + | ::Liquid::Template.parse(template).render(context) |
| + | end |
spec/unit/liquid/tags/consume_spec.rb
+89
-0
| @@ | @@ -0,0 +1,89 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Liquid::Tags::Consume do |
| + | |
| + | let(:template) { '{% consume blog from "http://blog.locomotiveapp.org" %}{% endconsume %}' } |
| + | let(:assigns) { {} } |
| + | let(:services) { Locomotive::Steam::Services.build_instance } |
| + | let(:context) { ::Liquid::Context.new(assigns, {}, { services: services }) } |
| + | |
| + | subject { render_template(template, context) } |
| + | |
| + | describe 'validating syntax' do |
| + | |
| + | let(:response) { nil } |
| + | before { allow(services.external_api).to receive(:consume).and_return(response) } |
| + | |
| + | describe 'validates a basic syntax' do |
| + | it { expect { subject }.not_to raise_exception } |
| + | end |
| + | |
| + | describe 'validates more complex syntax with attributes' do |
| + | let(:template) { '{% consume blog from "http://www.locomotiveapp.org", username: "john", password: password_from_context %}{% endconsume %}' } |
| + | it { expect { subject }.not_to raise_exception } |
| + | end |
| + | |
| + | describe 'should parse the correct url with complex syntax with attributes' do |
| + | let(:template) { '{% consume blog from "http://www.locomotiveapp.org" username: "john", password: "easyone" %}{% endconsume %}' } |
| + | it { expect { subject }.not_to raise_exception } |
| + | end |
| + | |
| + | describe 'raises an error if the syntax is incorrect' do |
| + | let(:template) { '{% consume blog http://www.locomotiveapp.org %}{% endconsume %}' } |
| + | it { expect { subject }.to raise_exception } |
| + | end |
| + | |
| + | end |
| + | |
| + | describe 'rendering' do |
| + | |
| + | let(:response) { { 'title' => 'Locomotive rocks!' } } |
| + | before { allow(services.external_api).to receive(:consume).and_return(response) } |
| + | |
| + | describe 'assign the response into the liquid variable' do |
| + | |
| + | let(:template) { "{% consume blog from \"http://blog.locomotiveapp.org/api/read\" %}{{ blog.title }}{% endconsume %}" } |
| + | it { is_expected.to eq 'Locomotive rocks!' } |
| + | |
| + | end |
| + | |
| + | describe 'assign the response into the liquid variable using a url from a variable' do |
| + | |
| + | let(:assigns) { { 'url' => 'http://blog.locomotiveapp.org/api/read' } } |
| + | let(:template) { "{% consume blog from url %}{{ blog.title }}{% endconsume %}" } |
| + | it { is_expected.to eq 'Locomotive rocks!' } |
| + | |
| + | end |
| + | |
| + | describe 'accept options for the web service' do |
| + | |
| + | let(:assigns) { { 'secret_password' => 'bar' } } |
| + | let(:template) { "{% consume blog from \"http://blog.locomotiveapp.org/api/read\", username: 'foo', password: secret_password %}{{ blog.title }}{% endconsume %}" } |
| + | it { is_expected.to eq 'Locomotive rocks!' } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | describe 'timeout' do |
| + | |
| + | let(:response) { { 'title' => 'first response' } } |
| + | let(:url) { 'http://blog.locomotiveapp.org/api/read' } |
| + | let(:template) { %{{% consume blog from "#{url}" timeout:5.0 %}{{ blog.title }}{% endconsume %}} } |
| + | |
| + | it 'should pass the timeout option to httparty' do |
| + | expect(services.external_api).to receive(:consume).with(url, timeout: 5.0).and_return(response) |
| + | subject |
| + | end |
| + | |
| + | it 'should return the previous successful response if a timeout occurs' do |
| + | allow(services.external_api).to receive(:consume).and_return(response) |
| + | is_expected.to eq 'first response' |
| + | |
| + | allow(services.external_api).to receive(:consume).and_raise(Timeout::Error) |
| + | is_expected.to eq 'first response' |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
spec/unit/services/external_api_spec.rb
+58
-0
| @@ | @@ -0,0 +1,58 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Services::ExternalAPI do |
| + | |
| + | let(:service) { Locomotive::Steam::Services::ExternalAPI.new } |
| + | |
| + | describe '#consume' do |
| + | |
| + | let(:url) { '' } |
| + | let(:options) { {} } |
| + | let(:response) { instance_double('Response', code: 200, parsed_response: OpenStruct.new) } |
| + | |
| + | subject { service.consume(url, options) } |
| + | |
| + | describe 'sets the base uri from a simple url' do |
| + | |
| + | let(:url) { 'http://blog.locomotiveapp.org' } |
| + | it do |
| + | expect(service.class).to receive(:get).with('/', { base_uri: 'http://blog.locomotiveapp.org' }).and_return(response) |
| + | subject |
| + | end |
| + | |
| + | end |
| + | |
| + | describe 'sets the base uri from a much more complex url' do |
| + | |
| + | let(:url) { 'http://free.worldweatheronline.com/feed/weather.ashx?key=secretapikey&format=json' } |
| + | it do |
| + | expect(service.class).to receive(:get).with('/feed/weather.ashx?key=secretapikey&format=json', { base_uri: 'http://free.worldweatheronline.com' }).and_return(response) |
| + | subject |
| + | end |
| + | |
| + | end |
| + | |
| + | |
| + | describe 'sets both the base uri and the path from an url with parameters' do |
| + | |
| + | let(:url) { 'http://blog.locomotiveapp.org/api/read/json?num=3' } |
| + | it do |
| + | expect(service.class).to receive(:get).with('/api/read/json?num=3', { base_uri: 'http://blog.locomotiveapp.org' }).and_return(response) |
| + | subject |
| + | end |
| + | |
| + | end |
| + | |
| + | describe 'sets auth credentials' do |
| + | |
| + | let(:url) { 'http://blog.locomotiveapp.org' } |
| + | let(:options) { { username: 'john', password: 'foo' } } |
| + | it do |
| + | expect(service.class).to receive(:get).with('/', { base_uri: 'http://blog.locomotiveapp.org', basic_auth: { username: 'john', password: 'foo' } }).and_return(response) |
| + | subject |
| + | end |
| + | end |
| + | |
| + | end |
| + | |
| + | end |