Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Continue work on `write` command #1395

Closed
wants to merge 11 commits into from

8 participants

@parkr
Owner

Looks like @Schoonology is no longer working on his PR (#1148) so I wanted to
continue work on this stuff here.

  • Implement command
  • Implement Template class (or something similar)
  • Write tests for Template class
  • Write integration features for writing

Idea:

$ jekyll write post --title TITLE [--link LINK] [--layout LAYOUT] [--ext EXT]
# generates post at _posts/2013-08-07-title.EXT like this:
#
# ---
# layout: LAYOUT # (defaults to 'default', maybe?)
# date: "2013-08-07T23:14:13+02:00"
# title: TITLE
# [link: LINK]
# ---
#

$ jekyll write page --path PATH [--title TITLE] [--layout LAYOUT]
# generates page at PATH like this:
#
# ---
# layout: LAYOUT
# title: TITLE # if provided
# ---
#

$ jekyll write post --template post --title TITLE
# reads in contents of `_write/post.erb`, runs it through ERB and outputs it to the proper place
# it would also take all the options above and set each of them as variables,
#     thus `--layout LAYOUT` is accessible via `<%= layout # outputs "LAYOUT" %>`.

# Same thing with pages.
Schoonology and others added some commits
@Schoonology Schoonology Implemented `write` command.
`jekyll write [type]` creates a new post, page, or draft depending on [type]. It supports option for --path, --title, and --ext.

See `jekyll help write`.
62883ec
@Schoonology Schoonology fixup! Implemented `write` command. 0ee99f8
@parkr parkr Merge branch 'write_command' of git://github.com/Schoonology/jekyll i…
…nto write-command

* 'write_command' of git://github.com/Schoonology/jekyll:
  fixup! Implemented `write` command.
  Implemented `write` command.
a35cd98
@parkr parkr Default to 'draft' instead of 'post' d36e830
@parkr parkr Set path more generally in Write command. 665900a
@parkr parkr Use String#empty? instead of String=='' 7e7a789
@parkr parkr Fixes and tidying fe44d97
@parkr parkr Completely refactored into a new class. 4f2322e
@parkr parkr referenced this pull request
Closed

Implemented `write` command. #1148

@benbalter
Owner

Wat. There's no way we want to be in the business of hard coding certain "blessed" YML attributes that you can pass via command line. That's a giant rabbit hole to start down.

What if the syntax was jekyll write [format] with two changes:

  1. Pass title immediately after format... assume I'm giving you a title... what's the downside if title is required?
  2. Any flag passed is converted to a YML key/value. so --layout post works, but --foo bar is just as supported.

Another idea:

What about supporting YML defaults like Prose does via _config.yml? Every time I write a post, there's ~10 YML fields I'll need to copy over (layout, comments, author, published, etc.). Would be awesome if we could just consume Prose's customizations or something similar so the command isn't 10 feet each time it's run.

@mattvh

@benbalter I like that idea.

On Jekyll Themes, I use a few "non-blessed" YAML keys like "demo" for the URL where a theme demo could be found and "thumbnail" for the associated image's filename. It's a little unwieldy if you're not just copying an old post manually.

@parkr
Owner

@benbalter That's a good idea, but with Commander and OptionsParser in general, it's impossible to accept all options. For all unspecified options, one will receive a invalid option: --foo.

The two options which remain are (1) specify ERB files to read in, parse, and write, or (2) keep all the yaml you want in your posts in your config.yml. The latter sucks so the former is probably the best way to go.

@scribu

Since this also involves drafts, related discussion: #1469

@parkr
Owner

Do we still think this is good to have bundled with Jekyll itself or have other tools filled the void satisfactorily?

@mscharley

I think that it's a good idea to have something standardised like this either in Jekyll core (preferable in my opinion) or available easily as a plugin. Is there anything available that isn't just people instrumenting around jekyll? I used to have a rake task that did something similar for instance.

@parkr parkr closed this
@parkr parkr reopened this
@parkr parkr modified the milestone: 2.1, 2.0
@parkr
Owner

Going to take care of all of this in https://github.com/jekyll/jekyll-compose

@parkr parkr closed this
@parkr parkr deleted the branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 31, 2013
  1. @Schoonology

    Implemented `write` command.

    Schoonology authored
    `jekyll write [type]` creates a new post, page, or draft depending on [type]. It supports option for --path, --title, and --ext.
    
    See `jekyll help write`.
Commits on Jun 8, 2013
  1. @Schoonology
Commits on Aug 7, 2013
  1. @parkr

    Merge branch 'write_command' of git://github.com/Schoonology/jekyll i…

    parkr authored
    …nto write-command
    
    * 'write_command' of git://github.com/Schoonology/jekyll:
      fixup! Implemented `write` command.
      Implemented `write` command.
  2. @parkr
  3. @parkr
  4. @parkr
  5. @parkr

    Fixes and tidying

    parkr authored
  6. @parkr
  7. @parkr

    Add --layout

    parkr authored
Commits on Aug 8, 2013
  1. @qmx
  2. @mattr-

    Merge pull request #1396 from qmx/write_command

    mattr- authored
    use builtin jekyll logger
This page is out of date. Refresh to see the latest.
Showing with 135 additions and 0 deletions.
  1. +19 −0 bin/jekyll
  2. +26 −0 lib/jekyll/commands/write.rb
  3. +90 −0 lib/jekyll/template.rb
View
19 bin/jekyll
@@ -155,3 +155,22 @@ command :import do |c|
Jekyll::Commands::Import.process(args.first, options)
end
end
+
+command :write do |c|
+ c.syntax = 'jekyll write [TYPE]'
+ c.summary = 'Write a new post, page, or draft.'
+ c.description = 'Write a new post, page, or draft, based on TYPE, which defaults to "draft". Either --title or --path is required.'
+
+ c.option '--title TITLE', String, 'Title to use.'
+ c.option '--path PATH', String, 'Path to write to.'
+ c.option '--ext EXTNAME', String, 'File extension to use with --title and directory paths. Default: markdown'
+ c.option '--layout LAYOUT', String, 'Title to use.'
+
+ c.action do |args, options|
+ args = ['draft'] if args.empty?
+
+ options.default :ext => 'markdown'
+
+ Jekyll::Commands::Write.process(args, options.__hash__)
+ end
+end
View
26 lib/jekyll/commands/write.rb
@@ -0,0 +1,26 @@
+module Jekyll
+ module Commands
+ class Write < Command
+ def self.process(args, options = {})
+ raise ArgumentError.new('You must specify either a path or a title.') if !options[:title] && !options[:path]
+
+ type = args[0].downcase
+
+ template = if %w[draft page post].include?(type)
+ Jekyll::Template.new(type, options)
+ else
+ Jekyll.logger.warn "Invalid Argument:", "Jekyll can only write posts, pages and drafts for you. Beyond that, you're on your own."
+ raise ArgumentError.new("Invalid type for writing: '#{type}'")
+ end
+
+ template.write
+
+ if STDOUT.tty?
+ Jekyll.logger.info("Wrote #{type} template to #{template.path}")
+ else
+ template.puts path
+ end
+ end
+ end
+ end
+end
View
90 lib/jekyll/template.rb
@@ -0,0 +1,90 @@
+module Jekyll
+ class Template
+
+ attr_accessor :type, :path, :options, :date, :external_url, :title
+
+ def initialize(type, opts)
+ raise ArgumentError.new('You must specify either a path or a title.') if !opts[:title] && !opts[:path]
+
+ self.type = type.downcase
+ self.options = opts
+ self.layout = options[:layout] || "#{self.type}"
+ self.date = Time.now if self.type = "post"
+ self.title = determine_title
+ self.path = determine_path
+ end
+
+ def content
+ frontmatter + "\n---\n\n"
+ end
+
+ def write
+ FileUtils.mkdir_p(File.dirname(path))
+ File.open(path, "wb") do |file|
+ file.puts(content)
+ end
+ end
+
+ private
+
+ def determine_path
+ if options[:path]
+ specified_path = options[:path]
+ if File.extname(specified_path).empty?
+ specified_path = File.join(specified_path, "index.#{options[:ext]}")
+ end
+ specified_path
+ else
+ case type
+ when "drafts"
+ "_drafts/#{slug}.#{options[:ext]}"
+ when "post"
+ "_posts/#{date.strftime('%Y-%m-%d')}-#{slug}.#{options[:ext]}"
+ when "page"
+ "#{slug}.#{options[:ext]}"
+ end
+ end
+ end
+
+ def determine_title
+ if options[:title]
+ options[:title]
+ else
+ titleize(path)
+ end
+ end
+
+ def slug
+ title.gsub(" ", "-").gsub(/[^\w-]/, "").downcase
+ end
+
+ def titleize(something)
+ something.gsub(File.extname(something), '').split("-").map(&:capitalize).join(" ")
+ end
+
+ def frontmatter
+ base = {
+ "layout" => layout,
+ "title" => title
+ }
+ YAML.dump(base.merge(date_frontmatter).merge(external_url_frontmatter))
+ end
+
+ def date_frontmatter
+ if date
+ { "date" => date.xmlschema }
+ else
+ {}
+ end
+ end
+
+ def external_url_frontmatter
+ if external_url
+ { "external-url" => external_url }
+ else
+ {}
+ end
+ end
+
+ end
+end
Something went wrong with that request. Please try again.