jekyll-json-feed 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 81fbe54b756186f7df4e7ed2283815eeffd44d44
4
+ data.tar.gz: 77944ea7447c9e73de28d3485b687c095d9c51a6
5
+ SHA512:
6
+ metadata.gz: a8d2e610097b29b4e45129cf7f7593e5e58ec0ddf6e33afccf5163b338703a76a36fd41358092c1cf48c8e119b9618a1a8300e2d9d42f7ab8be2e2a666aa5b1f
7
+ data.tar.gz: 5bfe4cf12f34a7d17545a54acd93523d8c7fc0f5fc9f86ea0f8f01fbc81f7e74112ac2f443bcfb74d472d38368c1a8c971d2433071463961cf1fb786bd2a81c9
@@ -0,0 +1,20 @@
1
+ /vendor
2
+ /.bundle/
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+ *.bundle
12
+ *.so
13
+ *.o
14
+ *.a
15
+ mkmf.log
16
+ *.gem
17
+ Gemfile.lock
18
+ spec/dest
19
+ .bundle
20
+ spec/fixtures/.jekyll-metadata
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
@@ -0,0 +1,29 @@
1
+ inherit_gem:
2
+ jekyll: .rubocop.yml
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.0
6
+ Include:
7
+ - lib/*.rb
8
+
9
+ Exclude:
10
+ - .rubocop.yml
11
+ - .codeclimate.yml
12
+ - .travis.yml
13
+ - .gitignore
14
+ - .rspec
15
+
16
+ - Gemfile.lock
17
+ - CHANGELOG.md
18
+ - readme.md
19
+ - README.md
20
+ - Readme.md
21
+ - ReadMe.md
22
+ - COPYING
23
+ - LICENSE
24
+
25
+ - test/**/*
26
+ - vendor/**/*
27
+ - features/**/*
28
+ - script/**/*
29
+ - spec/**/*
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2
4
+ cache: bundler
5
+ sudo: false
6
+ before_script: bundle update
7
+ script: "./script/cibuild"
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+
4
+ if ENV["JEKYLL_VERSION"]
5
+ gem "jekyll", "~> #{ENV["JEKYLL_VERSION"]}"
6
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2017 Colin Seymour
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,131 @@
1
+ # Jekyll JSON Feed plugin
2
+
3
+ A Jekyll plugin to generate a [JSON feed](https://jsonfeed.org/) of your Jekyll posts.
4
+
5
+ [![Build Status](https://travis-ci.org/lildude/jekyll-json-feed.svg)](https://travis-ci.org/lildude/jekyll-json-feed) [![Gem Version](https://badge.fury.io/rb/jekyll-json-feed.svg)](https://badge.fury.io/rb/jekyll-json-feed)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your site's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'jekyll-json-feed'
13
+ ```
14
+
15
+ And then add this line to your site's `_config.yml`:
16
+
17
+ ```yml
18
+ gems:
19
+ - jekyll-json-feed
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ The plugin will automatically generate a JSON feed at `/feed.json`.
25
+
26
+ ### Optional configuration options
27
+
28
+ The plugin will automatically use any of the following configuration variables, if they are present in your site's `_config.yml` file.
29
+
30
+ * `title` or `name` - The title of the site, e.g., "My awesome site"
31
+ * `description` - A longer description of what your site is about, e.g., "Where I blog about Jekyll and other awesome things"
32
+ * `url` - The URL to your site, e.g., `http://example.com`. If none is provided, the plugin will try to use `site.github.url`.
33
+ * `author` - Global author information (see below)
34
+
35
+ ### Optional front matter
36
+
37
+ The plugin will use the following post metadata, automatically generated by Jekyll, which you can override via a post's YAML front matter:
38
+
39
+ * `date`
40
+ * `title`
41
+ * `excerpt`
42
+ * `id`
43
+ * `tags`
44
+
45
+ Additionally, the plugin will use the following values, if present in a post's YAML front matter:
46
+
47
+ * `image` - URL of an image that is representative of the post (can also be passed as `image.path`)
48
+ * `banner_image` - URL of an image to use as a banner, like those used on Medium
49
+ * `author` - The author of the post, e.g., "Dr. Jekyll". If none is given, feed readers will look to the feed author as defined in `_config.yml`. Like the feed author, this can also be an object or a reference to an author in `_data/authors.yml` (see below).
50
+
51
+ ### Author information
52
+
53
+ *TL;DR: In most cases, put `author: [your name]` in the document's front matter, for sites with multiple authors. If you need something more complicated, read on.*
54
+
55
+ There are several ways to convey author-specific information. Author information is found in the following order of priority:
56
+
57
+ 1. An `author` object, in the documents's front matter, e.g.:
58
+
59
+ ```yml
60
+ author:
61
+ twitter: benbalter
62
+ ```
63
+
64
+ 2. An `author` object, in the site's `_config.yml`, e.g.:
65
+
66
+ ```yml
67
+ author:
68
+ twitter: benbalter
69
+ ```
70
+
71
+ 3. `site.data.authors[author]`, if an author is specified in the document's front matter, and a corresponding key exists in `site.data.authors`. E.g., you have the following in the document's front matter:
72
+
73
+ ```yml
74
+ author: benbalter
75
+ ```
76
+
77
+ And you have the following in `_data/authors.yml`:
78
+
79
+ ```yml
80
+ benbalter:
81
+ picture: /img/benbalter.png
82
+ twitter: jekyllrb
83
+
84
+ potus:
85
+ picture: /img/potus.png
86
+ twitter: whitehouse
87
+ ```
88
+
89
+ In the above example, the author `benbalter`'s Twitter handle will be resolved to `@jekyllrb`. This allows you to centralize author information in a single `_data/authors` file for site with many authors that require more than just the author's username.
90
+
91
+ *Pro-tip: If `authors` is present in the document's front matter as an array (and `author` is not), the plugin will use the first author listed.*
92
+
93
+ 4. An author in the document's front matter (the simplest way), e.g.:
94
+
95
+ ```yml
96
+ author: benbalter
97
+ ```
98
+
99
+ 5. An author in the site's `_config.yml`, e.g.:
100
+
101
+ ```yml
102
+ author: benbalter
103
+ ```
104
+
105
+ ### Meta tags
106
+
107
+ The plugin exposes a helper tag to expose the appropriate meta tags to support automated discovery of your feed. Simply place `{% json_feed_meta %}` someplace in your template's `<head>` section, to output the necessary metadata.
108
+
109
+ ### SmartyPants
110
+
111
+ The plugin uses [Jekyll's `smartify` filter](https://jekyllrb.com/docs/templates/) for processing the site title and post titles. This will translate plain ASCII punctuation into "smart" typographic punctuation. This will not render or strip any Markdown you may be using in a title.
112
+
113
+ ## Why JSON Feed?
114
+
115
+ Great question and I'll leave it to the [spec](https://jsonfeed.org/version/1) to answer:
116
+
117
+ > The JSON Feed format is a pragmatic syndication format, like RSS and Atom, but with one big difference: it’s JSON instead of XML.
118
+ >
119
+ > For most developers, JSON is far easier to read and write than XML. Developers may groan at picking up an XML parser, but decoding JSON is often just a single line of code.
120
+
121
+ ## Credit where credit is due
122
+
123
+ This plugin is heavily inspired by the [Jekyll Feed plugin](https://github.com/jekyll/jekyll-feed) plugin. So much so, that it is a fork with JSON tweaks. Big thanks go to @benbalter for creating the Jekyll Feed plugin, licensing it under the MIT license and making it so easy to create this plugin (it took me an afternoon whilst I was doing other things).
124
+
125
+ ## Contributing
126
+
127
+ 1. Fork it (https://github.com/lildude/jekyll-json-feed/fork)
128
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
129
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
130
+ 4. Push to the branch (`git push origin my-new-feature`)
131
+ 5. Create a new Pull Request
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "jekyll-json-feed"
5
+ spec.version = "1.0.0"
6
+ spec.authors = ["Colin Seymour"]
7
+ spec.email = ["lildood@gmail.com"]
8
+ spec.summary = "A Jekyll plugin to generate a JSON feed of your Jekyll posts"
9
+ spec.homepage = "https://github.com/lildude/jekyll-json-feed"
10
+ spec.license = "MIT"
11
+
12
+ spec.files = `git ls-files -z`.split("\x0")
13
+ spec.executables = spec.files.grep(%r!^bin/!) { |f| File.basename(f) }
14
+ spec.test_files = spec.files.grep(%r!^(test|spec|features)/!)
15
+ spec.require_paths = ["lib"]
16
+
17
+ spec.add_dependency "jekyll", "~> 3.3"
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.6"
20
+ spec.add_development_dependency "rake", "~> 10.0"
21
+ spec.add_development_dependency "rspec", "~> 3.0"
22
+ spec.add_development_dependency "rubocop"
23
+ end
@@ -0,0 +1,10 @@
1
+ require "jekyll"
2
+ require "fileutils"
3
+ require "jekyll-json-feed/generator"
4
+
5
+ module JekyllJsonFeed
6
+ autoload :MetaTag, "jekyll-json-feed/meta-tag"
7
+ autoload :PageWithoutAFile, "jekyll-json-feed/page-without-a-file.rb"
8
+ end
9
+
10
+ Liquid::Template.register_tag "json_feed_meta", JekyllJsonFeed::MetaTag
@@ -0,0 +1,62 @@
1
+ {
2
+ "version": "https://jsonfeed.org/version/1",
3
+ {% if site.title %}
4
+ "title": {{ site.title | smartify | jsonify }},
5
+ {% elsif site.name %}
6
+ "title": {{ site.name | smartify | jsonify }},
7
+ {% endif %}
8
+ {% if site.description %}
9
+ "description": {{ site.description | jsonify }},
10
+ {% endif %}
11
+ "home_page_url": {{ '/' | absolute_url | jsonify }},
12
+ "feed_url": {{ page.url | absolute_url | jsonify }},
13
+ {% if site.author %}
14
+ "author": {
15
+ "name": {{ site.author.name | default: site.author | jsonify }}
16
+ {% if site.author.uri %}
17
+ , "url": {{ site.author.uri | jsonify }}
18
+ {% endif %}
19
+ {% if site.author.avatar %}
20
+ , "avatar": {{ site.author.avatar | jsonify }}
21
+ {% endif %}
22
+ },
23
+ {% endif %}
24
+ "items": [
25
+ {% assign posts = site.posts | where_exp: "post", "post.draft != true" %}
26
+ {% for post in posts limit: 10 %}
27
+ {
28
+ "id": {{ post.id | absolute_url | jsonify }},
29
+ "url": {{ post.url | absolute_url | jsonify }},
30
+ "title": {{ post.title | smartify | strip_html | normalize_whitespace | jsonify }},
31
+ "content_html": {{ post.content | strip | jsonify }},
32
+ {% if post.excerpt and post.excerpt != empty %}
33
+ "summary": {{ post.excerpt | strip_html | normalize_whitespace | jsonify }},
34
+ {% endif %}
35
+ {% assign post_image = post.image.path | default: post.image %}
36
+ {% if post_image %}
37
+ {% unless post_image contains "://" %}
38
+ {% assign post_image = post_image | absolute_url | xml_escape %}
39
+ {% endunless %}
40
+ "image": {{ post_image | jsonify }},
41
+ {% endif %}
42
+ {% assign post_banner_image = post.banner_image.path | default: post.banner_image %}
43
+ {% if post_banner_image %}
44
+ "banner_image": {{ post_banner_image | jsonify }},
45
+ {% endif %}
46
+ "date_published": "{{ post.date | date_to_xmlschema }}",
47
+ "date_modified": "{{ post.last_modified_at | default: post.date | date_to_xmlschema }}",
48
+ {% assign post_author = post.author | default: post.authors[0] | default: site.author %}
49
+ {% assign post_author = site.data.authors[post_author] | default: post_author %}
50
+ {% assign post_author_uri = post_author.uri | default: nil %}
51
+ {% assign post_author_name = post_author.name | default: post_author %}
52
+ "author": {
53
+ "name": {{ post_author_name | default: "" | jsonify }}
54
+ {% if post_author_uri != nil %}
55
+ , "url": {{ post_author_uri | jsonify }}
56
+ {% endif %}
57
+ },
58
+ "tags": {{ post.tags | jsonify }}
59
+ }{% unless forloop.last == true %},{% endunless %}
60
+ {% endfor %}
61
+ ]
62
+ }
@@ -0,0 +1,54 @@
1
+ module JekyllJsonFeed
2
+ class Generator < Jekyll::Generator
3
+ safe true
4
+ priority :lowest
5
+
6
+ # Main plugin action, called by Jekyll-core
7
+ def generate(site)
8
+ @site = site
9
+ return if file_exists?(feed_path)
10
+ @site.pages << content_for_file(feed_path, feed_source_path)
11
+ end
12
+
13
+ private
14
+
15
+ # Matches all whitespace that follows
16
+ # 1. A '>', which closes an XML tag or
17
+ # 2. A '}', which closes a Liquid tag
18
+ # We will strip all of this whitespace to minify the template
19
+ MINIFY_REGEX = %r!(?<=>|})\s+!
20
+
21
+ # Path to feed from config, or feed.json for default
22
+ def feed_path
23
+ if @site.config["json_feed"] && @site.config["json_feed"]["path"]
24
+ @site.config["json_feed"]["path"]
25
+ else
26
+ "feed.json"
27
+ end
28
+ end
29
+
30
+ # Path to feed.json template file
31
+ def feed_source_path
32
+ File.expand_path "./feed.json", File.dirname(__FILE__)
33
+ end
34
+
35
+ # Checks if a file already exists in the site source
36
+ def file_exists?(file_path)
37
+ if @site.respond_to?(:in_source_dir)
38
+ File.exist? @site.in_source_dir(file_path)
39
+ else
40
+ File.exist? Jekyll.sanitized_path(@site.source, file_path)
41
+ end
42
+ end
43
+
44
+ # Generates contents for a file
45
+ def content_for_file(file_path, file_source_path)
46
+ file = PageWithoutAFile.new(@site, File.dirname(__FILE__), "", file_path)
47
+ file.content = File.read(file_source_path).gsub(MINIFY_REGEX, "")
48
+ file.data["layout"] = nil
49
+ file.data["sitemap"] = false
50
+ file.output
51
+ file
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,39 @@
1
+ module JekyllJsonFeed
2
+ class MetaTag < Liquid::Tag
3
+ # Use Jekyll's native relative_url filter
4
+ include Jekyll::Filters::URLFilters
5
+
6
+ def render(context)
7
+ @context = context
8
+ attrs = attributes.map { |k, v| %(#{k}="#{v}") }.join(" ")
9
+ "<link #{attrs} />"
10
+ end
11
+
12
+ private
13
+
14
+ def config
15
+ @context.registers[:site].config
16
+ end
17
+
18
+ def attributes
19
+ {
20
+ :type => "application/json",
21
+ :rel => "alternate",
22
+ :href => absolute_url(path),
23
+ :title => title,
24
+ }.keep_if { |_, v| v }
25
+ end
26
+
27
+ def path
28
+ if config["json_feed"] && config["json_feed"]["path"]
29
+ config["json_feed"]["path"]
30
+ else
31
+ "feed.json"
32
+ end
33
+ end
34
+
35
+ def title
36
+ config["title"] || config["name"]
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,7 @@
1
+ module JekyllJsonFeed
2
+ class PageWithoutAFile < Jekyll::Page
3
+ def read_yaml(*)
4
+ @data ||= {}
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ #! /bin/bash
2
+
3
+ bundle install
@@ -0,0 +1,7 @@
1
+ #! /bin/bash
2
+
3
+ set -e
4
+
5
+ bundle exec rspec
6
+ bundle exec rubocop -S -D
7
+ bundle exec rake build
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+ # Tag and push a release.
3
+
4
+ set -e
5
+
6
+ script/cibuild
7
+ bundle exec rake release
@@ -0,0 +1,9 @@
1
+ timezone: UTC
2
+
3
+ defaults:
4
+ -
5
+ scope:
6
+ path: ""
7
+ type: page
8
+ values:
9
+ layout: some_default
@@ -0,0 +1,6 @@
1
+ garthdb:
2
+ name: Garth
3
+ twitter: garthdb
4
+ uri: "http://garthdb.com"
5
+ email: example@mail.com
6
+ avatar: "http://garthdb.com/avatar.png"
@@ -0,0 +1,4 @@
1
+ ---
2
+ ---
3
+
4
+ This is a draft.
@@ -0,0 +1,11 @@
1
+ ---
2
+ ---
3
+ <html>
4
+ <head>
5
+ {% feed_meta %}
6
+ </head>
7
+ <body>
8
+ THIS IS MY LAYOUT
9
+ {{ content }}
10
+ </body>
11
+ </html>
@@ -0,0 +1,6 @@
1
+ ---
2
+ excerpt: "Foo"
3
+ image: "/image.png"
4
+ ---
5
+
6
+ # December the twelfth, actually.
@@ -0,0 +1,5 @@
1
+ ---
2
+ image: "https://cdn.example.org/absolute.png"
3
+ ---
4
+
5
+ March the second!
@@ -0,0 +1,9 @@
1
+ ---
2
+ tags:
3
+ - '"/><VADER>'
4
+ - foobar
5
+ image:
6
+ path: "/object-image.png"
7
+ ---
8
+
9
+ March the fourth!
@@ -0,0 +1,5 @@
1
+ ---
2
+ last_modified_at: 2015-05-12T13:27:59+00:00
3
+ ---
4
+
5
+ Please don't modify this file. It's modified time is important.
@@ -0,0 +1,6 @@
1
+ ---
2
+ title:
3
+ The plugin
4
+ will properly
5
+ strip newlines.
6
+ ---
@@ -0,0 +1,7 @@
1
+ ---
2
+ ---
3
+
4
+ {% capture liquidstring %}
5
+ Liquid is not rendered.
6
+ {% endcapture %}
7
+ {{ liquidstring | replace:'not ','' }}
@@ -0,0 +1,8 @@
1
+ ---
2
+ author: Pat
3
+ lang: en
4
+ ---
5
+
6
+ <pre>Line 1
7
+ Line 2
8
+ Line 3</pre>
@@ -0,0 +1,10 @@
1
+ ---
2
+ excerpt: ""
3
+ author:
4
+ name: Ben
5
+ uri: "http://ben.balter.com"
6
+ email: ben@example.com
7
+ avatar: "http://ben.balter.com/avatar.png"
8
+ ---
9
+
10
+ # December the twelfth, actually.
@@ -0,0 +1,6 @@
1
+ ---
2
+ excerpt: ""
3
+ author: garthdb
4
+ ---
5
+
6
+ # April the twenty-fifth?
@@ -0,0 +1,230 @@
1
+ require 'spec_helper'
2
+
3
+ describe(JekyllJsonFeed) do
4
+ let(:overrides) { Hash.new }
5
+ let(:config) do
6
+ Jekyll.configuration(Jekyll::Utils.deep_merge_hashes({
7
+ "full_rebuild" => true,
8
+ "source" => source_dir,
9
+ "destination" => dest_dir,
10
+ "show_drafts" => true,
11
+ "url" => "http://example.org",
12
+ "name" => "My awesome site",
13
+ "author" => {
14
+ "name" => "Dr. Jekyll",
15
+ "url" => "http://example.org/dr_jekyll",
16
+ "avatar" => "http://example.org/dr_jekyll/avatar.png"
17
+ },
18
+ "collections" => {
19
+ "my_collection" => { "output" => true },
20
+ "other_things" => { "output" => false }
21
+ }
22
+ }, overrides))
23
+ end
24
+ let(:site) { Jekyll::Site.new(config) }
25
+ let(:contents) { File.read(dest_dir("feed.json")) }
26
+ let(:context) { make_context(site: site) }
27
+ let(:json_feed_meta) { Liquid::Template.parse("{% json_feed_meta %}").render!(context, {}) }
28
+ before(:each) do
29
+ site.process
30
+ end
31
+
32
+ it "has no layout" do
33
+ expect(contents).not_to match(/\ATHIS IS MY LAYOUT/)
34
+ end
35
+
36
+ it "creates a feed.json file" do
37
+ expect(Pathname.new(dest_dir("feed.json"))).to exist
38
+ end
39
+
40
+
41
+ it "doesn't have multiple new lines or trailing whitespace" do
42
+ expect(contents).to_not match /\s+\n/
43
+ expect(contents).to_not match /\n{2,}/
44
+ end
45
+
46
+ it "puts all the posts in the feed.json file" do
47
+ expect(contents).to match /http:\/\/example\.org\/2014\/03\/04\/march-the-fourth\.html/
48
+ expect(contents).to match /http:\/\/example\.org\/2014\/03\/02\/march-the-second\.html/
49
+ expect(contents).to match /http:\/\/example\.org\/2013\/12\/12\/dec-the-second\.html/
50
+ expect(contents).to match "http://example.org/2015/08/08/stuck-in-the-middle.html"
51
+ expect(contents).to_not match /http:\/\/example\.org\/2016\/02\/09\/a-draft\.html/
52
+ end
53
+
54
+ it "does not include assets or any static files that aren't .html" do
55
+ expect(contents).not_to match /http:\/\/example\.org\/images\/hubot\.png/
56
+ expect(contents).not_to match /http:\/\/example\.org\/feeds\/atom\.xml/
57
+ end
58
+
59
+ it "preserves linebreaks in preformatted text in posts" do
60
+ expect(contents).to match /Line 1\\nLine 2\\nLine 3/
61
+ end
62
+
63
+ it "supports post author name as an object" do
64
+ expect(contents).to match %r!"author":\s*{\s*"name":\s*"Ben",\s*"url":\s*"http://ben.balter.com"\s*}!
65
+ end
66
+
67
+ it "supports post author name as a string" do
68
+ expect(contents).to match %r!"author":\s*{\s*"name":\s*"Pat"\s*}!
69
+ end
70
+
71
+ it "does not output author tag no author is provided" do
72
+ expect(contents).not_to match %r{"author":\s*{\s*}}
73
+ end
74
+
75
+ it "does use author reference with data from _data/authors.yml" do
76
+ expect(contents).to match %r!"author":\s*{\s*"name": "Garth",\s*"url":\s*"http://garthdb.com"\s*}!
77
+ end
78
+
79
+ it "converts markdown posts to HTML" do
80
+ expect(contents).to match %r{<p>March the second!</p>}
81
+ end
82
+
83
+ it "uses last_modified_at where available" do
84
+ expect(contents).to match %r{"date_modified": "2015-05-12T13:27:59\+00:00"}
85
+ end
86
+
87
+ it "replaces newlines in posts to spaces" do
88
+ expect(contents).to match %r!"title": "The plugin will properly strip newlines."!
89
+ end
90
+
91
+ it "renders Liquid inside posts" do
92
+ expect(contents).to match /Liquid is rendered\./
93
+ expect(contents).not_to match /Liquid is not rendered\./
94
+ end
95
+
96
+ it "includes the item image" do
97
+ expect(contents).to include('"image": "http://example.org/image.png"')
98
+ expect(contents).to include('"image": "https://cdn.example.org/absolute.png"')
99
+ expect(contents).to include('"image": "http://example.org/object-image.png"')
100
+ end
101
+
102
+ context "parsing" do
103
+ let(:feed) { JSON.parse(contents) }
104
+
105
+ it "outputs a JSON feed" do
106
+ expect(feed['version']).to eql("https://jsonfeed.org/version/1")
107
+ end
108
+
109
+ it "outputs the link" do
110
+ expect(feed['feed_url']).to eql("http://example.org/feed.json")
111
+ end
112
+
113
+ it "includes the items" do
114
+ expect(feed['items'].count).to eql(10)
115
+ end
116
+
117
+ it "includes item contents" do
118
+ post = feed['items'].last
119
+ expect(post['title']).to eql("Dec The Second")
120
+ expect(post['url']).to eql("http://example.org/2013/12/12/dec-the-second.html")
121
+ expect(post['date_published']).to eql(Time.parse("2013-12-12").iso8601)
122
+ end
123
+
124
+ it "includes the item's excerpt" do
125
+ post = feed['items'].last
126
+ expect(post['summary']).to eql("Foo")
127
+ end
128
+
129
+ it "doesn't include the item's excerpt if blank" do
130
+ post = feed['items'].first
131
+ expect(post['summary']).to be_nil
132
+ end
133
+
134
+ context "with site.title set" do
135
+ let(:site_title) { "My Site Title" }
136
+ let(:overrides) { {"title" => site_title} }
137
+
138
+ it "uses site.title for the title" do
139
+ expect(feed['title']).to eql(site_title)
140
+ end
141
+ end
142
+
143
+ context "with site.name set" do
144
+ let(:site_name) { "My Site Name" }
145
+ let(:overrides) { {"name" => site_name} }
146
+
147
+ it "uses site.name for the title" do
148
+ expect(feed['title']).to eql(site_name)
149
+ end
150
+ end
151
+
152
+ context "with site.name and site.title set" do
153
+ let(:site_title) { "My Site Title" }
154
+ let(:site_name) { "My Site Name" }
155
+ let(:overrides) { {"title" => site_title, "name" => site_name} }
156
+
157
+ it "uses site.title for the title, dropping site.name" do
158
+ expect(feed['title']).to eql(site_title)
159
+ end
160
+ end
161
+ end
162
+
163
+ context "smartify" do
164
+ let(:site_title) { "Pat's Site" }
165
+ let(:overrides) { { "title" => site_title } }
166
+ let(:feed) { JSON.parse(contents) }
167
+
168
+ it "processes site title with SmartyPants" do
169
+ expect(feed['title']).to eql("Pat’s Site")
170
+ end
171
+ end
172
+
173
+ context "with a baseurl" do
174
+ let(:overrides) do
175
+ { "baseurl" => "/bass" }
176
+ end
177
+
178
+ it "correctly adds the baseurl to the posts" do
179
+ expect(contents).to match /http:\/\/example\.org\/bass\/2014\/03\/04\/march-the-fourth\.html/
180
+ expect(contents).to match /http:\/\/example\.org\/bass\/2014\/03\/02\/march-the-second\.html/
181
+ expect(contents).to match /http:\/\/example\.org\/bass\/2013\/12\/12\/dec-the-second\.html/
182
+ end
183
+
184
+ it "renders the feed meta" do
185
+ expected = 'href="http://example.org/bass/feed.json"'
186
+ expect(json_feed_meta).to include(expected)
187
+ end
188
+ end
189
+
190
+ context "feed meta" do
191
+ it "renders the feed meta" do
192
+ expected = '<link type="application/json" rel="alternate" href="http://example.org/feed.json" title="My awesome site" />'
193
+ expect(json_feed_meta).to eql(expected)
194
+ end
195
+
196
+ context "with a blank site name" do
197
+ let(:config) do
198
+ Jekyll.configuration({
199
+ "source" => source_dir,
200
+ "destination" => dest_dir,
201
+ "url" => "http://example.org"
202
+ })
203
+ end
204
+
205
+ it "does not output blank title" do
206
+ expect(json_feed_meta).not_to include('title=')
207
+ end
208
+ end
209
+ end
210
+
211
+ context "changing the feed path" do
212
+ let(:overrides) do
213
+ {
214
+ "json_feed" => {
215
+ "path" => "atom.json"
216
+ }
217
+ }
218
+ end
219
+
220
+ it "should write to atom.json" do
221
+ expect(Pathname.new(dest_dir("atom.json"))).to exist
222
+ end
223
+
224
+ it "renders the feed meta with custom feed path" do
225
+ expected = 'href="http://example.org/atom.json"'
226
+ expect(json_feed_meta).to include(expected)
227
+ end
228
+ end
229
+
230
+ end
@@ -0,0 +1,25 @@
1
+ require 'jekyll'
2
+ require File.expand_path('../lib/jekyll-json-feed', File.dirname(__FILE__))
3
+
4
+ Jekyll.logger.log_level = :error
5
+
6
+ RSpec.configure do |config|
7
+ config.run_all_when_everything_filtered = true
8
+ config.filter_run :focus
9
+ config.order = 'random'
10
+
11
+ SOURCE_DIR = File.expand_path("../fixtures", __FILE__)
12
+ DEST_DIR = File.expand_path("../dest", __FILE__)
13
+
14
+ def source_dir(*files)
15
+ File.join(SOURCE_DIR, *files)
16
+ end
17
+
18
+ def dest_dir(*files)
19
+ File.join(DEST_DIR, *files)
20
+ end
21
+
22
+ def make_context(registers = {})
23
+ Liquid::Context.new({}, {}, { site: site }.merge(registers))
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jekyll-json-feed
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Colin Seymour
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description:
84
+ email:
85
+ - lildood@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".rubocop.yml"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - jekyll-json-feed.gemspec
99
+ - lib/jekyll-json-feed.rb
100
+ - lib/jekyll-json-feed/feed.json
101
+ - lib/jekyll-json-feed/generator.rb
102
+ - lib/jekyll-json-feed/meta-tag.rb
103
+ - lib/jekyll-json-feed/page-without-a-file.rb
104
+ - script/bootstrap
105
+ - script/cibuild
106
+ - script/release
107
+ - spec/fixtures/_config.yml
108
+ - spec/fixtures/_data/authors.yml
109
+ - spec/fixtures/_drafts/2015-01-12-a-draft.md
110
+ - spec/fixtures/_layouts/some_default.html
111
+ - spec/fixtures/_posts/2013-12-12-dec-the-second.md
112
+ - spec/fixtures/_posts/2014-03-02-march-the-second.md
113
+ - spec/fixtures/_posts/2014-03-04-march-the-fourth.md
114
+ - spec/fixtures/_posts/2015-01-18-jekyll-last-modified-at.md
115
+ - spec/fixtures/_posts/2015-02-12-strip-newlines.md
116
+ - spec/fixtures/_posts/2015-05-12-liquid.md
117
+ - spec/fixtures/_posts/2015-05-12-pre.html
118
+ - spec/fixtures/_posts/2015-05-18-author-detail.md
119
+ - spec/fixtures/_posts/2015-08-08-stuck-in-the-middle.html
120
+ - spec/fixtures/_posts/2016-04-25-author-reference.md
121
+ - spec/jekyll-json-feed_spec.rb
122
+ - spec/spec_helper.rb
123
+ homepage: https://github.com/lildude/jekyll-json-feed
124
+ licenses:
125
+ - MIT
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project:
143
+ rubygems_version: 2.6.8
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: A Jekyll plugin to generate a JSON feed of your Jekyll posts
147
+ test_files:
148
+ - spec/fixtures/_config.yml
149
+ - spec/fixtures/_data/authors.yml
150
+ - spec/fixtures/_drafts/2015-01-12-a-draft.md
151
+ - spec/fixtures/_layouts/some_default.html
152
+ - spec/fixtures/_posts/2013-12-12-dec-the-second.md
153
+ - spec/fixtures/_posts/2014-03-02-march-the-second.md
154
+ - spec/fixtures/_posts/2014-03-04-march-the-fourth.md
155
+ - spec/fixtures/_posts/2015-01-18-jekyll-last-modified-at.md
156
+ - spec/fixtures/_posts/2015-02-12-strip-newlines.md
157
+ - spec/fixtures/_posts/2015-05-12-liquid.md
158
+ - spec/fixtures/_posts/2015-05-12-pre.html
159
+ - spec/fixtures/_posts/2015-05-18-author-detail.md
160
+ - spec/fixtures/_posts/2015-08-08-stuck-in-the-middle.html
161
+ - spec/fixtures/_posts/2016-04-25-author-reference.md
162
+ - spec/jekyll-json-feed_spec.rb
163
+ - spec/spec_helper.rb