|
|
@@ -0,0 +1,257 @@ |
|
|
#!/usr/bin/env ruby |
|
|
|
|
|
require 'optparse' |
|
|
require 'ostruct' |
|
|
require 'pp' |
|
|
|
|
|
|
|
|
class Article |
|
|
|
|
|
attr_accessor :options, :file |
|
|
|
|
|
def initialize(arguments) |
|
|
@options = parse arguments |
|
|
@file = File.open(filename, "a") |
|
|
end |
|
|
|
|
|
def save |
|
|
add_frontmatter if file_blank? |
|
|
add_image_markup if images? |
|
|
file.close |
|
|
reload_jekyll |
|
|
do_work |
|
|
end |
|
|
|
|
|
private |
|
|
|
|
|
def title |
|
|
options[:title] |
|
|
end |
|
|
|
|
|
def description |
|
|
options[:description] |
|
|
end |
|
|
|
|
|
def images? |
|
|
options[:images] |
|
|
end |
|
|
|
|
|
def draft? |
|
|
options[:draft] |
|
|
end |
|
|
|
|
|
def any_images_to_add? |
|
|
entries = Dir.entries(images_dir) |
|
|
exclusions = %w{ . .. OpenGraph.png } |
|
|
|
|
|
(entries - exclusions).any? |
|
|
end |
|
|
|
|
|
def file_blank? |
|
|
File.zero?(filename) |
|
|
end |
|
|
|
|
|
def add_frontmatter |
|
|
file.puts(frontmatter) |
|
|
end |
|
|
|
|
|
def add_image_markup |
|
|
setup_source_image_directory |
|
|
setup_article_image_directory |
|
|
|
|
|
puts "\n\nIt puts the images in the directory, and hits enter when ready..." |
|
|
puts "\n(Don't forget 'OpenGraph.png')\n\n" |
|
|
`say 'Add your images'` |
|
|
gets |
|
|
|
|
|
file.puts(image_markup) if any_images_to_add? |
|
|
end |
|
|
|
|
|
def setup_source_image_directory |
|
|
if Dir.exists?(images_source_dir) |
|
|
system("open #{images_source_dir}") |
|
|
end |
|
|
end |
|
|
|
|
|
def setup_article_image_directory |
|
|
unless Dir.exists?(images_dir) |
|
|
Dir.mkdir(images_dir) |
|
|
end |
|
|
system("open #{images_dir}") |
|
|
end |
|
|
|
|
|
def image_markup |
|
|
image_markup = ["\n\n## Image Pull Options\n\n* pull\n* pull-full\n* pull-left\n* pull-right\n* pull-clean\n* pull-seprate\n\n"] |
|
|
counter = 0 |
|
|
|
|
|
Dir.foreach(images_dir) do |item| |
|
|
skippable = ['.', '..', '.DS_Store', 'OpenGraph.png'] |
|
|
next if skippable.include?(item) |
|
|
counter += 1 |
|
|
image_markup << image_markup_for(item, counter) |
|
|
end |
|
|
|
|
|
if image_markup.size > 1 |
|
|
return image_markup.join("\n\n") |
|
|
else |
|
|
return '' |
|
|
end |
|
|
end |
|
|
|
|
|
def do_work |
|
|
# Open Safari & Text Editor |
|
|
system("open -a safari #{local_web_address}") |
|
|
system("subl #{filename}") |
|
|
end |
|
|
|
|
|
def reload_jekyll |
|
|
# Jekyll isn't good at recognizing new files, so let's ditch any |
|
|
# existing instances and start fresh |
|
|
|
|
|
# Unless Jekyll is already running, let's start it up |
|
|
jekyll_instances = (`ps aux | grep [j]ekyll`).split(/\n/) |
|
|
|
|
|
jekyll_instances.each do |instance| |
|
|
instance =~ /\w+\s+(\d+)\s.+/i |
|
|
pid = $1 |
|
|
`kill -9 #{pid}` |
|
|
end |
|
|
|
|
|
system("jekyll serve --watch --detach") |
|
|
# Wait a moment for everything to propogate |
|
|
sleep 5 # seconds |
|
|
end |
|
|
|
|
|
def frontmatter |
|
|
str = <<-eot |
|
|
--- |
|
|
author: \"Garrett Dimon\" |
|
|
author_handle: garrettdimon |
|
|
title: \"#{title}\" |
|
|
description: \"#{description}\" |
|
|
layout: post |
|
|
image: #{opengraph_image} |
|
|
#{draft? ? 'state: draft' : ''} |
|
|
--- |
|
|
|
|
|
eot |
|
|
end |
|
|
|
|
|
def image_markup_for(image, counter) |
|
|
str = <<-eot |
|
|
<span class=\"ref\">#{counter}</span> |
|
|
|
|
|
<figure class=\"pull\"> |
|
|
<img src=\"/images/#{slug}/#{image}\" alt=\"\" /> |
|
|
<figcaption> |
|
|
<b>#{counter}</b> |
|
|
Description |
|
|
</figcaption> |
|
|
</figure> |
|
|
|
|
|
eot |
|
|
end |
|
|
|
|
|
# ex. "/Users/garrettdimon/Sites/garrettdimon.com/blog/images/2015-06-22-article-name-like-this" |
|
|
def images_dir |
|
|
"#{directory}/images/#{slug}" |
|
|
end |
|
|
|
|
|
def opengraph_image |
|
|
# https://garrettdimon.com/blog/images/2015-06-14-milestone-overview-calendar/MilestonesCalendar.png |
|
|
"https://garrettdimon.com/images/#{slug}/OpenGraph.png" |
|
|
end |
|
|
|
|
|
# ex. "./blog/_posts/2015-06-22-article-name-like-this.markdown" |
|
|
def filename |
|
|
section_folder = draft? ? "drafts" : "posts" |
|
|
"./_#{section_folder}/#{slug}.markdown" |
|
|
end |
|
|
|
|
|
# ex. "2015-06-22-article-name-like-this" |
|
|
def slug |
|
|
"#{date_slug}-#{title_slug}" |
|
|
end |
|
|
|
|
|
# ex. "article-name-like-this" |
|
|
def title_slug |
|
|
# Strip _'s, replace spaces with '-', and ditch non-alphanumerics |
|
|
@ts ||= title. |
|
|
downcase. |
|
|
gsub('_', ''). |
|
|
gsub(' ', '-'). |
|
|
gsub(/[^a-z0-9-]/, '') |
|
|
|
|
|
end |
|
|
|
|
|
# ex. "2015-06-22" |
|
|
def date_slug |
|
|
@ds ||= Time.now.strftime '%Y-%m-%d' |
|
|
end |
|
|
|
|
|
# ex. "2015/06/" |
|
|
def archive_folder_slug |
|
|
@as ||= Time.now.strftime '%Y/' |
|
|
end |
|
|
|
|
|
# ex. "/2015/article-name-like-this" |
|
|
def archive_path |
|
|
@ap ||= "#{archive_folder_slug}#{title_slug}/" |
|
|
end |
|
|
|
|
|
# This is the working directory for compiling images that will be used in the |
|
|
# post. If it's present, it will automatically be opened in Finder for easy |
|
|
# drag and drop into the new post directory. |
|
|
def images_source_dir |
|
|
"/Users/garrettdimon/Desktop/NewArticleImages/" |
|
|
end |
|
|
|
|
|
# For know what URL to open in the browser for previewing the new post. |
|
|
def local_web_address |
|
|
"http://127.0.0.1:4000/" |
|
|
end |
|
|
|
|
|
def directory |
|
|
Dir.pwd |
|
|
end |
|
|
|
|
|
def parse(options) |
|
|
|
|
|
args = OpenStruct.new |
|
|
args.title = "" |
|
|
args.description = "#TODO" |
|
|
args.images = false |
|
|
args.draft = false |
|
|
|
|
|
opt_parser = OptionParser.new do |opts| |
|
|
opts.banner = "Usage: write.rb [options]" |
|
|
|
|
|
opts.on("-t", "--title=TITLE", "Title of the article") do |t| |
|
|
args.title = t |
|
|
end |
|
|
|
|
|
opts.on("-d", "--desc=DESCRIPTION", "Meta description for article") do |s| |
|
|
args.description = d |
|
|
end |
|
|
|
|
|
opts.on("-f", "--draft", "If the article should be a draft for now") do |f| |
|
|
args.draft = true |
|
|
end |
|
|
|
|
|
opts.on("-i", "--images", "If the article includes images") do |i| |
|
|
args.images = true |
|
|
end |
|
|
|
|
|
opts.on("-h", "--help", "Prints this help") do |
|
|
puts opts |
|
|
exit |
|
|
end |
|
|
end |
|
|
|
|
|
opt_parser.parse!(options) |
|
|
return args |
|
|
end |
|
|
|
|
|
end |
|
|
|
|
|
article = Article.new(ARGV).save |