├── .gitignore
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── jekyll-contentful.gemspec
└── lib
├── jekyll-contentful.rb
└── jekyll-contentful
├── contentful-monkeypatch.rb
├── language_switcher_tag.rb
└── version.rb
/.gitignore:
--------------------------------------------------------------------------------
1 | /.bundle/
2 | /.yardoc
3 | /Gemfile.lock
4 | /_yardoc/
5 | /coverage/
6 | /doc/
7 | /pkg/
8 | /spec/reports/
9 | /tmp/
10 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # Specify your gem's dependencies in jekyllcontentful.gemspec
4 | gemspec
5 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Dommmel
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Jekyll-Contentful
2 |
3 | Generate Pages for Contentful Entries
4 |
5 | ## Installation
6 |
7 | Add this line to your Gemfile:
8 |
9 | ```ruby
10 | group :jekyll_plugins do
11 | gem "jekyll-contentful"
12 | end
13 | ```
14 |
15 | And then execute:
16 |
17 | $ bundle
18 |
19 | Alternatively install the gem yourself as:
20 |
21 | $ gem install jekyll-contentful
22 |
23 | and put this in your ``_config.yml``
24 |
25 | ```yaml
26 | gems: [jekyll-contentful]
27 | # This will require each of these gems automatically.
28 | ```
29 |
30 | ## Configuration
31 |
32 | Configure in your _config.yml file
33 |
34 |
35 | ```yaml
36 | contentful:
37 | preview: No
38 | production_access_token: 'YOUR_PRODUCTION_TOKEN'
39 | preview_access_token: 'YOUR_PREVIEW_TOKEN'
40 | space: 'YOUR_SPACE'
41 | content_types:
42 | - "First Content Type"
43 | - "Second Content Type"
44 | published_locales_field: "published_languages"
45 | localization:
46 | - locale: en-US
47 | url_prefix: ""
48 | lang: "English"
49 | - locale: de-DE
50 | url_prefix: "de/"
51 | lang: "Deutsch"
52 | ```
53 |
54 |
55 | ### Translations
56 | You can globally specify the languages/locales that you want to generate pages for.
57 | See the ``localization`` array in the ``_config.yml`` example above. You need to set the ``locale``, a string that this locale's urls will be prefixed with (``url_prefix``) and the language name (``lang``). The ``lang`` setting is used by the language switcher.
58 |
59 | #### Language switcher
60 | you can use the tag ``{% language_switcher %}`` in your templates to insert a link to the translations of the current page.
61 |
62 | #### Selective Translations
63 | By default the plugin will – for every entry – generate a page for every locale you specified in your ``_config.yml``.
64 |
65 | You can also **specify** which **locales** should be published **on the entry level**:
66 |
67 | 1. Add a Content Type called "Languages" to your space (you can name it differently).
68 | 2. Add a field called "locale" to that content type (this field has to be called "locale" and nothing else).
69 | 3. Add an entry of that content type for every locale you have enabled in your space. Set those entries' "locale" field accordingly.
70 | 4. Add a reference field (many) to the content type you want to selectively translate. Call it "published_languages" (you can name it differently but it has to match the name in the next step). Set the validations to allow only the content type "Languages" to be referenced.
71 | 5. Add ``published_locales_field: "published_languages"`` in the ``contentful:``section of your ``_config.yml``
72 |
73 | Now for every entry you can specify the languages you want to generate pages for by adding them to your entries "published_languages" list.
74 |
75 | #### Content Fields:
76 |
77 | All Entry fields can be used inside the layout templates as {{ page.contentful_fields.fieldname }}.
78 | The plugin adds two more fields to pages generated from Contentful entries: ``{ page.contentful_id }}`` and ``{{ page.contentful_locale }}``.
79 |
80 | #### ULRs and Layouts:
81 |
82 | Let's say you have a content type named "Blog Post" with an entry that has its title field set to "Awesome Title".
83 | The plugin will generate a page using the "blog-post.html" layout at the url: /en/blog-post/awesome-title/index.html
84 |
85 | If no layout named "blog-post.html" can be found the plugin will fallback to use the "default.html" layout.
86 |
87 | ## Minimal Layout Example
88 |
89 | the following example assumes a content type with two fields. A long text field named "body" and a short text field named "title".
90 |
91 | ```liquid
92 |
93 |
94 |
95 |
108 |
109 | {{ page.title }}
110 | {{ page.body | markdownify }}
111 |
112 | {% language_switcher %}
113 |
114 |
115 | ```
116 |
117 | You can find a more comprehensive example over at [github.com/dommmel/jekyll-contentful-example](https://github.com/dommmel/jekyll-contentful-example).
118 |
119 | ## License
120 |
121 | The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require "bundler/gem_tasks"
2 |
--------------------------------------------------------------------------------
/jekyll-contentful.gemspec:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | lib = File.expand_path('../lib', __FILE__)
3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4 | require 'jekyll-contentful/version'
5 |
6 | Gem::Specification.new do |spec|
7 | spec.name = "jekyll-contentful"
8 | spec.version = Jekyll::Contentful::VERSION
9 | spec.authors = ["Dommmel"]
10 | spec.email = ["dommmel@gmail.com"]
11 |
12 | spec.summary = %q{jekyll plugin that generates pages from contentful entries}
13 | spec.description = %q{jekyll plugin that generates pages from contentful entries}
14 | spec.homepage = "https://github.com/dommmel/jekyll-contentful"
15 | spec.license = "MIT"
16 |
17 | spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18 | spec.require_paths = ["lib"]
19 |
20 | spec.add_dependency 'jekyll'
21 | spec.add_dependency "contentful"
22 | spec.add_development_dependency "bundler", "~> 1.10"
23 | spec.add_development_dependency "rake", "~> 10.0"
24 | end
25 |
--------------------------------------------------------------------------------
/lib/jekyll-contentful.rb:
--------------------------------------------------------------------------------
1 | require "jekyll"
2 | require "contentful"
3 | require "jekyll-contentful/version"
4 | require "jekyll-contentful/contentful-monkeypatch"
5 | require "jekyll-contentful/language_switcher_tag"
6 |
7 | module Jekyll
8 | class ContentfulEntryPage < Page
9 | def initialize(site, entry, content_type_name, prefix)
10 |
11 | @site = site
12 | @base = site.source
13 | @name = 'index.html'
14 |
15 | content_type_slug = Utils.slugify content_type_name
16 |
17 | layout_filename = site.layouts.key?(content_type_slug) ? "#{content_type_slug}.html" : "default.html"
18 | self.read_yaml(File.join(@base, '_layouts'), layout_filename)
19 |
20 | # stringify hash keys
21 | fields = Jekyll::Utils.stringify_hash_keys(entry.fields)
22 | self.data['contentful_fields'] = fields
23 |
24 | display_field = entry.content_type.resolve.display_field
25 | self.data['title'] = fields[display_field] if display_field
26 |
27 | self.data["contentful_id"] = entry.id
28 | self.data["contentful_locale"] = entry.locale
29 | self.data["contentful_content_type_name"] = content_type_name
30 |
31 | # If there is a title fields make it the url
32 | page_title_slug = Utils.slugify(self.data["title"] || "")
33 | @dir = "/#{prefix}#{content_type_slug}/#{page_title_slug}"
34 |
35 | self.process(@name)
36 | end
37 | end
38 |
39 | class ContentfulEntryPageGenerator < Generator
40 | safe true
41 |
42 | def generate(site)
43 |
44 | if site.config['contentful']['preview']
45 | api_url = 'preview.contentful.com'
46 | access_token = site.config['contentful']['preview_access_token']
47 | else
48 | api_url = 'cdn.contentful.com'
49 | access_token = site.config['contentful']['production_access_token']
50 | end
51 |
52 | client = ::Contentful::Client.new(
53 | access_token: access_token,
54 | space: site.config['contentful']['space'],
55 | api_url: api_url
56 | )
57 |
58 | # Loop over all content types
59 | site.config['contentful']['content_types'].each do |content_type_id|
60 | # Get name for content type ID
61 | content_type = client.content_types('sys.id' => content_type_id).first
62 |
63 | throw "Content_type \'#{content_type_id}\' does not exist." if content_type.nil?
64 |
65 | localization = site.config['contentful']['localization'] || [{locale: nil, url_prefix: ""}]
66 |
67 | # Get all entries of content type
68 |
69 | localization.each do |loc|
70 | entries = client.entries(content_type: content_type_id, locale: loc["locale"], limit: 1000)
71 | entries.each do |entry|
72 |
73 | next if entry.fields.nil?
74 |
75 | published_locales_field = site.config['contentful']['published_locales_field']
76 | pub_langs = published_locales_field.nil? ? nil : entry.fields[published_locales_field.to_sym]
77 |
78 | if pub_langs.nil? or pub_langs.map{|x| x.fields[:locale]}.include?(loc["locale"])
79 | site.pages << ContentfulEntryPage.new(site, entry, content_type.name, "#{loc['url_prefix']}")
80 | end
81 | end
82 | end
83 |
84 | end
85 | end
86 | end
87 |
88 | end
89 |
--------------------------------------------------------------------------------
/lib/jekyll-contentful/contentful-monkeypatch.rb:
--------------------------------------------------------------------------------
1 | # Make asset arrays work in liquid templates
2 | # e.g.
3 | #
4 | # {% for pic in page.gallery %}
5 | # {{ pic.title }}
6 | #
7 | # {% endfor %}
8 | #
9 |
10 | module Contentful
11 | class Asset
12 | def to_liquid
13 | Jekyll::Utils.stringify_hash_keys(self.fields)
14 | end
15 | end
16 | class File
17 | def to_liquid
18 | Jekyll::Utils.stringify_hash_keys(self.properties)
19 | end
20 | end
21 | end
--------------------------------------------------------------------------------
/lib/jekyll-contentful/language_switcher_tag.rb:
--------------------------------------------------------------------------------
1 | module Jekyll
2 | class LanguageSwitcherTag < Liquid::Tag
3 |
4 | def initialize(tag_name, text, tokens)
5 | super
6 | @text = text
7 | end
8 |
9 | def render(context)
10 | @site = context.registers[:site]
11 | this_page = context.registers[:page]
12 |
13 | return "" if @site.config['contentful']['localization'].nil? || this_page["contentful_id"].nil?
14 |
15 | translated_pages = @site.pages.select do |that_page|
16 | that_page["contentful_id"] == this_page["contentful_id"] and that_page["contentful_locale"] != this_page["contentful_locale"]
17 | end
18 | if translated_pages.length > 1
19 | list = translated_pages.dup.map do |tp|
20 | "#{anchor(tp)}"
21 | end.join()
22 | return ""
23 | elsif translated_pages.length == 1
24 | return anchor(translated_pages[0])
25 | end
26 | end
27 |
28 | def anchor(page)
29 | lang = @site.config['contentful']['localization'].detect{ |loc| loc["locale"] == page['contentful_locale']}["lang"]
30 | "#{ lang }"
31 | end
32 | end
33 | end
34 |
35 | Liquid::Template.register_tag('language_switcher', Jekyll::LanguageSwitcherTag)
--------------------------------------------------------------------------------
/lib/jekyll-contentful/version.rb:
--------------------------------------------------------------------------------
1 | module Jekyll
2 | module Contentful
3 | VERSION = "0.1.5"
4 | end
5 | end
6 |
--------------------------------------------------------------------------------