implementation of the link_to liquid tag (wip)

did committed Jul 02, 2013
commit 45d8a1fe8223539304210a8234f652884469e0d2
Showing 7 changed files with 176 additions and 5 deletions
locomotive/wagon/liquid.rb b/lib/locomotive/wagon/liquid.rb +1 -0
@@ @@ -1,6 +1,7 @@
require 'liquid'
require 'locomotive/mounter'
require 'locomotive/wagon/liquid/drops/base'
+ require 'locomotive/wagon/liquid/tags/hybrid'
%w{. drops tags filters}.each do |dir|
Dir[File.join(File.dirname(__FILE__), 'liquid', dir, '*.rb')].each { |lib| require lib }
locomotive/wagon/liquid/tags/hybrid.rb b/lib/locomotive/wagon/liquid/tags/hybrid.rb +27 -0
@@ @@ -0,0 +1,27 @@
+ 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/link_to.rb b/lib/locomotive/wagon/liquid/tags/link_to.rb +110 -0
@@ @@ -0,0 +1,110 @@
+ module Locomotive
+ module Wagon
+ module Liquid
+ module Tags
+ class LinkTo < Hybrid
+
+ 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 'link_to' - Valid syntax: link_to page_handle, locale es (locale is optional)")
+ end
+
+ super
+ end
+
+ def render(context)
+ if page = self.retrieve_page_from_handle(context)
+ label = self.label_from_page(page)
+ path = self.public_page_url(context, page)
+
+ if @render_as_block
+ context.scopes.last['target'] = page
+ label = super.html_safe
+ end
+
+ %{<a href="#{path}">#{label}</a>}
+ else
+ '' # no page found
+ 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 String then fetch_page(mounting_point, handle)
+ 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 label_from_page(page)
+ ::Locomotive::Mounter.with_locale(@options['locale']) do
+ if page.templatized?
+ page.content_entry._label
+ else
+ page.title
+ end
+ end
+ end
+
+ def public_page_url(context, page)
+ fullpath = page.fullpath
+ mounting_point = context.registers[:mounting_point]
+
+ ::Locomotive::Mounter.with_locale(@options['locale']) do
+ fullpath = "#{::I18n.locale}/#{fullpath}" if ::I18n.locale.to_s != mounting_point.default_locale.to_s
+ end
+
+ if page.templatized?
+ fullpath.gsub!('content_type_template', page.content_entry._slug)
+ end
+
+ File.join('/', fullpath)
+ end
+
+ end
+
+ ::Liquid::Template.register_tag('link_to', LinkTo)
+ end
+ end
+ end
+ end
\ No newline at end of file
spec/fixtures/default/app/views/pages/about_us.liquid.haml +1 -0
@@ @@ -2,6 +2,7 @@
title: About Us
listed: true
position: 1
+ handle: about-us
editable_elements:
'banner/page_image': "/samples/photo_2.jpg"
'banner/pitch': "<h2>About us</h2><p>Lorem ipsum...</p>"
spec/fixtures/default/app/views/pages/events.liquid.haml +8 -0
@@ @@ -26,4 +26,12 @@ position: 5
{% endeditable_long_text %}
+ %p
+ %strong Discover: {% link_to our-music %}
+ %br
+ %strong {% link_to about-us %}Who are we ?{% endlink_to %}
+ %br
+ {% assign song = contents.songs.first %}
+ %strong {% link_to song %}
+
{% endblock %}
\ No newline at end of file
spec/fixtures/default/app/views/pages/music.liquid.haml +4 -1
@@ @@ -1,5 +1,6 @@
---
listed: true
+ handle: our-music
position: 2
---
{% extends parent %}
@@ @@ -24,5 +25,7 @@ position: 2
{% for song in contents.songs offset: 4 %}
{% include 'song' with song %}
{% endfor %}
- #is_listed{listed: "{{ page.listed? }}"}
+
+ #is_listed{ listed: "{{ page.listed? }}" }
+
{% endblock %}
\ No newline at end of file
spec/integration/server/liquid_spec.rb +25 -4
@@ @@ -11,12 +11,12 @@ describe Locomotive::Wagon::Server do
def app
run_server
end
-
+
it "converts {{ page.templatized? }} => true on templatized page" do
get '/songs/song-1'
last_response.body.should =~ /templatized=.true./
end
-
+
it "converts {{ page.templatized? }} => false on regular page" do
get '/index'
last_response.body.should =~ /templatized=.false./
@@ @@ -26,14 +26,35 @@ describe Locomotive::Wagon::Server do
get '/music'
last_response.body.should =~ /listed=.true./
end
-
+
it "provides an access to page's content_type collection" do
get '/songs/song-1'
last_response.body.should =~ /content_type_size=.8./
end
-
+
it "provides count alias on collections" do
get '/songs/song-1'
last_response.body.should =~ /content_type_count=.8./
end
+
+ describe '.link_to' do
+
+ it "writes a link to a page" do
+ get '/events'
+ last_response.body.should =~ /Discover: <a href="\/music">Music<\/a>/
+ end
+
+ it "writes a link to a page with a custom label" do
+ get '/events'
+ last_response.body.should =~ /<a href="\/about-us">Who are we \?<\/a>/
+ end
+
+ it "writes a link to a templatized page" do
+ get '/events'
+ last_response.body.should =~ /<a href="\/songs\/song-1">Song #1<\/a>/
+ end
+
+
+
+ end
end
\ No newline at end of file