site metafields are now available in the liquid template
did
committed Jan 24, 2016
commit c4302cb3d9119638dea8ca7fd3c99d1b9a6d6c2d
Showing 11
changed files with
185 additions
and 26 deletions
locomotive/steam/adapters/filesystem.rb b/lib/locomotive/steam/adapters/filesystem.rb
+1
-1
| @@ | @@ -116,7 +116,7 @@ module Locomotive::Steam |
| def build_sanitizers | |
| hash = Hash.new { build_klass('Sanitizers', :simple).new } | |
| - | %i(site pages content_types content_entries snippets).inject(hash) do |memo, name| |
| + | %i(sites pages content_types content_entries snippets).inject(hash) do |memo, name| |
| memo[name] = build_klass('Sanitizers', name).new | |
| memo | |
| end | |
locomotive/steam/adapters/filesystem/sanitizers/site.rb b/lib/locomotive/steam/adapters/filesystem/sanitizers/site.rb
+5
-7
| @@ | @@ -18,21 +18,19 @@ module Locomotive::Steam |
| schema.map do |namespace, definitions| | |
| { | |
| - | name: { default: namespace.to_s }.merge(definitions.delete(:name) || {}), |
| + | label: { default: namespace.to_s }.merge(definitions.delete(:label) || {}), |
| fields: parse_metafields(definitions.delete(:fields)) | |
| }.merge(definitions) | |
| - | end |
| + | end.as_json |
| end | |
| def parse_metafields(fields) | |
| fields.map do |name, attributes| | |
| if attributes # Hash | |
| - | attributes[:hint] = { default: attributes[:hint] } if attributes[:hint].is_a?(String) |
| - | |
| - | { name: { default: name.to_s }.merge(attributes.delete(:name)) }.merge(attributes) |
| - | else # Array |
| - | { name: { default: name.to_s } } |
| + | attributes[:label] = { default: attributes[:label] } if attributes[:label].is_a?(String) |
| + | attributes[:hint] = { default: attributes[:hint] } if attributes[:hint].is_a?(String) |
| end | |
| + | { name: name.to_s }.merge(attributes || {}) |
| end | |
| end | |
locomotive/steam/liquid/drops/metafields.rb b/lib/locomotive/steam/liquid/drops/metafields.rb
+47
-0
| @@ | @@ -0,0 +1,47 @@ |
| + | module Locomotive |
| + | module Steam |
| + | module Liquid |
| + | module Drops |
| + | |
| + | class Metafields < Base |
| + | |
| + | def before_method(meth) |
| + | if field = fields[meth.to_s] |
| + | find_value(meth.to_s, field) |
| + | else |
| + | Locomotive::Common::Logger.warn "[Liquid template] unknown site metafield \"#{meth.to_s}\"" |
| + | nil |
| + | end |
| + | end |
| + | |
| + | private |
| + | |
| + | def find_value(name, field) |
| + | value = @_source.metafields[name] |
| + | |
| + | return nil if value.blank? |
| + | |
| + | key = field['localized'] ? @context.registers[:locale] : 'default' |
| + | value = { 'default' => value } unless value.is_a?(Hash) |
| + | |
| + | value[key] |
| + | end |
| + | |
| + | def fields |
| + | return @schema if @schema |
| + | |
| + | (@schema = {}).tap do |
| + | @_source.metafields_schema.each do |definition| |
| + | definition['fields'].each do |field| |
| + | @schema[field['name']] = field |
| + | end |
| + | end |
| + | end |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | end |
| + | end |
| + | end |
locomotive/steam/liquid/drops/site.rb b/lib/locomotive/steam/liquid/drops/site.rb
+4
-0
| @@ | @@ -14,6 +14,10 @@ module Locomotive |
| liquify(*self.scoped_pages) | |
| end | |
| + | def metafields |
| + | @metafields ||= Metafields.new(@_source) |
| + | end |
| + | |
| protected | |
| def repository | |
spec/fixtures/default/app/views/pages/basic.liquid.haml
+7
-0
| @@ | @@ -12,3 +12,10 @@ position: 6 |
| %body | |
| %p | |
| This is a basic page | |
| + | |
| + | %ul |
| + | %li Color scheme={{ site.metafields.color_scheme }} |
| + | %li Facebook ID={{ site.metafields.facebook_id }} |
| + | %li Google ID={{ site.metafields.google_id }} |
| + | %li API URL={{ site.metafields.api_url }} |
| + | %li Expires In={{ site.metafields.expires_in }} |
spec/fixtures/default/config/metafields_schema.yml
+15
-9
| @@ | @@ -1,22 +1,28 @@ |
| + | Theme: |
| + | fields: |
| + | color_scheme: |
| + | localized: true |
| + | |
| Social: | |
| - | name: |
| + | label: |
| fr: Social (FR) | |
| position: 1 | |
| fields: | |
| - | - Facebook ID |
| - | - Google ID |
| + | - facebook_id |
| + | - google_id |
| Github: | |
| position: 0 | |
| fields: | |
| - | "API url": |
| - | name: |
| + | api_url: |
| + | label: |
| + | en: 'API Url' |
| fr: "Url de l'API" | |
| type: string | |
| - | hint: "API endpoint" |
| - | default: https://api.github.com/repos/locomotivecms/engine/issues?state=opened |
| - | "Expire in": |
| - | name: |
| + | hint: 'API endpoint' |
| + | expires_in: |
| + | label: |
| + | en: 'Expires in' |
| fr: 'Expire dans' | |
| hint: | |
| en: 'Cache - In milliseconds' | |
spec/fixtures/default/config/site.yml
+10
-0
| @@ | @@ -19,3 +19,13 @@ meta_keywords: |
| meta_description: some meta description | |
| robots_txt: "User-agent: *\nDisallow:" | |
| + | |
| + | metafields: |
| + | color_scheme: |
| + | en: 'white' |
| + | fr: 'blue' |
| + | nb: 'red' |
| + | facebook_id: 'FB42' |
| + | google_id: 'G42' |
| + | api_url: https://api.github.com/repos/vmg/redcarpet/issues?state=closed |
| + | expires_in: 42 |
spec/integration/server/metafields_spec.rb
+20
-0
| @@ | @@ -0,0 +1,20 @@ |
| + | require File.dirname(__FILE__) + '/../integration_helper' |
| + | |
| + | describe 'Site metafields' do |
| + | |
| + | include Rack::Test::Methods |
| + | |
| + | def app |
| + | run_server |
| + | end |
| + | |
| + | it 'returns all the values of the site metafields' do |
| + | get '/basic' |
| + | expect(last_response.body).to include 'Color scheme=white' |
| + | expect(last_response.body).to include 'Facebook ID=FB42' |
| + | expect(last_response.body).to include 'Google ID=G42' |
| + | expect(last_response.body).to include 'API URL=https://api.github.com/repos/vmg/redcarpet/issues?state=closed' |
| + | expect(last_response.body).to include 'Expires In=42' |
| + | end |
| + | |
| + | end |
spec/unit/adapters/filesystem/sanitizers/site_spec.rb
+8
-8
| @@ | @@ -26,19 +26,19 @@ describe Locomotive::Steam::Adapters::Filesystem::Sanitizers::Site do |
| describe 'with a schema' do | |
| # see the metafields_schema.yml in the fixtures folder | |
| - | let(:schema) { {:Social=>{:name=>{:fr=>"Social (FR)"}, :position=>1, :fields=>["Facebook ID", "Google ID"]}, :Github=>{:position=>0, :fields=>{:"API url"=>{:name=>{:fr=>"Url de l'API"}, :type=>"string", :hint=>"API endpoint", :default=>"https://api.github.com/repos/locomotivecms/engine/issues?state=opened"}, :"Expire in"=>{:name=>{:fr=>"Expire dans"}, :hint=>{:en=>"Cache - In milliseconds", :fr=>"Cache - En millisecondes"}, :type=>"integer", :min=>0, :max=>3600}}}} } |
| + | let(:schema) { {:Social=>{:label=>{:fr=>"Social (FR)"}, :position=>1, :fields=>["facebook_id", "google_id"]}, :Github=>{:position=>0, :fields=>{:api_url=>{:label=>"API Url", :type=>"string", :hint=>"API endpoint"}, :expires_in=>{:label=>{:en=>"Expires in", :fr=>"Expire dans"}, :hint=>{:en=>"Cache - In milliseconds", :fr=>"Cache - En millisecondes"}, :type=>"integer", :min=>0, :max=>3600}}}} } |
| it 'loads the full schema' do | |
| # First namespace | |
| - | expect(subject[0][:name]).to eq(default: 'Social', fr: 'Social (FR)') |
| - | expect(subject[0][:position]).to eq 1 |
| - | expect(subject[0][:fields]).to eq([{ name: { default: 'Facebook ID' } }, { name: { default: 'Google ID' } }]) |
| + | expect(subject[0]['label']).to eq('default' => 'Social', 'fr' => 'Social (FR)') |
| + | expect(subject[0]['position']).to eq 1 |
| + | expect(subject[0]['fields']).to eq([{ 'name' => 'facebook_id' }, { 'name' => 'google_id' }]) |
| # Second namespace | |
| - | expect(subject[1][:name]).to eq(default: 'Github') |
| - | expect(subject[1][:position]).to eq 0 |
| - | expect(subject[1][:fields].count).to eq 2 |
| - | expect(subject[1][:fields][0]).to eq(name: { default: 'API url', fr: "Url de l'API" }, type: 'string', hint: { default: 'API endpoint' }, default: 'https://api.github.com/repos/locomotivecms/engine/issues?state=opened') |
| + | expect(subject[1]['label']).to eq('default' => 'Github') |
| + | expect(subject[1]['position']).to eq 0 |
| + | expect(subject[1]['fields'].count).to eq 2 |
| + | expect(subject[1]['fields'][0]).to eq('name' => 'api_url', 'label' => { 'default' => 'API Url' }, 'type' => 'string', 'hint' => { 'default' => 'API endpoint' }) |
| end | |
| end | |
spec/unit/adapters/filesystem/yaml_loaders/site_spec.rb
+1
-1
| @@ | @@ -19,7 +19,7 @@ describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::Site do |
| subject { loader.load(nil).first[:metafields_schema] } | |
| it 'loads the full schema' do | |
| - | expect(subject.count).to eq 2 |
| + | expect(subject.count).to eq 3 |
| end | |
| end | |
spec/unit/liquid/drops/metafields_spec.rb
+67
-0
| @@ | @@ -0,0 +1,67 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Liquid::Drops::Metafields do |
| + | |
| + | let(:metafields) { { 'analytics_id' => { 'default' => '42' }, 'street' => { 'en' => '7 Albert Camus Alley', 'fr' => '7 allée Albert Camus' } } } |
| + | let(:schema) { [ { fields: [{ name: 'analytics_id' }] }, { fields: [{ name: 'street', localized: true }, { name: 'country' }] }].as_json } |
| + | let(:site) { instance_double('Site', metafields: metafields, metafields_schema: schema) } |
| + | let(:context) { ::Liquid::Context.new({}, {}, { locale: 'en' }) } |
| + | let(:drop) { described_class.new(site).tap { |d| d.context = context } } |
| + | |
| + | describe 'calling a metafield' do |
| + | |
| + | context 'unknown field' do |
| + | |
| + | subject { drop.before_method(:unknown_field) } |
| + | |
| + | it { is_expected.to eq nil } |
| + | |
| + | end |
| + | |
| + | context 'not localized field' do |
| + | |
| + | context 'the value exists' do |
| + | |
| + | subject { drop.before_method(:analytics_id) } |
| + | |
| + | it { is_expected.to eq '42' } |
| + | |
| + | end |
| + | |
| + | context "the value doesn't exist" do |
| + | |
| + | subject { drop.before_method(:country) } |
| + | |
| + | it { is_expected.to eq nil } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | context 'localized field' do |
| + | |
| + | subject { drop.before_method(:street) } |
| + | |
| + | it { is_expected.to eq '7 Albert Camus Alley' } |
| + | |
| + | context 'in another locale' do |
| + | |
| + | let(:context) { ::Liquid::Context.new({}, {}, { locale: 'fr' }) } |
| + | |
| + | it { is_expected.to eq '7 allée Albert Camus' } |
| + | |
| + | end |
| + | |
| + | context 'in a locale with no translation' do |
| + | |
| + | let(:context) { ::Liquid::Context.new({}, {}, { locale: 'de' }) } |
| + | |
| + | it { is_expected.to eq nil } |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
| + | |
| + | end |