den 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/den +72 -0
- data/den.gemspec +20 -0
- data/lib/den/examples.rb +25 -0
- data/lib/den/page.rb +41 -0
- data/lib/den/post.rb +62 -0
- data/lib/den/resource.rb +58 -0
- data/lib/den/template.rb +101 -0
- data/lib/den/utilities.rb +19 -0
- data/lib/den.rb +322 -0
- metadata +54 -0
data/bin/den
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
4
|
+
|
5
|
+
require 'den'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
# If the command was to make a new site, do it and quit
|
9
|
+
if "#{ARGV[0]} #{ARGV[1]}".downcase == "new site" and ARGV.length == 3
|
10
|
+
Den.create_skeleton(ARGV[2])
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
|
14
|
+
# Exit if the '.den' file doesn't exist
|
15
|
+
if !File.exists?('.den')
|
16
|
+
abort("Make sure you're running from the root of your Den instance.")
|
17
|
+
end
|
18
|
+
|
19
|
+
# Load the config if it exists
|
20
|
+
config = YAML::load(File.open('config.yml')) if File.exist?('config.yml')
|
21
|
+
|
22
|
+
# Create a Den instance
|
23
|
+
den = Den.new(config=config)
|
24
|
+
|
25
|
+
# Process arguments
|
26
|
+
case ARGV[0]
|
27
|
+
|
28
|
+
when 'new'
|
29
|
+
# Handle different 'new' cases (page, post)
|
30
|
+
if ARGV[1].downcase == 'page'
|
31
|
+
if !(ARGV.length == 3 or ARGV.length == 4)
|
32
|
+
abort('Invalid format for "new page".')
|
33
|
+
end
|
34
|
+
den.new_resource('page', :dest => ARGV[2], :file => ARGV[3])
|
35
|
+
elsif ARGV[1].downcase == 'post'
|
36
|
+
if !(ARGV.length == 2 or ARGV.length == 3)
|
37
|
+
abort('Invalid format for "new post".')
|
38
|
+
end
|
39
|
+
den.new_resource('post', :file => ARGV[2])
|
40
|
+
else
|
41
|
+
abort("'#{ARGV[1]}' is an invalid argument for 'new'. Must be either 'page' or 'post'.")
|
42
|
+
end
|
43
|
+
|
44
|
+
# Update the site
|
45
|
+
den.update_site(refresh=true)
|
46
|
+
|
47
|
+
|
48
|
+
when 'delete'
|
49
|
+
abort('Invalid format for command "delete".') if ARGV.length != 3
|
50
|
+
if ARGV[1].downcase == 'page' or ARGV[1].downcase == 'post'
|
51
|
+
den.delete_resource(ARGV[1].downcase, ARGV[2])
|
52
|
+
else
|
53
|
+
abort("'#{ARGV[1]}' is an invalid argument for 'delete'. Must be either 'page' or 'post'.")
|
54
|
+
end
|
55
|
+
|
56
|
+
# Update the site
|
57
|
+
den.update_site(refresh=true)
|
58
|
+
|
59
|
+
|
60
|
+
when 'list'
|
61
|
+
abort('Invalid format for "list".') if ARGV.length > 1
|
62
|
+
# Display all the content
|
63
|
+
den.print_content
|
64
|
+
|
65
|
+
# Unrecognized argument, exit
|
66
|
+
else
|
67
|
+
if ARGV.length > 0
|
68
|
+
abort('Invalid command.')
|
69
|
+
else
|
70
|
+
den.update_site
|
71
|
+
end
|
72
|
+
end
|
data/den.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'den'
|
3
|
+
s.version = '0.1.0'
|
4
|
+
s.summary = 'A really simple static-site generator.'
|
5
|
+
s.authors = ["Peter Valdez"]
|
6
|
+
s.email = 'peter@someindividual.com'
|
7
|
+
s.executables << 'den'
|
8
|
+
s.homepage = 'https://github.com/azlyth/den'
|
9
|
+
s.files = %w[
|
10
|
+
bin/den
|
11
|
+
lib/den/examples.rb
|
12
|
+
lib/den/page.rb
|
13
|
+
lib/den/post.rb
|
14
|
+
lib/den/resource.rb
|
15
|
+
lib/den/template.rb
|
16
|
+
lib/den/utilities.rb
|
17
|
+
lib/den.rb
|
18
|
+
den.gemspec
|
19
|
+
]
|
20
|
+
end
|
data/lib/den/examples.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# A module used to keep all the skeleton defaults in one place.
|
2
|
+
module Examples
|
3
|
+
CONFIG = ":site:\n :root: /var/www/\n :posts: musings\n"
|
4
|
+
|
5
|
+
TEMPLATES = {
|
6
|
+
# Base template
|
7
|
+
:base => "<html>\n <head>\n <title>{{ title }} | mysite</title>\n </head>\n <body>\n <div id=\"content\">\n {{ body }}\n </div>\n </body>\n</html>\n",
|
8
|
+
|
9
|
+
# Index template
|
10
|
+
:index => "{{ extends base.html }}\n\n{{ block title }}index{{ endblock }}\n\n{{ block body }}\n[[ body ]]\n{{ endblock }}\n",
|
11
|
+
|
12
|
+
# Page template
|
13
|
+
:page => "{{ extends base.html }}\n\n{{ block title }}[[ title ]]{{ endblock }}\n\n{{ block body }}\n[[ content ]]\n{{ endblock }}\n",
|
14
|
+
|
15
|
+
# Post template
|
16
|
+
:post => "{{ extends base.html }}\n\n{{ block title }}[[ title ]]{{ endblock }}\n\n{{ block body }}\n[[ content ]]\n{{ endblock }}\n",
|
17
|
+
}
|
18
|
+
|
19
|
+
# Example page
|
20
|
+
PAGE = "[About me]\n\nThis is a test \"about me\" page.\nAsdfasdf.\n\n# Intro\n\n## Past\n\nBlah blah, I did this and that.\n\n## Now\n\nWoah, you do WHAT these days?\n"
|
21
|
+
|
22
|
+
# Example post
|
23
|
+
POST = "[What a post.]\n\nNo, but really, what a post. I'm kidding this is an example post.\nIt's a post that makes a world of a difference.\n\n# Some great point\n\n## A worthy subpoint\n\nAnd some info.\n\nAnd conclude.\n"
|
24
|
+
|
25
|
+
end
|
data/lib/den/page.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require "cgi"
|
2
|
+
require "den/resource"
|
3
|
+
|
4
|
+
class Page < Resource
|
5
|
+
|
6
|
+
def to_s
|
7
|
+
"Page: #{@content[:id]}"
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
# Return the HTML rendering of this page
|
12
|
+
def html()
|
13
|
+
_html = "<div id=\"page\">\n"
|
14
|
+
|
15
|
+
# Wrap title in anchor if link is provided
|
16
|
+
_html += "<h1 id=\"title\">#{@content[:title]}</h1>\n"
|
17
|
+
|
18
|
+
# Add the rest of the necessary content
|
19
|
+
_html += "<div id=\"body\">\n" +
|
20
|
+
"#{@content[:body]}\n" +
|
21
|
+
"</div>" +
|
22
|
+
"</div>"
|
23
|
+
|
24
|
+
_html
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
# Pull out metadata and markup the page
|
29
|
+
def process
|
30
|
+
File.open(@file) do |f|
|
31
|
+
page = markup(f.read)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Extract the url from the filename
|
35
|
+
page[:id] = @file.split('/')[-1]
|
36
|
+
|
37
|
+
# Store the processed info
|
38
|
+
@content = page
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/lib/den/post.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require "date"
|
2
|
+
require "cgi"
|
3
|
+
require "den/resource"
|
4
|
+
|
5
|
+
class Post < Resource
|
6
|
+
|
7
|
+
def to_s
|
8
|
+
"Post #{@content[:id]}"
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
def [](index)
|
13
|
+
@content[index]
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
# Return the HTML rendering of the post
|
18
|
+
def html(link="")
|
19
|
+
_html = "<div id=\"post\">\n"
|
20
|
+
|
21
|
+
# Wrap title in anchor if link is provided
|
22
|
+
_html += "<h1 id=\"title\">"
|
23
|
+
if link != ""
|
24
|
+
_html += "<a href=\"#{link}\">"
|
25
|
+
end
|
26
|
+
_html += "#{@content[:title]}"
|
27
|
+
if link != ""
|
28
|
+
_html += "</a>"
|
29
|
+
end
|
30
|
+
|
31
|
+
_html += "</h1>\n"
|
32
|
+
|
33
|
+
|
34
|
+
# Add the rest of the necessary content
|
35
|
+
_html += "<h2 id=\"date\">#{@content[:date].strftime("%B %e, %Y")}</h2>\n" +
|
36
|
+
"<div id=\"body\">\n" +
|
37
|
+
"#{@content[:body]}\n" +
|
38
|
+
"</div>\n" +
|
39
|
+
"</div>"
|
40
|
+
|
41
|
+
_html
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
# Pull out metadata and markup the post
|
46
|
+
def process
|
47
|
+
File.open(@file) do |f|
|
48
|
+
# Extract the date
|
49
|
+
post = {
|
50
|
+
:id => f.readline.chomp,
|
51
|
+
:date => DateTime.strptime(f.readline.chomp, "%Y-%m-%d %H:%M:%S %z")
|
52
|
+
}
|
53
|
+
|
54
|
+
# Process the post
|
55
|
+
post.merge!(markup(f.read))
|
56
|
+
|
57
|
+
# Store the processed info
|
58
|
+
@content = post
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
data/lib/den/resource.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# General Den resource object (included by Page and Post)
|
2
|
+
class Resource
|
3
|
+
|
4
|
+
# Initialize the object
|
5
|
+
def initialize(file)
|
6
|
+
@file = file
|
7
|
+
process
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
def [](index)
|
12
|
+
@content[index]
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
# Deletes itself
|
17
|
+
def delete
|
18
|
+
File.delete(@file)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
# General markup function
|
23
|
+
def markup(s)
|
24
|
+
s = CGI::escapeHTML(s)
|
25
|
+
title = nil
|
26
|
+
|
27
|
+
# Extract title
|
28
|
+
s.gsub!(/\A\[(.*\S)\]$/) do |x|
|
29
|
+
title = $1
|
30
|
+
""
|
31
|
+
end
|
32
|
+
|
33
|
+
# Remove duplicate newlines
|
34
|
+
s.gsub!(/\n\n+/, "\n\n")
|
35
|
+
|
36
|
+
# Remove leading whitespace from lines
|
37
|
+
s.gsub!(/^ +/, "")
|
38
|
+
|
39
|
+
# Pad string to remove edge cases
|
40
|
+
s.gsub!(/(\A\n*)|(\n*\z)/, "\n")
|
41
|
+
|
42
|
+
# Headers
|
43
|
+
s.gsub!(/^(#+)\s*(.*)/) {
|
44
|
+
len = $1.length
|
45
|
+
"<h#{len+1} class=\"header\">#$2</h#{len}>"
|
46
|
+
}
|
47
|
+
|
48
|
+
# Paragraphs
|
49
|
+
s.gsub!(/(\A|\n)\n([^<])/, "\n\n<p>\\2")
|
50
|
+
s.gsub!(/([^>])\n\n/, "\\1</p>\n\n")
|
51
|
+
|
52
|
+
# Remove extra newlines
|
53
|
+
s.gsub!(/\n+/, "\n")
|
54
|
+
|
55
|
+
{:title => title, :body => s}
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/lib/den/template.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
class Template
|
2
|
+
|
3
|
+
def initialize(template_dir, template_file=nil, post_location=nil)
|
4
|
+
@template_dir = template_dir
|
5
|
+
load_template(template_file) if !template_file.nil?
|
6
|
+
@post_location = post_location
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
# Calls the appropriate render function
|
11
|
+
def render(obj, prev_page=nil, next_page=nil)
|
12
|
+
case obj
|
13
|
+
when Resource
|
14
|
+
return render_resource(obj)
|
15
|
+
when Array
|
16
|
+
return render_index(obj, prev_page, next_page)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
# Returns the HTML of a Resource
|
22
|
+
def render_resource(r)
|
23
|
+
data = {
|
24
|
+
"title" => r[:title],
|
25
|
+
"content" => r.html
|
26
|
+
}
|
27
|
+
|
28
|
+
populate(data)
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
# Returns the HTML of an index
|
33
|
+
def render_index(posts, prev_page, next_page)
|
34
|
+
# Get the HTML of each Post and combine them
|
35
|
+
posts.collect! { |p| p.html(File.join('/', @post_location, p[:id].to_s)) }
|
36
|
+
data = { "body" => posts.join("\n\n") }
|
37
|
+
|
38
|
+
# Append next/previous links if necessary
|
39
|
+
if !prev_page.nil?
|
40
|
+
data["body"] += "<a class=\"nav\" id=\"future\" href=\"#{prev_page}\">Newer Posts</a>\n"
|
41
|
+
end
|
42
|
+
|
43
|
+
if !next_page.nil?
|
44
|
+
data["body"] += "<a class=\"nav\" id=\"past\" href=\"#{next_page}\">Older Posts</a>\n"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Return the rendered index
|
48
|
+
populate(data)
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# Fills in the template with the data provided
|
53
|
+
def populate(data)
|
54
|
+
@content.gsub(/\[\[ (\S*) \]\]/) { |x| data[$1] }
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# Loads the template file into @content
|
59
|
+
def load_template(filename)
|
60
|
+
template_path = File.join(@template_dir, filename)
|
61
|
+
|
62
|
+
if File.file?(template_path)
|
63
|
+
# Load the template file
|
64
|
+
template_file = ''
|
65
|
+
File.open(template_path) do |f|
|
66
|
+
template_file = f.read
|
67
|
+
end
|
68
|
+
|
69
|
+
# Check if this template is an extension
|
70
|
+
if template_file =~ /{{ extends (\S*) }}/
|
71
|
+
# Load the parent template into content
|
72
|
+
load_template($1)
|
73
|
+
|
74
|
+
# Find blocks
|
75
|
+
template_file = template_file.split("{{ endblock }}")
|
76
|
+
blocks = {}
|
77
|
+
for block in template_file
|
78
|
+
if /{{ block (?<label>\S*) }}(?<content>[\s\S]*)/ =~ block
|
79
|
+
blocks[label] = content
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Combine the parent template with the blocks
|
84
|
+
merge_templates(blocks)
|
85
|
+
else
|
86
|
+
# Load the file into content
|
87
|
+
@content = template_file
|
88
|
+
end
|
89
|
+
else
|
90
|
+
puts "Unable to locate template: #{@template_dir + filename}."
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Combine a template with its parent
|
95
|
+
def merge_templates(blocks)
|
96
|
+
@content.gsub!(/{{ (\S*) }}/) do |x|
|
97
|
+
blocks[$1]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Given a filename (and extension, optionally), returns an unused filename.
|
2
|
+
def get_unused_filename(filename, extension="")
|
3
|
+
extension = "." + extension if extension != ""
|
4
|
+
|
5
|
+
full_path = filename + extension
|
6
|
+
|
7
|
+
if File.exists?(full_path)
|
8
|
+
count = 1
|
9
|
+
|
10
|
+
# Keep adding to the count until we find filename that isn't taken.
|
11
|
+
while File.exists?("#{filename}_#{count}#{extension}")
|
12
|
+
count += 1
|
13
|
+
end
|
14
|
+
|
15
|
+
full_path = "#{filename}_#{count}#{extension}"
|
16
|
+
end
|
17
|
+
|
18
|
+
full_path
|
19
|
+
end
|
data/lib/den.rb
ADDED
@@ -0,0 +1,322 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "date"
|
3
|
+
require "den/post"
|
4
|
+
require "den/page"
|
5
|
+
require "den/template"
|
6
|
+
require "den/utilities"
|
7
|
+
require "den/examples"
|
8
|
+
|
9
|
+
class Den
|
10
|
+
|
11
|
+
# Creates a new Den site
|
12
|
+
def self.create_skeleton(location)
|
13
|
+
# Create the directories along with default templates
|
14
|
+
Dir.mkdir(location)
|
15
|
+
Dir.mkdir(File.join(location, 'pages'))
|
16
|
+
Dir.mkdir(File.join(location, 'posts'))
|
17
|
+
Dir.mkdir(File.join(location, 'posts', 'new'))
|
18
|
+
Dir.mkdir(File.join(location, 'templates'))
|
19
|
+
Examples::TEMPLATES.each_pair { |file, content|
|
20
|
+
File.open(File.join(location, 'templates', file.to_s + '.html'), 'w') do |f|
|
21
|
+
f.print(content)
|
22
|
+
end
|
23
|
+
}
|
24
|
+
|
25
|
+
File.open(File.join(location, 'config.yml'), 'w') do |f|
|
26
|
+
f.write(Examples::CONFIG)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Create the file that indicates this is a Den instance
|
30
|
+
FileUtils.touch(File.join(location, '.den'))
|
31
|
+
|
32
|
+
puts "Created new site in '#{location}'."
|
33
|
+
end
|
34
|
+
|
35
|
+
# Default configuration values
|
36
|
+
@@default_config = {
|
37
|
+
# Where pages are actually served from
|
38
|
+
# Note the following:
|
39
|
+
# - 'root' gets prepended to all locations but 'index'
|
40
|
+
# - 'posts' gets prepended to 'index'
|
41
|
+
:site => {
|
42
|
+
:root => "/var/www/",
|
43
|
+
:pages => "",
|
44
|
+
:posts => "posts/",
|
45
|
+
:index => "index/",
|
46
|
+
},
|
47
|
+
}
|
48
|
+
|
49
|
+
@@default_meta = {
|
50
|
+
# The number of total posts
|
51
|
+
:last_post => 0,
|
52
|
+
}
|
53
|
+
|
54
|
+
|
55
|
+
# Create the Den and store the config, prioritizing the provided one.
|
56
|
+
def initialize(config=nil)
|
57
|
+
@config = @@default_config
|
58
|
+
|
59
|
+
if !config.nil?
|
60
|
+
@config[:new_posts] = config[:new_posts] if !config[:new_posts].nil?
|
61
|
+
@config[:site].merge!(config[:site]) if !config[:site].nil?
|
62
|
+
end
|
63
|
+
|
64
|
+
load_metadata
|
65
|
+
gather_new_posts
|
66
|
+
prepare_content
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
# Update the site
|
73
|
+
def update_site(refresh=false)
|
74
|
+
if refresh
|
75
|
+
prepare_content
|
76
|
+
end
|
77
|
+
push_content
|
78
|
+
create_indices
|
79
|
+
puts "Updated the site."
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# Display the Den's pages and posts, along with their metadata
|
84
|
+
def print_content
|
85
|
+
puts "Pages:" if !@pages.empty?
|
86
|
+
@pages.each do |p|
|
87
|
+
puts " #{p[:id]} (title: '#{p[:title]}')"
|
88
|
+
end
|
89
|
+
|
90
|
+
puts "Posts:" if !@posts.empty?
|
91
|
+
@posts.each do |p|
|
92
|
+
puts " #{p[:id]} (title: '#{p[:title]}', date: #{p[:date].strftime("%B %e, %Y")})"
|
93
|
+
end
|
94
|
+
|
95
|
+
if @pages.empty? and @posts.empty?
|
96
|
+
puts "No content."
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
# Adds a page or post. If a file is provided, it copies the contents of the
|
102
|
+
# file. Otherwise, it will start the default editor to make the new resource.
|
103
|
+
def new_resource(type, options)
|
104
|
+
defaults = {:file => nil, :dest => nil}
|
105
|
+
options = defaults.merge(options)
|
106
|
+
type.downcase!
|
107
|
+
|
108
|
+
if options[:file].nil?
|
109
|
+
# Create the new page/post with the default editor
|
110
|
+
if type == 'page'
|
111
|
+
file = File.join('pages', options[:dest])
|
112
|
+
system("/usr/bin/editor #{file}")
|
113
|
+
elsif type == 'post'
|
114
|
+
file = File.join('posts', 'new', 'new.post')
|
115
|
+
system("/usr/bin/editor #{file}")
|
116
|
+
gather_new_posts
|
117
|
+
end
|
118
|
+
|
119
|
+
if File.exists?(file)
|
120
|
+
puts "Added a #{type}."
|
121
|
+
else
|
122
|
+
puts "Cancelled adding a #{type}."
|
123
|
+
end
|
124
|
+
|
125
|
+
else
|
126
|
+
# Copy the file that will be the new page/post
|
127
|
+
if type == 'page'
|
128
|
+
FileUtils.cp(options[:file], File.join('pages', options[:dest]))
|
129
|
+
elsif type == 'post'
|
130
|
+
FileUtils.cp(options[:file], File.join('posts', 'new'))
|
131
|
+
gather_new_posts
|
132
|
+
end
|
133
|
+
|
134
|
+
puts "Using #{options[:file]} as a new #{type}."
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
# Deletes a page/post, identified by its ID
|
140
|
+
def delete_resource(type, id)
|
141
|
+
type.downcase!
|
142
|
+
|
143
|
+
# Find the page/post
|
144
|
+
if type == 'page'
|
145
|
+
res = @pages.select { |p| p[:id] == id }
|
146
|
+
fn = File.join(@config[:site][:root], @config[:site][:pages])
|
147
|
+
elsif type == 'post'
|
148
|
+
res = @posts.select { |p| p[:id] == id }
|
149
|
+
fn = File.join(@config[:site][:root], @config[:site][:posts])
|
150
|
+
end
|
151
|
+
|
152
|
+
# If we found a resource, delete it.
|
153
|
+
if !res.nil?
|
154
|
+
res = res[0]
|
155
|
+
fn = File.join(fn, res[:id])
|
156
|
+
File.delete(fn) if File.exists?(fn)
|
157
|
+
res.delete
|
158
|
+
puts "Deleted #{type} '#{id}'."
|
159
|
+
else
|
160
|
+
puts "No #{type} with id '#{id}'."
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
def load_metadata
|
166
|
+
@meta = @@default_meta
|
167
|
+
|
168
|
+
meta_file = File.join("metadata.yml")
|
169
|
+
|
170
|
+
# Load the metadata
|
171
|
+
if File.exists?(meta_file)
|
172
|
+
yml = YAML::load(File.open(meta_file))
|
173
|
+
@meta.merge!(yml)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
def save_metadata
|
179
|
+
meta_file = File.join("metadata.yml")
|
180
|
+
|
181
|
+
File.open(meta_file, 'w') do |f|
|
182
|
+
f.puts("# Do not touch this file, as it's auto-generated.")
|
183
|
+
YAML::dump(@meta, f)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
# Create the indices for the posts
|
189
|
+
def create_indices
|
190
|
+
destination = File.join(@config[:site][:root], @config[:site][:posts], @config[:site][:index])
|
191
|
+
Dir.mkdir(destination) if !Dir.exists?(destination)
|
192
|
+
|
193
|
+
# Clear out the indices before making them
|
194
|
+
Dir.entries(destination).each do |f|
|
195
|
+
index = File.join(destination, f)
|
196
|
+
File.delete(index) if File.file?(index)
|
197
|
+
end
|
198
|
+
|
199
|
+
temp_dir = File.join("templates")
|
200
|
+
template = Template.new(temp_dir, 'index.html', post_location=@config[:site][:posts])
|
201
|
+
indices = []
|
202
|
+
|
203
|
+
# Segment the posts into groups of 5
|
204
|
+
@posts.each_slice(5) { |posts|
|
205
|
+
indices << posts
|
206
|
+
}
|
207
|
+
|
208
|
+
# Create the indices and save them
|
209
|
+
indices.length.times { |i|
|
210
|
+
p_pg = nil
|
211
|
+
n_pg = nil
|
212
|
+
|
213
|
+
# Find the relative location (to the site) of the index
|
214
|
+
rel_index = File.join("/", @config[:site][:posts], @config[:site][:index])
|
215
|
+
|
216
|
+
# Figure out the previous/next pages, if they exist
|
217
|
+
p_pg = File.join(rel_index, i.to_s) if i > 0
|
218
|
+
n_pg = File.join(rel_index, (i+2).to_s) if i + 1 < indices.length
|
219
|
+
|
220
|
+
# Render the index page
|
221
|
+
indices[i] = template.render(indices[i], prev_page=p_pg, next_page=n_pg)
|
222
|
+
|
223
|
+
# Save the index page
|
224
|
+
index_file = File.join(destination, (i+1).to_s)
|
225
|
+
File.open(index_file, 'w') do |f|
|
226
|
+
f.print(indices[i])
|
227
|
+
end
|
228
|
+
}
|
229
|
+
end
|
230
|
+
|
231
|
+
|
232
|
+
# Publish the posts and pages
|
233
|
+
def push_content
|
234
|
+
temp_dir = File.join("templates")
|
235
|
+
|
236
|
+
# Create the post directory if it doesn't exist
|
237
|
+
destination = File.join(@config[:site][:root], @config[:site][:posts])
|
238
|
+
Dir.mkdir(destination) if !Dir.exists?(destination)
|
239
|
+
|
240
|
+
# Render and save each post to the post directory
|
241
|
+
template = Template.new(temp_dir, 'post.html')
|
242
|
+
@posts.each do |post|
|
243
|
+
post_file = File.join(destination, post[:id])
|
244
|
+
File.open(post_file, 'w') do |f|
|
245
|
+
f.print(template.render(post))
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# Create the page directory if it doesn't exist
|
250
|
+
destination = File.join(@config[:site][:root], @config[:site][:pages])
|
251
|
+
Dir.mkdir(destination) if !Dir.exists?(destination)
|
252
|
+
|
253
|
+
# Render and save each page to the page directory
|
254
|
+
template = Template.new(temp_dir, 'page.html')
|
255
|
+
@pages.each do |page|
|
256
|
+
page_file = File.join(destination, page[:id])
|
257
|
+
File.open(page_file, 'w') do |f|
|
258
|
+
f.print(template.render(page))
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
end
|
263
|
+
|
264
|
+
# Move any new posts to the saved posts directory.
|
265
|
+
def gather_new_posts
|
266
|
+
new_dir = File.join("posts", "new")
|
267
|
+
|
268
|
+
Dir.entries(new_dir).each do |f|
|
269
|
+
post_file = File.join(new_dir, f)
|
270
|
+
if File.file?(post_file)
|
271
|
+
|
272
|
+
# Save the new post to the processed directory with metadata attached
|
273
|
+
File.open(post_file) do |new_post|
|
274
|
+
date = new_post.mtime
|
275
|
+
save_path = get_unused_filename(File.join("posts", date.strftime("%Y-%m-%d")), "post")
|
276
|
+
|
277
|
+
File.open(save_path, "w") do |save_file|
|
278
|
+
save_file.puts(@meta[:last_post] + 1)
|
279
|
+
save_file.puts(date.strftime("%Y-%m-%d %H:%M:%S %z"))
|
280
|
+
save_file.print(new_post.read)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
# Remove the file from the new post directory
|
285
|
+
File.delete(post_file)
|
286
|
+
|
287
|
+
# Update the value of the last ID used
|
288
|
+
@meta[:last_post] += 1
|
289
|
+
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
# Process the pages and posts
|
295
|
+
def prepare_content
|
296
|
+
@posts = []
|
297
|
+
@pages = []
|
298
|
+
|
299
|
+
# Create a Post for each file in the posts directory
|
300
|
+
Dir.entries('posts').each do |f|
|
301
|
+
entry = File.join('posts', f)
|
302
|
+
if File.file?(entry)
|
303
|
+
@posts << Post.new(entry)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
# Create a Page for each file in the pages directory
|
308
|
+
Dir.entries('pages').each do |f|
|
309
|
+
entry = File.join('pages', f)
|
310
|
+
if File.file?(entry)
|
311
|
+
@pages << Page.new(entry)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
save_metadata
|
316
|
+
|
317
|
+
# Sort the posts by date, with most recent first
|
318
|
+
@posts.sort_by! { |post| post[:date] }
|
319
|
+
@posts.reverse!
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: den
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Peter Valdez
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-25 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description:
|
15
|
+
email: peter@someindividual.com
|
16
|
+
executables:
|
17
|
+
- den
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- bin/den
|
22
|
+
- lib/den/examples.rb
|
23
|
+
- lib/den/page.rb
|
24
|
+
- lib/den/post.rb
|
25
|
+
- lib/den/resource.rb
|
26
|
+
- lib/den/template.rb
|
27
|
+
- lib/den/utilities.rb
|
28
|
+
- lib/den.rb
|
29
|
+
- den.gemspec
|
30
|
+
homepage: https://github.com/azlyth/den
|
31
|
+
licenses: []
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ! '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
requirements: []
|
49
|
+
rubyforge_project:
|
50
|
+
rubygems_version: 1.8.11
|
51
|
+
signing_key:
|
52
|
+
specification_version: 3
|
53
|
+
summary: A really simple static-site generator.
|
54
|
+
test_files: []
|