adding 2 new liquid tags: consume (to retrieve posts from a blog for instance) + nav (display children of a page) + fix a few bugs
This commit is contained in:
parent
821210795d
commit
c38a8ff9dd
|
@ -9,7 +9,10 @@ spec/tmp
|
|||
public/sites
|
||||
public/uploads
|
||||
public/stylesheets/all.css
|
||||
public/stylesheets/plugins
|
||||
public/javascripts/all.js
|
||||
public/javascripts/plugins
|
||||
public/images/plugins
|
||||
pkg
|
||||
*.gemspec
|
||||
rails_3_gems
|
||||
|
|
1
Gemfile
1
Gemfile
|
@ -21,6 +21,7 @@ gem 'formtastic-rails3', :require => 'formtastic'
|
|||
gem 'carrierwave-rails3', :require => 'carrierwave'
|
||||
gem 'actionmailer-with-request', :require => 'actionmailer_with_request'
|
||||
gem 'heroku'
|
||||
gem 'httparty', '0.6.0'
|
||||
|
||||
# Development environment
|
||||
group :development do
|
||||
|
|
|
@ -9,6 +9,7 @@ module Admin
|
|||
assets = current_site.theme_assets.all
|
||||
@non_image_assets = assets.find_all { |a| a.stylesheet? || a.javascript? }
|
||||
@image_assets = assets.find_all { |a| a.image? }
|
||||
@flash_assets = assets.find_all { |a| a.movie? }
|
||||
|
||||
if request.xhr?
|
||||
render :action => 'images', :layout => false
|
||||
|
|
|
@ -21,7 +21,7 @@ class ContentType
|
|||
|
||||
## validations ##
|
||||
validates_presence_of :site, :name, :slug
|
||||
validates_uniqueness_of :slug, :scope => :site
|
||||
validates_uniqueness_of :slug, :scope => :site_id
|
||||
validates_size_of :content_custom_fields, :minimum => 1, :message => :array_too_short
|
||||
|
||||
## behaviours ##
|
||||
|
|
|
@ -33,7 +33,7 @@ class ThemeAsset
|
|||
|
||||
## methods ##
|
||||
|
||||
%w{image stylesheet javascript}.each do |type|
|
||||
%w{movie image stylesheet javascript}.each do |type|
|
||||
define_method("#{type}?") do
|
||||
self.content_type == type
|
||||
end
|
||||
|
@ -53,7 +53,7 @@ class ThemeAsset
|
|||
end
|
||||
|
||||
def performing_plain_text?
|
||||
return true if !self.new_record? && !self.image? && self.errors.empty?
|
||||
return true if !self.new_record? && !self.image? && !self.movie? && self.errors.empty?
|
||||
|
||||
!(self.performing_plain_text.blank? || self.performing_plain_text == 'false' || self.performing_plain_text == false)
|
||||
end
|
||||
|
|
|
@ -45,6 +45,8 @@ class AssetUploader < CarrierWave::Uploader::Base
|
|||
end
|
||||
end
|
||||
|
||||
puts "content_type = #{value}"
|
||||
|
||||
model.content_type = value
|
||||
end
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ class ThemeAssetUploader < AssetUploader
|
|||
end
|
||||
|
||||
def extension_white_list
|
||||
%w(jpg jpeg gif png css js)
|
||||
%w(jpg jpeg gif png css js swf flv)
|
||||
end
|
||||
|
||||
end
|
|
@ -25,3 +25,12 @@
|
|||
%ul.assets
|
||||
= render :partial => 'asset', :collection => @image_assets
|
||||
%li.clear
|
||||
|
||||
|
||||
- if not @flash_assets.empty?
|
||||
%br
|
||||
|
||||
%h3= t('.flash')
|
||||
%ul.assets
|
||||
= render :partial => 'asset', :collection => @flash_assets
|
||||
%li.clear
|
9
doc/TODO
9
doc/TODO
|
@ -3,23 +3,24 @@ BOARD:
|
|||
- refactoring admin crud (pages + layouts + snippets)
|
||||
- refactor slugify method (use parameterize + create a module)
|
||||
|
||||
- localize application in French (tork)
|
||||
- localize application in French
|
||||
x default
|
||||
x devise
|
||||
x carrierwave
|
||||
x localize devise emails
|
||||
- admin
|
||||
|
||||
- rss parser
|
||||
|
||||
BACKLOG:
|
||||
|
||||
- notify accounts when new instance of models (opt): none, one or many accounts. Used for contact form.
|
||||
- theme assets: disable version if not image
|
||||
|
||||
- new custom field types:
|
||||
- belongs_to => association
|
||||
|
||||
- cucumber features for admin pages
|
||||
|
||||
- sitemap
|
||||
- validation for custom fields
|
||||
|
||||
BUGS:
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ require 'locomotive/mongoid'
|
|||
require 'locomotive/carrierwave'
|
||||
require 'locomotive/heroku'
|
||||
require 'locomotive/custom_fields'
|
||||
require 'locomotive/httparty'
|
||||
|
||||
require 'mongo_session_store/mongoid'
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ module CarrierWave
|
|||
def to_liquid
|
||||
{
|
||||
:url => self.url,
|
||||
:filename => File.basename(self.url),
|
||||
:filename => (File.basename(self.url) rescue ''),
|
||||
:size => self.size
|
||||
}.stringify_keys
|
||||
end
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
require 'locomotive/httparty/webservice'
|
||||
require 'locomotive/httparty/patches'
|
|
@ -0,0 +1,18 @@
|
|||
require 'crack/json'
|
||||
|
||||
module Crack
|
||||
class JSON
|
||||
|
||||
def self.parse_with_tumblr(json)
|
||||
cleaned_json = json.gsub(/^var\s+.+\s+=\s+/, '').gsub(/;$/, '')
|
||||
parse_without_tumblr(cleaned_json)
|
||||
rescue ArgumentError => e
|
||||
raise ParseError, "Invalid JSON string #{e.inspect}"
|
||||
end
|
||||
|
||||
class << self
|
||||
alias_method_chain :parse, :tumblr
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
module Locomotive
|
||||
module Httparty
|
||||
class Webservice
|
||||
|
||||
include HTTParty
|
||||
|
||||
def self.consume(url, options = {})
|
||||
url = HTTParty.normalize_base_uri(url)
|
||||
|
||||
options[:base_uri], path = url.scan(/^(http[s]?:\/\/.+\.[a-z]{2,})(\/.+)*/).first
|
||||
options.delete(:format) if options[:format] == 'default'
|
||||
|
||||
username, password = options.delete(:username), options.delete(:password)
|
||||
options[:basic_auth] = { :username => username, :password => password } if username
|
||||
|
||||
path ||= '/'
|
||||
|
||||
puts "[WebService] consuming #{path}, #{options.inspect}"
|
||||
|
||||
self.get(path, options)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,46 @@
|
|||
module Locomotive
|
||||
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' %}
|
||||
# {% for post in blog.posts %}
|
||||
# {{ post.title }}
|
||||
# {% endfor %}
|
||||
# {% endconsume %}
|
||||
#
|
||||
class Consume < ::Liquid::Block
|
||||
|
||||
Syntax = /(#{::Liquid::VariableSignature}+)\s*from\s*(#{::Liquid::QuotedString}+)/
|
||||
|
||||
def initialize(tag_name, markup, tokens)
|
||||
if markup =~ Syntax
|
||||
@target = $1
|
||||
@url = $2.gsub(/['"]/, '')
|
||||
@options = {}
|
||||
markup.scan(::Liquid::TagAttributes) do |key, value|
|
||||
@options[key] = value if key != 'http'
|
||||
end
|
||||
else
|
||||
raise ::Liquid::SyntaxError.new("Syntax Error in 'consume' - Valid syntax: consume <var> from \"<url>\" [username: value, password: value]")
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def render(context)
|
||||
context.stack do
|
||||
context.scopes.last[@target.to_s] = Locomotive::Httparty::Webservice.consume(@url, @options.symbolize_keys)
|
||||
|
||||
render_all(@nodelist, context)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
::Liquid::Template.register_tag('consume', Consume)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,60 @@
|
|||
module Locomotive
|
||||
module Liquid
|
||||
module Tags
|
||||
# Display the children pages of the site or the current 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>
|
||||
#
|
||||
class Nav < ::Liquid::Tag
|
||||
|
||||
Syntax = /(#{::Liquid::Expression}+)?/
|
||||
|
||||
def initialize(tag_name, markup, tokens)
|
||||
if markup =~ Syntax
|
||||
@site_or_page = $1 || 'page'
|
||||
else
|
||||
raise ::Liquid::SyntaxError.new("Syntax Error in 'nav' - Valid syntax: nav <page|site>")
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def render(context)
|
||||
@current_page = context.registers[:page]
|
||||
|
||||
source = context.registers[@site_or_page.to_sym]
|
||||
|
||||
# puts "[Nav] source = #{source.inspect}"
|
||||
|
||||
if source.respond_to?(:name) # site ?
|
||||
source = source.pages.first # start from home page
|
||||
else
|
||||
source = source.parent
|
||||
end
|
||||
|
||||
output = %{<ul id="nav">}
|
||||
output += source.children.map { |p| render_child_link(p) }.join("\n")
|
||||
output += %{</ul>}
|
||||
output
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_child_link(page)
|
||||
selected = @current_page._id == page._id ? ' on' : ''
|
||||
|
||||
%{
|
||||
<li id="#{page.slug.dasherize}" class="link#{selected}">
|
||||
<a href="/#{page.fullpath}">#{page.title}</a>
|
||||
</li>
|
||||
}.strip
|
||||
end
|
||||
|
||||
::Liquid::Template.register_tag('nav', Nav)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -24,7 +24,7 @@ module Locomotive
|
|||
@collection_name = $1
|
||||
@per_page = $2.to_i
|
||||
else
|
||||
raise ::Liquid::SyntaxError.new("Syntax Error in 'paginate' - Valid syntax: paginate [collection] by [number]")
|
||||
raise ::Liquid::SyntaxError.new("Syntax Error in 'paginate' - Valid syntax: paginate <collection> by <number>")
|
||||
end
|
||||
|
||||
super
|
||||
|
@ -34,7 +34,7 @@ module Locomotive
|
|||
context.stack do
|
||||
collection = context[@collection_name]
|
||||
|
||||
raise 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?
|
||||
|
||||
pagination = collection.paginate({
|
||||
:page => context['current_page'],
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
module Locomotive
|
||||
|
||||
module Liquid
|
||||
|
||||
module Tags
|
||||
|
||||
class Snippet < ::Liquid::Include
|
||||
|
@ -34,9 +32,6 @@ module Locomotive
|
|||
end
|
||||
|
||||
::Liquid::Template.register_tag('include', Snippet)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'Httparty patches' do
|
||||
|
||||
describe 'Crack patch' do
|
||||
|
||||
context '#parsing json' do
|
||||
|
||||
it 'fixes an issue about json input beginning by a variable declaration' do
|
||||
lambda {
|
||||
Crack::JSON.parse('var json = { "foo": 42 };')
|
||||
}.should_not raise_error
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Locomotive::Httparty::Webservice do
|
||||
|
||||
context '#consuming' do
|
||||
|
||||
it 'sets the base uri from a simple url' do
|
||||
Locomotive::Httparty::Webservice.expects(:get).with('/', { :base_uri => 'http://blog.locomotiveapp.org' })
|
||||
Locomotive::Httparty::Webservice.consume('http://blog.locomotiveapp.org')
|
||||
end
|
||||
|
||||
it 'sets both the base uri and the path from an url with parameters' do
|
||||
Locomotive::Httparty::Webservice.expects(:get).with('/api/read/json?num=3', { :base_uri => 'http://blog.locomotiveapp.org' })
|
||||
Locomotive::Httparty::Webservice.consume('http://blog.locomotiveapp.org/api/read/json?num=3')
|
||||
end
|
||||
|
||||
it 'sets auth credentials' do
|
||||
Locomotive::Httparty::Webservice.expects(:get).with('/', { :base_uri => 'http://blog.locomotiveapp.org', :basic_auth => { :username => 'john', :password => 'foo' } })
|
||||
Locomotive::Httparty::Webservice.consume('http://blog.locomotiveapp.org', { :username => 'john', :password => 'foo' })
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,40 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Locomotive::Liquid::Tags::Consume do
|
||||
|
||||
context '#validating syntax' do
|
||||
|
||||
it 'validates a basic syntax' do
|
||||
markup = 'blog from "http://blog.locomotiveapp.org"'
|
||||
lambda do
|
||||
Locomotive::Liquid::Tags::Consume.new('consume', markup, ["{% endconsume %}"])
|
||||
end.should_not raise_error
|
||||
end
|
||||
|
||||
it 'validates more complex syntax with attributes' do
|
||||
markup = 'blog from "http://www.locomotiveapp.org" username: "john", password: "easyone"'
|
||||
lambda do
|
||||
Locomotive::Liquid::Tags::Consume.new('consume', markup, ["{% endconsume %}"])
|
||||
end.should_not raise_error
|
||||
end
|
||||
|
||||
it 'raises an error if the syntax is incorrect' do
|
||||
markup = 'blog from http://www.locomotiveapp.org'
|
||||
lambda do
|
||||
Locomotive::Liquid::Tags::Consume.new('consume', markup, ["{% endconsume %}"])
|
||||
end.should raise_error
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context '#rendering' do
|
||||
|
||||
it 'puts the response into the liquid variable' do
|
||||
Locomotive::Httparty::Webservice.stubs(:get).returns({ 'title' => 'Locomotive rocks !' })
|
||||
template = "{% consume blog from \"http://blog.locomotiveapp.org/api/read\" %}{{ blog.title }}{% endconsume %}"
|
||||
Liquid::Template.parse(template).render.should == 'Locomotive rocks !'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,41 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Locomotive::Liquid::Tags::Nav do
|
||||
|
||||
before(:each) do
|
||||
@home = Factory.build(:page)
|
||||
@home.stubs(:children).returns([
|
||||
Page.new(:title => 'Child #1', :fullpath => 'child_1', :slug => 'child_1'),
|
||||
Page.new(:title => 'Child #2', :fullpath => 'child_2', :slug => 'child_2')
|
||||
])
|
||||
@home.children.last.stubs(:children).returns([
|
||||
Page.new(:title => 'Child #2.1', :fullpath => 'child_2/sub_child_1', :slug => 'sub_child_1'),
|
||||
Page.new(:title => 'Child #2.2', :fullpath => 'child_2/sub_child_2', :slug => 'sub_child_2')
|
||||
])
|
||||
@site = Factory.build(:site)
|
||||
@site.stubs(:pages).returns([@home])
|
||||
end
|
||||
|
||||
context '#rendering' do
|
||||
|
||||
it 'renders from site' do
|
||||
render_nav.should == '<ul id="nav"><li id="child-1" class="link"><a href="/child_1">Child #1</a></li><li id="child-2" class="link"><a href="/child_2">Child #2</a></li></ul>'
|
||||
end
|
||||
|
||||
it 'renders from page' do
|
||||
(page = @home.children.last.children.first).stubs(:parent).returns(@home.children.last)
|
||||
output = render_nav 'page', { :page => page }
|
||||
output.should == '<ul id="nav"><li id="sub-child-1" class="link on"><a href="/child_2/sub_child_1">Child #2.1</a></li><li id="sub-child-2" class="link"><a href="/child_2/sub_child_2">Child #2.2</a></li></ul>'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def render_nav(source = 'site', registers = {})
|
||||
registers = { :site => @site, :page => @home }.merge(registers)
|
||||
liquid_context = ::Liquid::Context.new({}, registers)
|
||||
|
||||
output = Liquid::Template.parse("{% nav #{source} %}").render(liquid_context)
|
||||
output.gsub(/\n\s{0,}/, '')
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue