locomotivecms_builder 1.0.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +31 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +68 -0
- data/Rakefile +47 -0
- data/TODO +57 -0
- data/bin/builder +9 -0
- data/generators/blank/Gemfile.tt +20 -0
- data/generators/blank/app/content_types/.empty_directory +1 -0
- data/generators/blank/app/views/pages/404.liquid +11 -0
- data/generators/blank/app/views/pages/index.liquid +19 -0
- data/generators/blank/app/views/snippets/.empty_directory +1 -0
- data/generators/blank/config/deploy.yml +12 -0
- data/generators/blank/config/site.yml.tt +16 -0
- data/generators/blank/config/translations.yml +8 -0
- data/generators/blank/config.ru +3 -0
- data/generators/blank/data/.empty_directory +1 -0
- data/generators/blank/public/fonts/.empty_directory +1 -0
- data/generators/blank/public/images/.empty_directory +1 -0
- data/generators/blank/public/javascripts/.empty_directory +1 -0
- data/generators/blank/public/samples/.empty_directory +1 -0
- data/generators/blank/public/stylesheets/.empty_directory +1 -0
- data/generators/bootstrap/Gemfile.tt +20 -0
- data/generators/bootstrap/app/content_types/.empty_directory +1 -0
- data/generators/bootstrap/app/views/pages/404.liquid +13 -0
- data/generators/bootstrap/app/views/pages/404.liquid.haml +10 -0
- data/generators/bootstrap/app/views/pages/index.liquid +85 -0
- data/generators/bootstrap/app/views/pages/index.liquid.haml +72 -0
- data/generators/bootstrap/app/views/snippets/footer.liquid +3 -0
- data/generators/bootstrap/app/views/snippets/footer.liquid.haml +2 -0
- data/generators/bootstrap/config/deploy.yml +12 -0
- data/generators/bootstrap/config/site.yml.tt +16 -0
- data/generators/bootstrap/config/translations.yml +8 -0
- data/generators/bootstrap/config.ru +3 -0
- data/generators/bootstrap/data/.empty_directory +1 -0
- data/generators/bootstrap/public/fonts/FontAwesome.otf +0 -0
- data/generators/bootstrap/public/fonts/font-awesome-ie7.min.css +23 -0
- data/generators/bootstrap/public/fonts/font-awesome.css +469 -0
- data/generators/bootstrap/public/fonts/font-awesome.min.css +34 -0
- data/generators/bootstrap/public/fonts/fontawesome-webfont.eot +0 -0
- data/generators/bootstrap/public/fonts/fontawesome-webfont.ttf +0 -0
- data/generators/bootstrap/public/fonts/fontawesome-webfont.woff +0 -0
- data/generators/bootstrap/public/javascripts/bootstrap.js +2159 -0
- data/generators/bootstrap/public/javascripts/bootstrap.min.js +6 -0
- data/generators/bootstrap/public/samples/.empty_directory +1 -0
- data/generators/bootstrap/public/stylesheets/application.css.scss +39 -0
- data/generators/bootstrap/public/stylesheets/bootstrap-responsive.css +1092 -0
- data/generators/bootstrap/public/stylesheets/bootstrap-responsive.min.css +9 -0
- data/generators/bootstrap/public/stylesheets/bootstrap.css +5652 -0
- data/generators/bootstrap/public/stylesheets/bootstrap.min.css +726 -0
- data/generators/content_type/app/content_types/%name%.yml.tt +58 -0
- data/generators/content_type/data/%name%.yml.tt +24 -0
- data/generators/page/template.liquid.haml.tt +35 -0
- data/generators/page/template.liquid.tt +1 -0
- data/generators/snippet/template.liquid.haml.tt +4 -0
- data/generators/snippet/template.liquid.tt +4 -0
- data/lib/locomotive/builder/cli.rb +225 -0
- data/lib/locomotive/builder/exceptions.rb +17 -0
- data/lib/locomotive/builder/generators/content_type.rb +47 -0
- data/lib/locomotive/builder/generators/page.rb +57 -0
- data/lib/locomotive/builder/generators/site/base.rb +30 -0
- data/lib/locomotive/builder/generators/site/blank.rb +23 -0
- data/lib/locomotive/builder/generators/site/bootstrap.rb +35 -0
- data/lib/locomotive/builder/generators/site.rb +97 -0
- data/lib/locomotive/builder/generators/snippet.rb +54 -0
- data/lib/locomotive/builder/liquid/drops/base.rb +44 -0
- data/lib/locomotive/builder/liquid/drops/content_entry.rb +48 -0
- data/lib/locomotive/builder/liquid/drops/content_types.rb +121 -0
- data/lib/locomotive/builder/liquid/drops/page.rb +36 -0
- data/lib/locomotive/builder/liquid/drops/site.rb +21 -0
- data/lib/locomotive/builder/liquid/errors.rb +7 -0
- data/lib/locomotive/builder/liquid/filters/date.rb +98 -0
- data/lib/locomotive/builder/liquid/filters/html.rb +154 -0
- data/lib/locomotive/builder/liquid/filters/misc.rb +28 -0
- data/lib/locomotive/builder/liquid/filters/resize.rb +18 -0
- data/lib/locomotive/builder/liquid/filters/text.rb +50 -0
- data/lib/locomotive/builder/liquid/filters/translate.rb +24 -0
- data/lib/locomotive/builder/liquid/patches.rb +47 -0
- data/lib/locomotive/builder/liquid/tags/consume.rb +58 -0
- data/lib/locomotive/builder/liquid/tags/csrf.rb +34 -0
- data/lib/locomotive/builder/liquid/tags/editable/base.rb +46 -0
- data/lib/locomotive/builder/liquid/tags/editable/control.rb +19 -0
- data/lib/locomotive/builder/liquid/tags/editable/file.rb +15 -0
- data/lib/locomotive/builder/liquid/tags/editable/long_text.rb +15 -0
- data/lib/locomotive/builder/liquid/tags/editable/short_text.rb +15 -0
- data/lib/locomotive/builder/liquid/tags/editable.rb +5 -0
- data/lib/locomotive/builder/liquid/tags/extends.rb +25 -0
- data/lib/locomotive/builder/liquid/tags/google_analytics.rb +28 -0
- data/lib/locomotive/builder/liquid/tags/inline_editor.rb +16 -0
- data/lib/locomotive/builder/liquid/tags/locale_switcher.rb +180 -0
- data/lib/locomotive/builder/liquid/tags/nav.rb +167 -0
- data/lib/locomotive/builder/liquid/tags/paginate.rb +105 -0
- data/lib/locomotive/builder/liquid/tags/seo.rb +74 -0
- data/lib/locomotive/builder/liquid/tags/snippet.rb +42 -0
- data/lib/locomotive/builder/liquid/tags/with_scope.rb +43 -0
- data/lib/locomotive/builder/liquid.rb +19 -0
- data/lib/locomotive/builder/listen.rb +48 -0
- data/lib/locomotive/builder/misc/core_ext.rb +29 -0
- data/lib/locomotive/builder/misc/dragonfly.rb +82 -0
- data/lib/locomotive/builder/misc/httparty.rb +47 -0
- data/lib/locomotive/builder/misc/i18n.rb +2 -0
- data/lib/locomotive/builder/misc/will_paginate.rb +16 -0
- data/lib/locomotive/builder/misc.rb +5 -0
- data/lib/locomotive/builder/server/dynamic_assets.rb +31 -0
- data/lib/locomotive/builder/server/entry_submission.rb +116 -0
- data/lib/locomotive/builder/server/favicon.rb +17 -0
- data/lib/locomotive/builder/server/locale.rb +42 -0
- data/lib/locomotive/builder/server/middleware.rb +54 -0
- data/lib/locomotive/builder/server/not_found.rb +18 -0
- data/lib/locomotive/builder/server/page.rb +59 -0
- data/lib/locomotive/builder/server/path.rb +34 -0
- data/lib/locomotive/builder/server/renderer.rb +105 -0
- data/lib/locomotive/builder/server/templatized_page.rb +32 -0
- data/lib/locomotive/builder/server.rb +78 -0
- data/lib/locomotive/builder/standalone_server.rb +33 -0
- data/lib/locomotive/builder/version.rb +5 -0
- data/lib/locomotive/builder.rb +167 -0
- data/locales/de.yml +143 -0
- data/locales/en.yml +164 -0
- data/locales/es.yml +119 -0
- data/locales/et.yml +140 -0
- data/locales/fr.yml +133 -0
- data/locales/it.yml +141 -0
- data/locales/nb.yml +177 -0
- data/locales/nl.yml +148 -0
- data/locales/pl.yml +189 -0
- data/locales/pt-BR.yml +125 -0
- data/locales/ru.yml +210 -0
- data/locomotivecms_builder.gemspec +42 -0
- data/spec/integration/cassettes/pull.yml +590 -0
- data/spec/integration/cassettes/push.yml +775 -0
- data/spec/integration/integration_helper.rb +15 -0
- data/spec/integration/server_spec.rb +37 -0
- data/spec/integration/sites_spec.rb +27 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/helpers.rb +13 -0
- metadata +468 -0
@@ -0,0 +1,167 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Builder
|
3
|
+
module Liquid
|
4
|
+
module Tags
|
5
|
+
# Display the children pages of the site, current page or the parent page. If not precised, nav is applied on the current page.
|
6
|
+
# The html output is based on the ul/li tags.
|
7
|
+
#
|
8
|
+
# Usage:
|
9
|
+
#
|
10
|
+
# {% nav site %} => <ul class="nav"><li class="on"><a href="/features">Features</a></li></ul>
|
11
|
+
#
|
12
|
+
# {% nav site, no_wrapper: true, exclude: 'contact|about', id: 'main-nav', class: 'nav', active_class: 'on' }
|
13
|
+
#
|
14
|
+
class Nav < ::Liquid::Tag
|
15
|
+
|
16
|
+
Syntax = /(#{::Liquid::Expression}+)?/
|
17
|
+
|
18
|
+
attr_accessor :current_page, :mounting_point
|
19
|
+
|
20
|
+
def initialize(tag_name, markup, tokens, context)
|
21
|
+
if markup =~ Syntax
|
22
|
+
@source = ($1 || 'page').gsub(/"|'/, '')
|
23
|
+
@options = { :id => 'nav', :class => '', :active_class => 'on', :bootstrap => false }
|
24
|
+
markup.scan(::Liquid::TagAttributes) { |key, value| @options[key.to_sym] = value.gsub(/"|'/, '') }
|
25
|
+
|
26
|
+
@options[:exclude] = Regexp.new(@options[:exclude]) if @options[:exclude]
|
27
|
+
|
28
|
+
if @options[:snippet]
|
29
|
+
if template = self.parse_snippet_template(context, @options[:snippet])
|
30
|
+
@options[:liquid_render] = template
|
31
|
+
end
|
32
|
+
end
|
33
|
+
else
|
34
|
+
raise ::Liquid::SyntaxError.new("Syntax Error in 'nav' - Valid syntax: nav <site|parent|page|<path to a page>> <options>")
|
35
|
+
end
|
36
|
+
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
def render(context)
|
41
|
+
self.set_accessors_from_context(context)
|
42
|
+
|
43
|
+
children_output = []
|
44
|
+
|
45
|
+
entries = self.fetch_entries
|
46
|
+
|
47
|
+
entries.each_with_index do |p, index|
|
48
|
+
css = []
|
49
|
+
css << 'first' if index == 0
|
50
|
+
css << 'last' if index == entries.size - 1
|
51
|
+
|
52
|
+
children_output << render_entry_link(p, css.join(' '), 1)
|
53
|
+
end
|
54
|
+
|
55
|
+
output = children_output.join("\n")
|
56
|
+
|
57
|
+
if @options[:no_wrapper] != 'true'
|
58
|
+
output = %{<ul id="#{@options[:id]}" class="#{@options[:class]}">\n#{output}</ul>}
|
59
|
+
end
|
60
|
+
|
61
|
+
output
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
def set_accessors_from_context(context)
|
67
|
+
self.current_page = context.registers[:page]
|
68
|
+
self.mounting_point = context.registers[:mounting_point]
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse_snippet_template(context, template_name)
|
72
|
+
source = if template_name.include?('{')
|
73
|
+
template_name
|
74
|
+
else
|
75
|
+
context[:mounting_point].snippets[template_name].try(:source)
|
76
|
+
end
|
77
|
+
|
78
|
+
source ? ::Liquid::Template.parse(source) : nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def fetch_entries
|
82
|
+
children = (case @source
|
83
|
+
when 'site' then self.mounting_point.pages['index']
|
84
|
+
when 'parent' then self.current_page.parent || self.current_page
|
85
|
+
when 'page' then self.current_page
|
86
|
+
else
|
87
|
+
self.mounting_point.pages[@source]
|
88
|
+
end).children.clone
|
89
|
+
|
90
|
+
children.delete_if { |p| !include_page?(p) }
|
91
|
+
end
|
92
|
+
|
93
|
+
# Determines whether or not a page should be a part of the menu
|
94
|
+
def include_page?(page)
|
95
|
+
if !page.listed? || page.templatized? || !page.published?
|
96
|
+
false
|
97
|
+
elsif @options[:exclude]
|
98
|
+
(page.fullpath =~ @options[:exclude]).nil?
|
99
|
+
else
|
100
|
+
true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Returns a list element, a link to the page and its children
|
105
|
+
def render_entry_link(page, css, depth)
|
106
|
+
selected = self.current_page.fullpath =~ /^#{page.fullpath}/ ? " #{@options[:active_class]}" : ''
|
107
|
+
|
108
|
+
icon = @options[:icon] ? '<span></span>' : ''
|
109
|
+
|
110
|
+
title = @options[:liquid_render] ? @options[:liquid_render].render('page' => page) : page.title
|
111
|
+
|
112
|
+
label = %{#{icon if @options[:icon] != 'after' }#{title}#{icon if @options[:icon] == 'after' }}
|
113
|
+
|
114
|
+
dropdow = ""
|
115
|
+
link_options = ""
|
116
|
+
href = ::I18n.locale.to_s == self.mounting_point.default_locale.to_s ? "/#{page.fullpath}" : "/#{::I18n.locale}/#{page.fullpath}"
|
117
|
+
caret = ""
|
118
|
+
|
119
|
+
if render_children_for_page?(page, depth) && bootstrap?
|
120
|
+
dropdow = "dropdown"
|
121
|
+
link_options = %{class="dropdown-toggle" data-toggle="dropdown"}
|
122
|
+
href = "#"
|
123
|
+
caret = %{<b class="caret"></b>}
|
124
|
+
end
|
125
|
+
|
126
|
+
output = %{<li id="#{page.slug.to_s.dasherize}-link" class="link#{selected} #{css} #{dropdow}">}
|
127
|
+
output << %{<a href="#{href}" #{link_options}>#{label} #{caret}</a>}
|
128
|
+
output << render_entry_children(page, depth.succ) if (depth.succ <= @options[:depth].to_i)
|
129
|
+
output << %{</li>}
|
130
|
+
|
131
|
+
output.strip
|
132
|
+
end
|
133
|
+
|
134
|
+
def render_children_for_page?(page, depth)
|
135
|
+
depth.succ <= @options[:depth].to_i && page.children.reject { |c| !include_page?(c) }.any?
|
136
|
+
end
|
137
|
+
|
138
|
+
# Recursively creates a nested unordered list for the depth specified
|
139
|
+
def render_entry_children(page, depth)
|
140
|
+
output = %{}
|
141
|
+
|
142
|
+
children = page.children.reject { |c| !include_page?(c) }
|
143
|
+
if children.present?
|
144
|
+
output = %{<ul id="#{@options[:id]}-#{page.slug.to_s.dasherize}" class="#{bootstrap? ? "dropdown-menu" : ""}">}
|
145
|
+
children.each do |c, page|
|
146
|
+
css = []
|
147
|
+
css << 'first' if children.first == c
|
148
|
+
css << 'last' if children.last == c
|
149
|
+
|
150
|
+
output << render_entry_link(c, css.join(' '),depth)
|
151
|
+
end
|
152
|
+
output << %{</ul>}
|
153
|
+
end
|
154
|
+
|
155
|
+
output
|
156
|
+
end
|
157
|
+
|
158
|
+
def bootstrap?
|
159
|
+
@options[:bootstrap] == 'true' || @options[:bootstrap] == true
|
160
|
+
end
|
161
|
+
|
162
|
+
::Liquid::Template.register_tag('nav', Nav)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Builder
|
3
|
+
module Liquid
|
4
|
+
module Tags
|
5
|
+
|
6
|
+
# Paginate a collection
|
7
|
+
#
|
8
|
+
# Usage:
|
9
|
+
#
|
10
|
+
# {% paginate contents.projects by 5 %}
|
11
|
+
# {% for project in paginate.collection %}
|
12
|
+
# {{ project.name }}
|
13
|
+
# {% endfor %}
|
14
|
+
# {% endpaginate %}
|
15
|
+
#
|
16
|
+
|
17
|
+
class Paginate < ::Liquid::Block
|
18
|
+
|
19
|
+
Syntax = /(#{::Liquid::Expression}+)\s+by\s+([0-9]+)/
|
20
|
+
|
21
|
+
def initialize(tag_name, markup, tokens, context)
|
22
|
+
if markup =~ Syntax
|
23
|
+
@collection_name = $1
|
24
|
+
@per_page = $2.to_i
|
25
|
+
else
|
26
|
+
raise ::Liquid::SyntaxError.new("Syntax Error in 'paginate' - Valid syntax: paginate <collection> by <number>")
|
27
|
+
end
|
28
|
+
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def render(context)
|
33
|
+
context.stack do
|
34
|
+
collection = context[@collection_name]
|
35
|
+
|
36
|
+
raise ::Liquid::ArgumentError.new("Cannot paginate array '#{@collection_name}'. Not found.") if collection.nil?
|
37
|
+
|
38
|
+
pagination = collection.send(:paginate, {
|
39
|
+
:page => context['current_page'],
|
40
|
+
:per_page => @per_page }).stringify_keys!
|
41
|
+
|
42
|
+
page_count, current_page = pagination['total_pages'], pagination['current_page']
|
43
|
+
|
44
|
+
path = sanitize_path(context['fullpath'])
|
45
|
+
|
46
|
+
pagination['previous'] = link(I18n.t('pagination.previous'), current_page - 1, path) if pagination['previous_page']
|
47
|
+
pagination['next'] = link(I18n.t('pagination.next'), current_page + 1, path) if pagination['next_page']
|
48
|
+
pagination['parts'] = []
|
49
|
+
|
50
|
+
hellip_break = false
|
51
|
+
|
52
|
+
if page_count > 1
|
53
|
+
1.upto(page_count) do |page|
|
54
|
+
if current_page == page
|
55
|
+
pagination['parts'] << no_link(page)
|
56
|
+
elsif page == 1
|
57
|
+
pagination['parts'] << link(page, page, path)
|
58
|
+
elsif page == page_count - 1
|
59
|
+
pagination['parts'] << link(page, page, path)
|
60
|
+
elsif page <= current_page - window_size or page >= current_page + window_size
|
61
|
+
next if hellip_break
|
62
|
+
pagination['parts'] << no_link('…')
|
63
|
+
hellip_break = true
|
64
|
+
next
|
65
|
+
else
|
66
|
+
pagination['parts'] << link(page, page, path)
|
67
|
+
end
|
68
|
+
|
69
|
+
hellip_break = false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context['paginate'] = pagination
|
74
|
+
|
75
|
+
render_all(@nodelist, context)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def sanitize_path(path)
|
82
|
+
_path = path.gsub(/page=[0-9]+&?/, '').gsub(/_pjax=true&?/, '')
|
83
|
+
_path = _path.slice(0..-2) if _path.last == '?' || _path.last == '&'
|
84
|
+
_path
|
85
|
+
end
|
86
|
+
|
87
|
+
def window_size
|
88
|
+
3
|
89
|
+
end
|
90
|
+
|
91
|
+
def no_link(title)
|
92
|
+
{ 'title' => title, 'is_link' => false, 'hellip_break' => title == '…' }
|
93
|
+
end
|
94
|
+
|
95
|
+
def link(title, page, path)
|
96
|
+
_path = %(#{path}#{path.include?('?') ? '&' : '?'}page=#{page})
|
97
|
+
{ 'title' => title, 'url' => _path, 'is_link' => true }
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
::Liquid::Template.register_tag('paginate', Paginate)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Builder
|
3
|
+
module Liquid
|
4
|
+
module Tags
|
5
|
+
module SEO
|
6
|
+
|
7
|
+
class Base < ::Liquid::Tag
|
8
|
+
|
9
|
+
def render(context)
|
10
|
+
%{
|
11
|
+
#{self.render_title(context)}
|
12
|
+
#{self.render_metadata(context)}
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def render_title(context)
|
19
|
+
title = self.value_for(:seo_title, context)
|
20
|
+
title = context.registers[:site].name if title.blank?
|
21
|
+
|
22
|
+
%{
|
23
|
+
<title>#{title}</title>
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def render_metadata(context)
|
28
|
+
%{
|
29
|
+
<meta name="description" content="#{self.value_for(:meta_description, context)}" />
|
30
|
+
<meta name="keywords" content="#{self.value_for(:meta_keywords, context)}" />
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
# Removes whitespace and quote characters from the input
|
35
|
+
def sanitized_string(string)
|
36
|
+
string ? string.strip.gsub(/"/, '') : ''
|
37
|
+
end
|
38
|
+
|
39
|
+
def value_for(attribute, context)
|
40
|
+
object = self.metadata_object(context)
|
41
|
+
value = object.try(attribute.to_sym).blank? ? context.registers[:site].send(attribute.to_sym) : object.send(attribute.to_sym)
|
42
|
+
self.sanitized_string(value)
|
43
|
+
end
|
44
|
+
|
45
|
+
def metadata_object(context)
|
46
|
+
context['content_instance'] || context['page']
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Title < Base
|
51
|
+
|
52
|
+
def render(context)
|
53
|
+
self.render_title(context)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
class Metadata < Base
|
59
|
+
|
60
|
+
def render(context)
|
61
|
+
self.render_metadata(context)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
::Liquid::Template.register_tag('seo', SEO::Base)
|
69
|
+
::Liquid::Template.register_tag('seo_title', SEO::Title)
|
70
|
+
::Liquid::Template.register_tag('seo_metadata', SEO::Metadata)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Builder
|
3
|
+
module Liquid
|
4
|
+
module Tags
|
5
|
+
|
6
|
+
class Snippet < ::Liquid::Include
|
7
|
+
|
8
|
+
def render(context)
|
9
|
+
name = @template_name.gsub(/[\"\']/, '')
|
10
|
+
|
11
|
+
source = context.registers[:mounting_point].snippets[name].try(:source)
|
12
|
+
|
13
|
+
partial = ::Liquid::Template.parse(source)
|
14
|
+
|
15
|
+
variable = context[@variable_name || @template_name[1..-2]]
|
16
|
+
|
17
|
+
context.stack do
|
18
|
+
@attributes.each do |key, value|
|
19
|
+
context[key] = context[value]
|
20
|
+
end
|
21
|
+
|
22
|
+
output = (if variable.is_a?(Array)
|
23
|
+
variable.collect do |variable|
|
24
|
+
context[@template_name[1..-2]] = variable
|
25
|
+
partial.render(context)
|
26
|
+
end
|
27
|
+
else
|
28
|
+
context[@template_name[1..-2]] = variable
|
29
|
+
partial.render(context)
|
30
|
+
end)
|
31
|
+
|
32
|
+
output
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
::Liquid::Template.register_tag('include', Snippet)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Builder
|
3
|
+
module Liquid
|
4
|
+
module Tags
|
5
|
+
class WithScope < ::Liquid::Block
|
6
|
+
|
7
|
+
def initialize(tag_name, markup, tokens, context)
|
8
|
+
@options = {}
|
9
|
+
|
10
|
+
markup.scan(::Liquid::TagAttributes) do |key, value|
|
11
|
+
@options[key] = value
|
12
|
+
end
|
13
|
+
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def render(context)
|
18
|
+
context.stack do
|
19
|
+
context['with_scope'] = decode(@options, context)
|
20
|
+
render_all(@nodelist, context)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def decode(attributes, context)
|
27
|
+
attributes.each_pair do |key, value|
|
28
|
+
attributes[key] = (case value
|
29
|
+
when /^true|false$/i then value == 'true'
|
30
|
+
when /^[0-9]+$/ then value.to_i
|
31
|
+
when /^["|'](.+)["|']$/ then $1.gsub(/^["|']/, '').gsub(/["|']$/, '')
|
32
|
+
else
|
33
|
+
context[value] || value
|
34
|
+
end)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
::Liquid::Template.register_tag('with_scope', WithScope)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "locomotive/mounter"
|
2
|
+
require 'liquid'
|
3
|
+
require 'locomotive/builder/liquid/drops/base'
|
4
|
+
|
5
|
+
%w{. drops tags filters}.each do |dir|
|
6
|
+
Dir[File.join(File.dirname(__FILE__), 'liquid', dir, '*.rb')].each { |lib| require lib }
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
# add to_liquid methods to main models from the mounter
|
11
|
+
%w{site page content_entry}.each do |name|
|
12
|
+
klass = "Locomotive::Mounter::Models::#{name.classify}".constantize
|
13
|
+
|
14
|
+
klass.class_eval <<-EOV
|
15
|
+
def to_liquid
|
16
|
+
::Locomotive::Builder::Liquid::Drops::#{name.classify}.new(self)
|
17
|
+
end
|
18
|
+
EOV
|
19
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'listen'
|
2
|
+
|
3
|
+
module Locomotive::Builder
|
4
|
+
class Listen
|
5
|
+
|
6
|
+
attr_accessor :reader
|
7
|
+
|
8
|
+
def self.instance
|
9
|
+
@@instance = new
|
10
|
+
end
|
11
|
+
|
12
|
+
def start(reader)
|
13
|
+
self.reader = reader
|
14
|
+
|
15
|
+
self.definitions.each do |definition|
|
16
|
+
self.apply(definition)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def definitions
|
21
|
+
[
|
22
|
+
['config', /\.yml/, [:site, :content_types, :pages, :snippets, :content_entries, :translations]],
|
23
|
+
['app/views', /\.liquid/, [:pages, :snippets]],
|
24
|
+
['app/content_types', /\.yml/, [:content_types, :content_entries]],
|
25
|
+
['data', /\.yml/, :content_entries]
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def apply(definition)
|
32
|
+
reloader = Proc.new do |modified, added, removed|
|
33
|
+
reader.reload(definition.last)
|
34
|
+
end
|
35
|
+
|
36
|
+
filter = definition[1]
|
37
|
+
path = File.join(self.reader.mounting_point.path, definition.first)
|
38
|
+
path = File.expand_path(path)
|
39
|
+
|
40
|
+
listener = ::Listen.to(path).filter(filter).change(&reloader)
|
41
|
+
|
42
|
+
# non blocking listener
|
43
|
+
listener.start(false)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
unless Hash.instance_methods.include?(:underscore_keys)
|
2
|
+
class Hash
|
3
|
+
|
4
|
+
def underscore_keys
|
5
|
+
new_hash = {}
|
6
|
+
|
7
|
+
self.each_pair do |key, value|
|
8
|
+
if value.respond_to?(:collect!) # Array
|
9
|
+
value.collect do |item|
|
10
|
+
if item.respond_to?(:each_pair) # Hash item within
|
11
|
+
item.underscore_keys
|
12
|
+
else
|
13
|
+
item
|
14
|
+
end
|
15
|
+
end
|
16
|
+
elsif value.respond_to?(:each_pair) # Hash
|
17
|
+
value = value.underscore_keys
|
18
|
+
end
|
19
|
+
|
20
|
+
new_key = key.is_a?(String) ? key.underscore : key # only String keys
|
21
|
+
|
22
|
+
new_hash[new_key] = value
|
23
|
+
end
|
24
|
+
|
25
|
+
self.replace(new_hash)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Builder
|
3
|
+
class Dragonfly
|
4
|
+
|
5
|
+
attr_accessor :path, :enabled
|
6
|
+
|
7
|
+
def enabled?
|
8
|
+
!!self.enabled
|
9
|
+
end
|
10
|
+
|
11
|
+
def resize_url(source, resize_string)
|
12
|
+
_source = (case source
|
13
|
+
when String then source
|
14
|
+
when Hash then source['url'] || source[:url]
|
15
|
+
else
|
16
|
+
source.try(:url)
|
17
|
+
end)
|
18
|
+
|
19
|
+
if _source.blank?
|
20
|
+
LocomotiveEditor::Logger.error "Unable to resize on the fly: #{source.inspect}"
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
return _source unless self.enabled?
|
25
|
+
|
26
|
+
if _source =~ /^http/
|
27
|
+
file = self.class.app.fetch_url(_source)
|
28
|
+
else
|
29
|
+
file = self.class.app.fetch_file(File.join(self.path, 'public', _source))
|
30
|
+
end
|
31
|
+
|
32
|
+
file.process(:thumb, resize_string).url
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.app
|
36
|
+
::Dragonfly[:images]
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def self.instance
|
41
|
+
@@instance ||= new
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.setup!(path)
|
45
|
+
self.instance.path = path
|
46
|
+
self.instance.enabled = false
|
47
|
+
|
48
|
+
begin
|
49
|
+
require 'rack/cache'
|
50
|
+
require 'RMagick'
|
51
|
+
require 'dragonfly'
|
52
|
+
|
53
|
+
## initialize Dragonfly ##
|
54
|
+
app = ::Dragonfly[:images].configure_with(:imagemagick)
|
55
|
+
|
56
|
+
## configure it ##
|
57
|
+
::Dragonfly[:images].configure do |c|
|
58
|
+
convert = `which convert`.strip.presence || '/usr/local/bin/convert'
|
59
|
+
c.convert_command = convert
|
60
|
+
c.identify_command = convert
|
61
|
+
|
62
|
+
c.allow_fetch_url = true
|
63
|
+
c.allow_fetch_file = true
|
64
|
+
|
65
|
+
c.url_format = '/images/dynamic/:job/:basename.:format'
|
66
|
+
end
|
67
|
+
|
68
|
+
puts 'Dragonfly enabled'
|
69
|
+
|
70
|
+
self.instance.enabled = true
|
71
|
+
rescue Exception => e
|
72
|
+
puts %{
|
73
|
+
\tIf you want to take full benefits of all the features in the LocomotiveEditor, we recommend you to install ImageMagick and RMagick.
|
74
|
+
\tCheck out the documentation here: http://doc.locomotivecms.com/editor/installation.}
|
75
|
+
|
76
|
+
puts 'Dragonfly disabled'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Locomotive
|
4
|
+
module Builder
|
5
|
+
module Httparty
|
6
|
+
class Webservice
|
7
|
+
|
8
|
+
include ::HTTParty
|
9
|
+
|
10
|
+
def self.consume(url, options = {})
|
11
|
+
url = ::HTTParty.normalize_base_uri(url)
|
12
|
+
|
13
|
+
uri = URI.parse(url)
|
14
|
+
options[:base_uri] = "#{uri.scheme}://#{uri.host}"
|
15
|
+
options[:base_uri] += ":#{uri.port}" if uri.port != 80
|
16
|
+
path = uri.request_uri
|
17
|
+
|
18
|
+
options.delete(:format) if options[:format] == 'default'
|
19
|
+
|
20
|
+
username, password = options.delete(:username), options.delete(:password)
|
21
|
+
options[:basic_auth] = { username: username, password: password } if username
|
22
|
+
|
23
|
+
path ||= '/'
|
24
|
+
|
25
|
+
# puts "[WebService] consuming #{path}, #{options.inspect}"
|
26
|
+
|
27
|
+
response = self.get(path, options)
|
28
|
+
|
29
|
+
if response.code == 200
|
30
|
+
_response = response.parsed_response
|
31
|
+
if _response.respond_to?(:underscore_keys)
|
32
|
+
_response.underscore_keys
|
33
|
+
else
|
34
|
+
_response.collect(&:underscore_keys)
|
35
|
+
end
|
36
|
+
else
|
37
|
+
# TODO: handle errors
|
38
|
+
puts "[Locomotive][Builder][Error] consuming #{path}, #{options.inspect}, response = #{response.inspect}"
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'will_paginate'
|
2
|
+
require 'will_paginate/collection'
|
3
|
+
|
4
|
+
Array.class_eval do
|
5
|
+
def paginate(options = {})
|
6
|
+
raise ArgumentError, "parameter hash expected (got #{options.inspect})" unless Hash === options
|
7
|
+
|
8
|
+
WillPaginate::Collection.create(
|
9
|
+
options[:page] || 1,
|
10
|
+
options[:per_page] || 30,
|
11
|
+
options[:total_entries] || self.length
|
12
|
+
) { |pager|
|
13
|
+
pager.replace self[pager.offset, pager.per_page].to_a
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|