From f959e649d451a88b4571127d244fac164d6538a0 Mon Sep 17 00:00:00 2001 From: Matthew Loberg Date: Wed, 31 Aug 2016 22:27:48 -0500 Subject: [PATCH 1/8] Add --config and --source option to draft command In some Jekyll setups, the site assets are in a sub-directory. The drafts command, does not process any configuration files or allow to set the site source. Add these options to the draft command and update the FileCreator class to take an optional root that will be prepended to the file.path. --- lib/jekyll-compose/file_creator.rb | 18 ++++++++++------ lib/jekyll/commands/draft.rb | 10 +++++++-- spec/draft_spec.rb | 33 ++++++++++++++++++++++++++++++ spec/spec_helper.rb | 2 ++ 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/lib/jekyll-compose/file_creator.rb b/lib/jekyll-compose/file_creator.rb index 33930fc..1be2d68 100644 --- a/lib/jekyll-compose/file_creator.rb +++ b/lib/jekyll-compose/file_creator.rb @@ -1,10 +1,11 @@ module Jekyll module Compose class FileCreator - attr_reader :file, :force - def initialize(fileInfo, force = false) + attr_reader :file, :force, :root + def initialize(fileInfo, force = false, root = nil) @file = fileInfo @force = force + @root = root end def create! @@ -16,20 +17,25 @@ def create! private def validate_should_write! - raise ArgumentError.new("A #{file.resource_type} already exists at #{file.path}") if File.exist?(file.path) and !force + raise ArgumentError.new("A #{file.resource_type} already exists at #{file_path}") if File.exist?(file_path) and !force end def ensure_directory_exists - dir = File.dirname file.path + dir = File.dirname file_path Dir.mkdir(dir) unless Dir.exist?(dir) end def write_file - File.open(file.path, "w") do |f| + File.open(file_path, "w") do |f| f.puts(file.content) end - puts "New #{file.resource_type} created at #{file.path}." + puts "New #{file.resource_type} created at #{file_path}." + end + + def file_path + return file.path if root.nil? or root.empty? + return File.join(root, file.path) end end end diff --git a/lib/jekyll/commands/draft.rb b/lib/jekyll/commands/draft.rb index 09c1bc8..7631782 100644 --- a/lib/jekyll/commands/draft.rb +++ b/lib/jekyll/commands/draft.rb @@ -16,18 +16,24 @@ def self.options [ ['extension', '-x EXTENSION', '--extension EXTENSION', 'Specify the file extension'], ['layout', '-l LAYOUT', '--layout LAYOUT', "Specify the draft layout"], - ['force', '-f', '--force', 'Overwrite a draft if it already exists'] + ['force', '-f', '--force', 'Overwrite a draft if it already exists'], + ['config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'], + ['source', '-s', '--source SOURCE', 'Custom source directory'], ] end def self.process(args = [], options = {}) + config = configuration_from_options(options) + params = Compose::ArgParser.new args, options params.validate! draft = DraftFileInfo.new params - Compose::FileCreator.new(draft, params.force?).create! + root = config['source'].gsub(/^#{Regexp.quote(Dir.pwd)}/, '') + + Compose::FileCreator.new(draft, params.force?, root).create! end class DraftFileInfo < Compose::FileInfo diff --git a/spec/draft_spec.rb b/spec/draft_spec.rb index 2a2a7ec..51ff696 100644 --- a/spec/draft_spec.rb +++ b/spec/draft_spec.rb @@ -73,4 +73,37 @@ expect(File.read(path)).to match(/layout: post/) end end + + context 'when a configuration file exists' do + let(:config) { source_dir('_config.yml') } + let(:drafts_dir) { Pathname.new source_dir(File.join('site', '_drafts')) } + + before(:each) do + File.open(config, 'w') do |f| + f.write(%{ +source: site +}) + end + end + + after(:each) do + FileUtils.rm(config) + end + + it 'should use source directory set by config' do + expect(path).not_to exist + capture_stdout { described_class.process(args) } + expect(path).to exist + end + end + + context 'when source option is set' do + let(:drafts_dir) { Pathname.new source_dir(File.join('site', '_drafts')) } + + it 'should use source directory set by command line option' do + expect(path).not_to exist + capture_stdout { described_class.process(args, 'source' => 'site') } + expect(path).to exist + end + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6f2b361..20d574a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -26,6 +26,8 @@ Kernel.srand config.seed + Jekyll.logger.log_level = :error + ### ### Helper methods ### From d7bb9af74c38383d58cbccf4f05c6f2e401b8c02 Mon Sep 17 00:00:00 2001 From: Matthew Loberg Date: Thu, 1 Sep 2016 08:30:01 -0500 Subject: [PATCH 2/8] Refactor ArgParser to load Jekyll configuration Load in Jekyll configuration when parsing args. Add source method to return Jekyll source directory and update the drafts command to use this new method. --- lib/jekyll-compose/arg_parser.rb | 7 ++++++- lib/jekyll/commands/draft.rb | 6 +----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/jekyll-compose/arg_parser.rb b/lib/jekyll-compose/arg_parser.rb index b1319a3..b30cf97 100644 --- a/lib/jekyll-compose/arg_parser.rb +++ b/lib/jekyll-compose/arg_parser.rb @@ -1,8 +1,9 @@ class Jekyll::Compose::ArgParser - attr_reader :args, :options + attr_reader :args, :options, :config def initialize(args, options) @args = args @options = options + @config = Jekyll.configuration(options) end def validate! @@ -24,4 +25,8 @@ def title def force? !!options["force"] end + + def source + source = config['source'].gsub(/^#{Regexp.quote(Dir.pwd)}/, '') + end end diff --git a/lib/jekyll/commands/draft.rb b/lib/jekyll/commands/draft.rb index 7631782..19f7100 100644 --- a/lib/jekyll/commands/draft.rb +++ b/lib/jekyll/commands/draft.rb @@ -24,16 +24,12 @@ def self.options def self.process(args = [], options = {}) - config = configuration_from_options(options) - params = Compose::ArgParser.new args, options params.validate! draft = DraftFileInfo.new params - root = config['source'].gsub(/^#{Regexp.quote(Dir.pwd)}/, '') - - Compose::FileCreator.new(draft, params.force?, root).create! + Compose::FileCreator.new(draft, params.force?, params.source).create! end class DraftFileInfo < Compose::FileInfo From 7b71ac487c89da13244a2ef5b9ff6d142ab2a5dc Mon Sep 17 00:00:00 2001 From: Matthew Loberg Date: Thu, 1 Sep 2016 08:32:42 -0500 Subject: [PATCH 3/8] Add source and config options to page command Update the page command to use the correct Jekyll source from config or command line option. --- lib/jekyll/commands/page.rb | 6 ++++-- spec/page_spec.rb | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/lib/jekyll/commands/page.rb b/lib/jekyll/commands/page.rb index e13b1bd..a5afc1a 100644 --- a/lib/jekyll/commands/page.rb +++ b/lib/jekyll/commands/page.rb @@ -16,7 +16,9 @@ def self.options [ ['extension', '-x EXTENSION', '--extension EXTENSION', 'Specify the file extension'], ['layout', '-l LAYOUT', '--layout LAYOUT', "Specify the page layout"], - ['force', '-f', '--force', 'Overwrite a page if it already exists'] + ['force', '-f', '--force', 'Overwrite a page if it already exists'], + ['config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'], + ['source', '-s', '--source SOURCE', 'Custom source directory'], ] end @@ -26,7 +28,7 @@ def self.process(args = [], options = {}) page = PageFileInfo.new params - Compose::FileCreator.new(page, params.force?).create! + Compose::FileCreator.new(page, params.force?, params.source).create! end class PageArgParser < Compose::ArgParser diff --git a/spec/page_spec.rb b/spec/page_spec.rb index 8c83cf2..d3a2178 100644 --- a/spec/page_spec.rb +++ b/spec/page_spec.rb @@ -63,4 +63,37 @@ expect(File.read(path)).to match(/layout: page/) end end + + context 'when a configuration file exists' do + let(:config) { source_dir('_config.yml') } + let(:path) { Pathname.new(source_dir).join('site', filename) } + + before(:each) do + File.open(config, 'w') do |f| + f.write(%{ +source: site +}) + end + end + + after(:each) do + FileUtils.rm(config) + end + + it 'should use source directory set by config' do + expect(path).not_to exist + capture_stdout { described_class.process(args) } + expect(path).to exist + end + end + + context 'when source option is set' do + let(:path) { Pathname.new(source_dir).join('site', filename) } + + it 'should use source directory set by command line option' do + expect(path).not_to exist + capture_stdout { described_class.process(args, 'source' => 'site') } + expect(path).to exist + end + end end From d9469c82610d188aef421edfad7f839e310ad87a Mon Sep 17 00:00:00 2001 From: Matthew Loberg Date: Thu, 1 Sep 2016 08:53:40 -0500 Subject: [PATCH 4/8] Add source and config options to post command Update post command to respect any custom Jekyll source. --- lib/jekyll/commands/post.rb | 6 ++++-- spec/post_spec.rb | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/lib/jekyll/commands/post.rb b/lib/jekyll/commands/post.rb index 2635059..dd25667 100644 --- a/lib/jekyll/commands/post.rb +++ b/lib/jekyll/commands/post.rb @@ -17,7 +17,9 @@ def self.options ['extension', '-x EXTENSION', '--extension EXTENSION', 'Specify the file extension'], ['layout', '-l LAYOUT', '--layout LAYOUT', "Specify the post layout"], ['force', '-f', '--force', 'Overwrite a post if it already exists'], - ['date', '-d DATE', '--date DATE', 'Specify the post date'] + ['date', '-d DATE', '--date DATE', 'Specify the post date'], + ['config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'], + ['source', '-s', '--source SOURCE', 'Custom source directory'], ] end @@ -27,7 +29,7 @@ def self.process(args = [], options = {}) post = PostFileInfo.new params - Compose::FileCreator.new(post, params.force?).create! + Compose::FileCreator.new(post, params.force?, params.source).create! end diff --git a/spec/post_spec.rb b/spec/post_spec.rb index d24f18e..c7b572c 100644 --- a/spec/post_spec.rb +++ b/spec/post_spec.rb @@ -82,4 +82,37 @@ expect(File.read(path)).to match(/layout: post/) end end + + context 'when a configuration file exists' do + let(:config) { source_dir('_config.yml') } + let(:posts_dir) { Pathname.new source_dir('site', '_posts') } + + before(:each) do + File.open(config, 'w') do |f| + f.write(%{ +source: site +}) + end + end + + after(:each) do + FileUtils.rm(config) + end + + it 'should use source directory set by config' do + expect(path).not_to exist + capture_stdout { described_class.process(args) } + expect(path).to exist + end + end + + context 'when source option is set' do + let(:posts_dir) { Pathname.new source_dir('site', '_posts') } + + it 'should use source directory set by command line option' do + expect(path).not_to exist + capture_stdout { described_class.process(args, 'source' => 'site') } + expect(path).to exist + end + end end From 9103444942f003a375d1528ec42a1aa607a19b8c Mon Sep 17 00:00:00 2001 From: Matthew Loberg Date: Thu, 1 Sep 2016 08:55:10 -0500 Subject: [PATCH 5/8] Add source and config options to publish command Update Publish command to allow custom Jekyll source. Update MovementArgParser to generate Jekyll config like was done with ArgParser. Update FileMover to automatically use a root directory if given. --- lib/jekyll-compose/file_mover.rb | 27 ++++++++++++---- lib/jekyll-compose/movement_arg_parser.rb | 7 ++++- lib/jekyll/commands/publish.rb | 4 ++- spec/publish_spec.rb | 38 ++++++++++++++++++++++- 4 files changed, 67 insertions(+), 9 deletions(-) diff --git a/lib/jekyll-compose/file_mover.rb b/lib/jekyll-compose/file_mover.rb index 7bc67ee..d7828d8 100644 --- a/lib/jekyll-compose/file_mover.rb +++ b/lib/jekyll-compose/file_mover.rb @@ -1,9 +1,10 @@ module Jekyll module Compose class FileMover - attr_reader :movement - def initialize(movement) + attr_reader :movement, :root + def initialize(movement, root = nil) @movement = movement + @root = root end def resource_type @@ -17,17 +18,31 @@ def move end def validate_source - raise ArgumentError.new("There was no #{resource_type} found at '#{movement.from}'.") unless File.exist? movement.from + raise ArgumentError.new("There was no #{resource_type} found at '#{from}'.") unless File.exist? from end def ensure_directory_exists - dir = File.dirname movement.to + dir = File.dirname to Dir.mkdir(dir) unless Dir.exist?(dir) end def move_file - FileUtils.mv(movement.from, movement.to) - puts "#{resource_type.capitalize} #{movement.from} was moved to #{movement.to}" + FileUtils.mv(from, to) + puts "#{resource_type.capitalize} #{from} was moved to #{to}" + end + + private + def from + file_path(movement.from) + end + + def to + file_path(movement.to) + end + + def file_path(path) + return path if root.nil? or root.empty? + return File.join(root, path) end end end diff --git a/lib/jekyll-compose/movement_arg_parser.rb b/lib/jekyll-compose/movement_arg_parser.rb index 903cac3..b45cc5a 100644 --- a/lib/jekyll-compose/movement_arg_parser.rb +++ b/lib/jekyll-compose/movement_arg_parser.rb @@ -1,10 +1,11 @@ module Jekyll module Compose class MovementArgParser - attr_reader :args, :options + attr_reader :args, :options, :config def initialize(args, options) @args = args @options = options + @config = Jekyll.configuration(options) end def validate! @@ -14,6 +15,10 @@ def validate! def path args.join ' ' end + + def source + source = config['source'].gsub(/^#{Regexp.quote(Dir.pwd)}/, '') + end end end end diff --git a/lib/jekyll/commands/publish.rb b/lib/jekyll/commands/publish.rb index 8a14cbb..ee7270f 100644 --- a/lib/jekyll/commands/publish.rb +++ b/lib/jekyll/commands/publish.rb @@ -7,6 +7,8 @@ def self.init_with_program(prog) c.description 'Moves a draft into the _posts directory and sets the date' c.option 'date', '-d DATE', '--date DATE', 'Specify the post date' + c.option 'config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file' + c.option 'source', '-s', '--source SOURCE', 'Custom source directory' c.action do |args, options| Jekyll::Commands::Publish.process(args, options) @@ -20,7 +22,7 @@ def self.process(args = [], options = {}) movement = DraftMovementInfo.new params - mover = DraftMover.new movement + mover = DraftMover.new movement, params.source mover.move end diff --git a/spec/publish_spec.rb b/spec/publish_spec.rb index c1e1a6e..5905365 100644 --- a/spec/publish_spec.rb +++ b/spec/publish_spec.rb @@ -46,7 +46,7 @@ output = capture_stdout { described_class.process(args) } expect(output).to eql("Draft _drafts/#{draft_to_publish} was moved to _posts/#{post_filename}\n") end - + it 'publishes a draft on the specified date' do path = posts_dir.join "2012-03-04-a-test-post.md" capture_stdout { described_class.process(args, {"date" => '2012-3-4'}) } @@ -72,4 +72,40 @@ }).to raise_error("There was no draft found at '_drafts/i-do-not-exist.markdown'.") end + context 'when a configuration file exists' do + let(:config) { source_dir('_config.yml') } + let(:drafts_dir) { Pathname.new source_dir('site', '_drafts') } + let(:posts_dir) { Pathname.new source_dir('site', '_posts') } + + before(:each) do + File.open(config, 'w') do |f| + f.write(%{ +source: site +}) + end + end + + after(:each) do + FileUtils.rm(config) + end + + it 'should use source directory set by config' do + expect(post_path).not_to exist + expect(draft_path).to exist + capture_stdout { described_class.process(args) } + expect(post_path).to exist + end + end + + context 'when source option is set' do + let(:drafts_dir) { Pathname.new source_dir('site', '_drafts') } + let(:posts_dir) { Pathname.new source_dir('site', '_posts') } + + it 'should use source directory set by command line option' do + expect(post_path).not_to exist + expect(draft_path).to exist + capture_stdout { described_class.process(args, 'source' => 'site') } + expect(post_path).to exist + end + end end From d20fb110b468b541f3205ed526c9ea13b589fada Mon Sep 17 00:00:00 2001 From: Matthew Loberg Date: Thu, 1 Sep 2016 08:58:35 -0500 Subject: [PATCH 6/8] Add source and config options to unpublish command Update Unpublish command to allow custom Jekyll source. --- lib/jekyll/commands/unpublish.rb | 5 ++++- spec/unpublish_spec.rb | 38 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/jekyll/commands/unpublish.rb b/lib/jekyll/commands/unpublish.rb index 8ce0b32..4b65615 100644 --- a/lib/jekyll/commands/unpublish.rb +++ b/lib/jekyll/commands/unpublish.rb @@ -6,6 +6,9 @@ def self.init_with_program(prog) c.syntax 'unpublish POST_PATH' c.description 'Moves a post back into the _drafts directory' + c.option 'config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file' + c.option 'source', '-s', '--source SOURCE', 'Custom source directory' + c.action do |args, options| process(args, options) end @@ -18,7 +21,7 @@ def self.process(args = [], options = {}) movement = PostMovementInfo.new params - mover = PostMover.new movement + mover = PostMover.new movement, params.source mover.move end diff --git a/spec/unpublish_spec.rb b/spec/unpublish_spec.rb index cdffff3..c86e626 100644 --- a/spec/unpublish_spec.rb +++ b/spec/unpublish_spec.rb @@ -57,4 +57,42 @@ }).to raise_error("There was no post found at '#{weird_path}'.") end + context 'when a configuration file exists' do + let(:config) { source_dir('_config.yml') } + let(:drafts_dir) { Pathname.new(source_dir('site', '_drafts')) } + let(:posts_dir) { Pathname.new(source_dir('site', '_posts')) } + + before(:each) do + File.open(config, 'w') do |f| + f.write(%{ +source: site +}) + end + end + + after(:each) do + FileUtils.rm(config) + end + + it 'should use source directory set by config' do + expect(post_path).to exist + expect(draft_path).not_to exist + capture_stdout { described_class.process(args) } + expect(post_path).not_to exist + expect(draft_path).to exist + end + end + + context 'when source option is set' do + let(:drafts_dir) { Pathname.new(source_dir('site', '_drafts')) } + let(:posts_dir) { Pathname.new(source_dir('site', '_posts')) } + + it 'should use source directory set by command line option' do + expect(post_path).to exist + expect(draft_path).not_to exist + capture_stdout { described_class.process(args, 'source' => 'site') } + expect(post_path).not_to exist + expect(draft_path).to exist + end + end end From 696a74c200fcb1f502d1c4b4f3e988002d8e4e8d Mon Sep 17 00:00:00 2001 From: Matthew Loberg Date: Thu, 1 Sep 2016 09:08:42 -0500 Subject: [PATCH 7/8] Fix FileMover Both Publish and Unpublish take in the relative path as the argument, so prepending the root directory won't give you the correct path to the file. Just prepend the root directory to the target path. --- lib/jekyll-compose/file_mover.rb | 2 +- spec/publish_spec.rb | 4 ++++ spec/unpublish_spec.rb | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/jekyll-compose/file_mover.rb b/lib/jekyll-compose/file_mover.rb index d7828d8..323afdb 100644 --- a/lib/jekyll-compose/file_mover.rb +++ b/lib/jekyll-compose/file_mover.rb @@ -33,7 +33,7 @@ def move_file private def from - file_path(movement.from) + movement.from end def to diff --git a/spec/publish_spec.rb b/spec/publish_spec.rb index 5905365..f274006 100644 --- a/spec/publish_spec.rb +++ b/spec/publish_spec.rb @@ -77,6 +77,8 @@ let(:drafts_dir) { Pathname.new source_dir('site', '_drafts') } let(:posts_dir) { Pathname.new source_dir('site', '_posts') } + let(:args) { ["site/_drafts/#{draft_to_publish}"] } + before(:each) do File.open(config, 'w') do |f| f.write(%{ @@ -101,6 +103,8 @@ let(:drafts_dir) { Pathname.new source_dir('site', '_drafts') } let(:posts_dir) { Pathname.new source_dir('site', '_posts') } + let(:args) { ["site/_drafts/#{draft_to_publish}"] } + it 'should use source directory set by command line option' do expect(post_path).not_to exist expect(draft_path).to exist diff --git a/spec/unpublish_spec.rb b/spec/unpublish_spec.rb index c86e626..fec4140 100644 --- a/spec/unpublish_spec.rb +++ b/spec/unpublish_spec.rb @@ -62,6 +62,8 @@ let(:drafts_dir) { Pathname.new(source_dir('site', '_drafts')) } let(:posts_dir) { Pathname.new(source_dir('site', '_posts')) } + let(:args) { ["site/_posts/#{post_filename}"] } + before(:each) do File.open(config, 'w') do |f| f.write(%{ @@ -87,6 +89,8 @@ let(:drafts_dir) { Pathname.new(source_dir('site', '_drafts')) } let(:posts_dir) { Pathname.new(source_dir('site', '_posts')) } + let(:args) { ["site/_posts/#{post_filename}"] } + it 'should use source directory set by command line option' do expect(post_path).to exist expect(draft_path).not_to exist From d467f20f487382fc1e837cb4a06b659f9ddfd584 Mon Sep 17 00:00:00 2001 From: Matthew Loberg Date: Fri, 9 Sep 2016 21:11:42 -0500 Subject: [PATCH 8/8] Remove unneeded variable assignment in ArgParser The variable assignments in ArgParser do nothing, so remove them. --- lib/jekyll-compose/arg_parser.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/jekyll-compose/arg_parser.rb b/lib/jekyll-compose/arg_parser.rb index b30cf97..95caa84 100644 --- a/lib/jekyll-compose/arg_parser.rb +++ b/lib/jekyll-compose/arg_parser.rb @@ -11,11 +11,11 @@ def validate! end def type - type = options["extension"] || Jekyll::Compose::DEFAULT_TYPE + options["extension"] || Jekyll::Compose::DEFAULT_TYPE end def layout - layout = options["layout"] || Jekyll::Compose::DEFAULT_LAYOUT + options["layout"] || Jekyll::Compose::DEFAULT_LAYOUT end def title @@ -27,6 +27,6 @@ def force? end def source - source = config['source'].gsub(/^#{Regexp.quote(Dir.pwd)}/, '') + config['source'].gsub(/^#{Regexp.quote(Dir.pwd)}/, '') end end