From e3df910533eeb808325a326d0bd1a79f9cd31c4f Mon Sep 17 00:00:00 2001 From: Parker Moore Date: Mon, 16 May 2016 09:07:22 -0700 Subject: [PATCH] Add more template files and add a ThemeBuilder which can create the site --- lib/jekyll.rb | 1 + lib/jekyll/commands/new_theme.rb | 96 ++++++----------------- lib/jekyll/theme_builder.rb | 108 ++++++++++++++++++++++++++ lib/theme_template/CODE_OF_CONDUCT.md | 0 lib/theme_template/Gemfile | 2 + lib/theme_template/LICENSE.txt.erb | 21 +++++ lib/theme_template/README.md | 0 lib/theme_template/theme.gemspec.erb | 21 +++++ 8 files changed, 175 insertions(+), 74 deletions(-) create mode 100644 lib/jekyll/theme_builder.rb create mode 100644 lib/theme_template/CODE_OF_CONDUCT.md create mode 100644 lib/theme_template/Gemfile create mode 100644 lib/theme_template/LICENSE.txt.erb create mode 100644 lib/theme_template/README.md create mode 100644 lib/theme_template/theme.gemspec.erb diff --git a/lib/jekyll.rb b/lib/jekyll.rb index ffc1539f..e9f4547b 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -68,6 +68,7 @@ module Jekyll autoload :StaticFile, 'jekyll/static_file' autoload :Stevenson, 'jekyll/stevenson' autoload :Theme, 'jekyll/theme' + autoload :ThemeBuilder, 'jekyll/theme_builder' autoload :URL, 'jekyll/url' autoload :Utils, 'jekyll/utils' autoload :VERSION, 'jekyll/version' diff --git a/lib/jekyll/commands/new_theme.rb b/lib/jekyll/commands/new_theme.rb index 3e37bd84..3855c3f8 100644 --- a/lib/jekyll/commands/new_theme.rb +++ b/lib/jekyll/commands/new_theme.rb @@ -1,82 +1,30 @@ require 'erb' -module Jekyll - module Commands - class NewTheme < Command - class << self - def init_with_program(prog) - prog.command(:"new-theme") do |c| - c.syntax 'new-theme NAME' - c.description 'Creates a new Jekyll theme scaffold' +class Jekyll::Commands::NewTheme < Jekyll::Command + class << self + def init_with_program(prog) + prog.command(:"new-theme") do |c| + c.syntax 'new-theme NAME' + c.description 'Creates a new Jekyll theme scaffold' - c.action do |args, _| - Jekyll::Commands::NewTheme.process(args) - end - end - end - - def process(args) - raise InvalidThemeName, 'You must specify a theme name.' if args.empty? - - new_theme_name = args.join("_") - theme = ThemeBuilder.new(new_theme_name) - if theme.path.exist? - Jekyll.logger.abort_with "Conflict:", "#{theme.path} already exists." - end - - theme.create! - Jekyll.logger.info "Your new Jekyll theme, #{theme.name} is ready for you in #{theme.path}." - end - - class ThemeBuilder - attr_reader :name, :path - def initialize(theme_name) - @name = theme_name - @path = Pathname.new(File.expand_path(theme_name, Dir.pwd)) - end - - def create! - create_directories - create_gemspec - create_readme - end - - private - - def create_directories - Dir.chdir(path) do - FileUtils.mkdir_p(%w{_includes _layouts _sass}) - end - end - end - - private - - def gemfile_contents - <<-RUBY -source "https://rubygems.org" - -# Hello! This is where you manage which Jekyll version is used to run. -# When you want to use a different version, change it below, save the -# file and run `bundle install`. Run Jekyll with `bundle exec`, like so: -# -# bundle exec jekyll serve -# -# This will help ensure the proper Jekyll version is running. -# Happy Jekylling! -gem "jekyll", "#{Jekyll::VERSION}" - -# If you want to use GitHub Pages, remove the "gem "jekyll"" above and -# uncomment the line below. To upgrade, run `bundle update github-pages`. -# gem "github-pages", group: :jekyll_plugins - -# If you have any plugins, put them here! -# group :jekyll_plugins do -# gem "jekyll-github-metadata", "~> 1.0" -# end -RUBY + c.action do |args, _| + Jekyll::Commands::NewTheme.process(args) end end end + + def process(args) + raise InvalidThemeName, 'You must specify a theme name.' if args.empty? + + new_theme_name = args.join("_") + theme = Jekyll::ThemeBuilder.new(new_theme_name) + if theme.path.exist? + Jekyll.logger.abort_with "Conflict:", "#{theme.path} already exists." + end + + theme.create! + Jekyll.logger.info "Your new Jekyll theme, #{theme.name}, is ready for you in #{theme.path}!" + Jekyll.logger.info "For help getting started, read #{theme.path}/README.md." + end end end diff --git a/lib/jekyll/theme_builder.rb b/lib/jekyll/theme_builder.rb new file mode 100644 index 00000000..8b352865 --- /dev/null +++ b/lib/jekyll/theme_builder.rb @@ -0,0 +1,108 @@ +class Jekyll::ThemeBuilder + SCAFFOLD_DIRECTORIES = %w{ + _layouts _includes _sass + }.freeze + + attr_reader :name, :path + + def initialize(theme_name) + @name = theme_name.to_s.gsub(/ /, "_").gsub(/_+/, "_") + @path = Pathname.new(File.expand_path(name, Dir.pwd)) + end + + def create! + create_directories + create_gemspec + create_accessories + initialize_git_repo + end + + private + + def root + @root ||= Pathname.new(File.expand_path("../", __dir__)) + end + + def template_file(filename) + [ + root.join("theme_template", "#{filename}.erb"), + root.join("theme_template", "#{filename}") + ].find do |pathname| + pathname.exist? + end + end + + def template(filename) + erb.render(template_file(filename).read) + end + + def erb + @erb ||= ERBRenderer.new(self) + end + + def mkdir_p(directories) + Array(directories).each do |directory| + full_path = path.join(directory) + Jekyll.logger.info "create", "#{full_path}" + FileUtils.mkdir_p(full_path) + end + end + + def write_file(filename, contents) + full_path = path.join(filename) + Jekyll.logger.info "create", "#{full_path}" + File.write(full_path, contents) + end + + def create_directories + mkdir_p(SCAFFOLD_DIRECTORIES) + end + + def create_gemspec + write_file("Gemfile", template("Gemfile")) + write_file("#{name}.gemspec", template("theme.gemspec")) + end + + def create_accessories + %w{README.md CODE_OF_CONDUCT.md LICENSE.txt}.each do |filename| + write_file(filename, template(filename)) + end + end + + def initialize_git_repo + Jekyll.logger.info "initialize", "#{path.join(".git")}" + Dir.chdir(path.to_s) { `git init` } + end + + def user_name + @user_name ||= `git config user.name`.chomp + end + + def user_email + @user_email ||= `git config user.email`.chomp + end + + class ERBRenderer + extend Forwardable + + def_delegator :@theme_builder, :name, :theme_name + def_delegator :@theme_builder, :user_name, :user_name + def_delegator :@theme_builder, :user_email, :user_email + + def initialize(theme_builder) + @theme_builder = theme_builder + end + + def jekyll_pessimistic_version + Jekyll::VERSION.split(".").take(2).join(".") + end + + def theme_directories + SCAFFOLD_DIRECTORIES + end + + def render(contents) + ERB.new(contents).result binding + end + end +end diff --git a/lib/theme_template/CODE_OF_CONDUCT.md b/lib/theme_template/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..e69de29b diff --git a/lib/theme_template/Gemfile b/lib/theme_template/Gemfile new file mode 100644 index 00000000..3be9c3cd --- /dev/null +++ b/lib/theme_template/Gemfile @@ -0,0 +1,2 @@ +source "https://rubygems.org" +gemspec diff --git a/lib/theme_template/LICENSE.txt.erb b/lib/theme_template/LICENSE.txt.erb new file mode 100644 index 00000000..df803135 --- /dev/null +++ b/lib/theme_template/LICENSE.txt.erb @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 <%= user_name %> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/lib/theme_template/README.md b/lib/theme_template/README.md new file mode 100644 index 00000000..e69de29b diff --git a/lib/theme_template/theme.gemspec.erb b/lib/theme_template/theme.gemspec.erb new file mode 100644 index 00000000..507a7c52 --- /dev/null +++ b/lib/theme_template/theme.gemspec.erb @@ -0,0 +1,21 @@ +# coding: utf-8 + +Gem::Specification.new do |spec| + spec.name = <%= theme_name.inspect %> + spec.version = "0.1.0" + spec.authors = [<%= user_name.inspect %>] + spec.email = [<%= user_email.inspect %>] + + spec.summary = %q{TODO: Write a short summary, because Rubygems requires one.} + spec.description = %q{TODO: Write a longer description or delete this line.} + spec.homepage = "TODO: Put your gem's website or public repo URL here." + spec.license = "MIT" + + spec.metadata["jekyll"] = { "theme" => true } + + spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(exe|<%= theme_directories.join("|") %>)/}) } + spec.bindir = "exe" + spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + + spec.add_development_dependency "jekyll", "~> <%= jekyll_pessimistic_version %>" +end