diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1f40a44 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +spec/examples.txt +_site +*.gem +Gemfile.lock diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..83e16f8 --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--color +--require spec_helper diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..6ea3ca8 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,6 @@ +inherit_gem: + jekyll: .rubocop.yml + +AllCops: + Exclude: + - vendor/**/* diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..be3bd52 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +rvm: + - 2.2 +before_install: gem install bundler +language: ruby +script: script/cibuild +sudo: false +cache: bundler diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..fa75df1 --- /dev/null +++ b/Gemfile @@ -0,0 +1,3 @@ +source 'https://rubygems.org' + +gemspec diff --git a/README.md b/README.md new file mode 100644 index 0000000..20060f0 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# Jekyll Optional Front Matter + +A Jekyll plugin to make front matter optional for Markdown files + +## What it does + +Out of the box, Jekyll requires that any markdown file have YAML front matter (key/value pairs separated by two sets of three dashes) in order to be processed and converted to HTML. + +While that behavior may be helpful for large, complex sites, sometimes it's easier to simply add a plain markdown file and have it render without fanfare. + +This plugin does just that. Any Markdown file in your site's source will be treated as a Page and rendered as HTML, even if it doesn't have YAML front matter. + +## Usage + +1. Add the following to your site's Gemfile: + + ```ruby + gem 'jekyll-optional-front-matter' + ``` + +2. Add the following to your site's config file: + + ```yml + gems: + - jekyll-optional-front-matter + ``` + +## Disabling + +Even if the plugin is enabled (e.g., via the `:jekyll_plugins` group in your Gemfile) you can disable it by adding the following to your site's config: + +```yml +require_front_matter: true +``` diff --git a/jekyll-optional-front-matter.gemspec b/jekyll-optional-front-matter.gemspec new file mode 100644 index 0000000..343a6d3 --- /dev/null +++ b/jekyll-optional-front-matter.gemspec @@ -0,0 +1,22 @@ +# encoding: utf-8 + +$:.unshift File.expand_path('../lib', __FILE__) +require 'jekyll-optional-front-matter/version' + +Gem::Specification.new do |s| + s.name = "jekyll-optional-front-matter" + s.version = JekyllOptionalFrontMatter::VERSION + s.authors = ["Ben Balter"] + s.email = ["ben.balter@github.com"] + s.homepage = "https://github.com/benbalter/jekyll-optional-front-matter" + s.summary = "A Jekyll plugin to make front matter optional for Markdown files" + + s.files = `git ls-files app lib`.split("\n") + s.platform = Gem::Platform::RUBY + s.require_paths = ['lib'] + s.license = "MIT" + + s.add_runtime_dependency "jekyll", "~> 3.0" + s.add_development_dependency "rspec", "~> 3.5" + s.add_development_dependency "rubocop", "~> 0.40" +end diff --git a/lib/jekyll-optional-front-matter.rb b/lib/jekyll-optional-front-matter.rb new file mode 100644 index 0000000..c5ae745 --- /dev/null +++ b/lib/jekyll-optional-front-matter.rb @@ -0,0 +1,5 @@ +require "jekyll" + +module JekyllOptionalFrontMatter + autoload :Generator, "jekyll-optional-front-matter/generator" +end diff --git a/lib/jekyll-optional-front-matter/generator.rb b/lib/jekyll-optional-front-matter/generator.rb new file mode 100644 index 0000000..5eaea16 --- /dev/null +++ b/lib/jekyll-optional-front-matter/generator.rb @@ -0,0 +1,39 @@ +module JekyllOptionalFrontMatter + class Generator < Jekyll::Generator + attr_accessor :site + + safe :true + priority :low + + def initialize(site) + @site = site + end + + def generate(site) + @site = site + return if site.config["require_front_matter"] + site.pages.concat(pages) + end + + private + + def pages + markdown_files.map { |static_file| page_from_static_file(static_file) } + end + + def page_from_static_file(static_file) + base = static_file.instance_variable_get("@base") + dir = static_file.instance_variable_get("@dir") + name = static_file.instance_variable_get("@name") + Jekyll::Page.new(site, base, dir, name) + end + + def markdown_files + site.static_files.select { |f| markdown_converter.matches(f.extname) } + end + + def markdown_converter + site.find_converter_instance(Jekyll::Converters::Markdown) + end + end +end diff --git a/lib/jekyll-optional-front-matter/version.rb b/lib/jekyll-optional-front-matter/version.rb new file mode 100644 index 0000000..7c97df6 --- /dev/null +++ b/lib/jekyll-optional-front-matter/version.rb @@ -0,0 +1,3 @@ +module JekyllOptionalFrontMatter + VERSION = "0.0.1".freeze +end diff --git a/script/bootstrap b/script/bootstrap new file mode 100755 index 0000000..ff2a795 --- /dev/null +++ b/script/bootstrap @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e + +bundle install diff --git a/script/cibuild b/script/cibuild new file mode 100755 index 0000000..665b3d7 --- /dev/null +++ b/script/cibuild @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +bundle exec rspec +bundle exec rubocop -S -D +bundle exec gem build jekyll-optional-front-matter.gemspec diff --git a/spec/fixtures/site/another-file.markdown b/spec/fixtures/site/another-file.markdown new file mode 100644 index 0000000..f60114d --- /dev/null +++ b/spec/fixtures/site/another-file.markdown @@ -0,0 +1 @@ +# Another file diff --git a/spec/fixtures/site/index.md b/spec/fixtures/site/index.md new file mode 100644 index 0000000..dcbcd8b --- /dev/null +++ b/spec/fixtures/site/index.md @@ -0,0 +1,5 @@ +--- +permalink: / +--- + +# Index diff --git a/spec/fixtures/site/readme.md b/spec/fixtures/site/readme.md new file mode 100644 index 0000000..f395431 --- /dev/null +++ b/spec/fixtures/site/readme.md @@ -0,0 +1 @@ +# Readme diff --git a/spec/jekyll-optional-front-matter/generator_spec.rb b/spec/jekyll-optional-front-matter/generator_spec.rb new file mode 100644 index 0000000..d3a2b2e --- /dev/null +++ b/spec/jekyll-optional-front-matter/generator_spec.rb @@ -0,0 +1,72 @@ +describe JekyllOptionalFrontMatter::Generator do + let(:site) { fixture_site("site") } + let(:generator) { described_class.new(site) } + let(:markdown_converter) { generator.send(:markdown_converter) } + let(:markdown_files) { generator.send(:markdown_files) } + let(:pages) { generator.send(:pages) } + + before do + site.reset + site.read + end + + it "grabs the markdown converter" do + expect(markdown_converter.class).to eql(Jekyll::Converters::Markdown) + end + + it "grabs the markdown files" do + expect(markdown_files.count).to eql(2) + paths = markdown_files.map(&:relative_path) + expect(paths).to include("/readme.md") + expect(paths).to include("/another-file.markdown") + end + + it "builds a page from a static file" do + static_file = Jekyll::StaticFile.new(site, site.source, "/", "readme.md") + page = generator.send(:page_from_static_file, static_file) + expect(page.class).to eql(Jekyll::Page) + expect(page.name).to eql("readme.md") + expect(page.content).to eql("# Readme\n") + end + + it "builds the array of pages" do + expect(pages.count).to eql(2) + names = pages.map(&:name) + expect(names).to include("readme.md") + expect(names).to include("another-file.markdown") + end + + context "generating" do + before { generator.generate(site) } + + it "adds the pages to the site" do + expect(site.pages.count).to eql(3) + names = site.pages.map(&:name) + expect(names).to include("readme.md") + expect(names).to include("another-file.markdown") + expect(names).to include("index.md") + end + end + + context "when disabled" do + let(:site) { fixture_site("site", { "require_front_matter" => true }) } + context "generating" do + before { generator.generate(site) } + + it "doesn't add the pages to the site" do + expect(site.pages.count).to eql(1) + end + end + end + + context "when explicitly enabled" do + let(:site) { fixture_site("site", { "require_front_matter" => false }) } + context "generating" do + before { generator.generate(site) } + + it "doesn't add the pages to the site" do + expect(site.pages.count).to eql(3) + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..9398676 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,36 @@ +require "jekyll-optional-front-matter" + +RSpec.configure do |config| + config.expect_with :rspec do |expectations| + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end + + config.shared_context_metadata_behavior = :apply_to_host_groups + config.example_status_persistence_file_path = "spec/examples.txt" + + if config.files_to_run.one? + config.default_formatter = "doc" + end + + config.order = :random + Kernel.srand config.seed +end + +def fixture_path(fixture) + File.expand_path "./fixtures/#{fixture}", File.dirname(__FILE__) +end + +def fixture_site(fixture, override = {}) + default_config = { "source" => fixture_path(fixture) } + config = Jekyll::Utils.deep_merge_hashes(default_config, override) + config = Jekyll.configuration(config) + Jekyll::Site.new(config) +end + +RSpec::Matchers.define :be_an_existing_file do + match { |path| File.exist?(path) } +end