Skip to content

Commit d4d4016

Browse files
committed
Initial checkin: basic functionality
Currently uses fixed replace-strings as opposed to a templating engine: this requires a lot of polishing. Posting from email is a planned feature.
0 parents  commit d4d4016

File tree

5 files changed

+129
-0
lines changed

5 files changed

+129
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*~
2+
imap-settings.private

README.md

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# clayoven
2+
3+
An extremely simple website generator that operates on a very specific
4+
kind of repository. It has no dependencies, and hand-parses
5+
everything using regular expressions. Posts can optionally posted via
6+
email.
7+
8+
## Repository format
9+
10+
* There are two kinds of pages: index pages and content pages. Index
11+
pages are toplevel pages and (optionally) contain links to
12+
corresponding content pages. To specify which pages should go under
13+
which "topic" (or index), content page filenames must look like
14+
`<topic>:<permalink>`.
15+
16+
* To generate HTML from the index and content files, the repository
17+
should contain `design/template.index.html` (for index pages) and
18+
`design/template.html` (for content pages).
19+
20+
* Both index and content pages conform to the same format. The first
21+
line of file contains the title, followed by the body which is
22+
intended to be enclosed in a \<pre\> (you can change this in your
23+
template) pepper with [\d+] markers referring to links in the
24+
footer. The footer should contain "[\d+]: \<link\>" lines. The
25+
links will be turned into clickable links.
26+
27+
## Posting via email
28+
29+
clayoven includes clayovend, a daemon which constantly polls an IMAP
30+
server for new emails. Copy `imap-settings.template` to
31+
`imap-settings.private` and configure. The subject of the email
32+
should be suffixed with "# \<permalink\>".
33+
34+
## Contributing
35+
36+
Open issues and send pull requests on GitHub. You can optionally
37+
email the author your patches, if you prefer that.

clayoven.rb

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
def escape_htmlspecialchars(content)
2+
# see: http://php.net/htmlspecialchars
3+
replaces = {
4+
"&" => "&amp;",
5+
"\"" => "&quot;",
6+
"'" => "&apos;",
7+
"<" => "&lt;",
8+
">" => "&gt;"
9+
}
10+
replaces.each { |key, value| content.gsub!(key, value) }
11+
content
12+
end
13+
14+
def anchor_footerlinks(footer)
15+
footer.gsub!(/^(\[\d+\]:) (.*)/, '\1 <a href="\2">\2</a>')
16+
end
17+
18+
def main
19+
# First, make sure that the required files are present
20+
all_files = (Dir.entries(".") - [".", "..", "design", ".git"]).reject { |file|
21+
/\.html$/ =~ file
22+
}
23+
if not all_files.include? "index"
24+
puts "error: index file not found; aborting"
25+
exit 1
26+
end
27+
28+
["template.index.html", "template.html"].each { |file|
29+
if not Dir.entries("design").include? file
30+
puts "error: design/#{file} file not found; aborting"
31+
exit 1
32+
end
33+
}
34+
35+
# Next, look for stray files
36+
index_files = ["index"] + all_files.select { |file| /\.index/ =~ file }
37+
topics = index_files.map { |file| file.split(".index")[0] }
38+
content_files = all_files - index_files
39+
(content_files.reject { |file| topics.include? (file.split(":", 2)[0]) })
40+
.each { |stray_file|
41+
content_files = content_files - [stray_file]
42+
puts "warning: #{stray_file} is a stray file; ignored"
43+
}
44+
45+
# Generate all the pages
46+
(index_files + content_files).each { |file|
47+
if file == "index"
48+
target = "index.html"
49+
permalink = file
50+
template = IO.read("design/template.index.html")
51+
elsif index_files.include? file
52+
target = file.sub(".index", ".html")
53+
permalink = file.split(".index")[0]
54+
template = IO.read("design/template.index.html")
55+
else
56+
target = "#{file.split(':', 2)[1]}.html"
57+
permalink = file.split(":", 2)[0]
58+
template = IO.read("design/template.html")
59+
end
60+
content = escape_htmlspecialchars(IO.read file)
61+
title, rest = content.split("\n\n", 2)
62+
begin
63+
# Optional footer
64+
body, partial_footer = rest.split("\n\n[1]: ", 2)
65+
footer = "\n\n[1]: #{partial_footer}"
66+
rescue
67+
end
68+
anchor_footerlinks footer if footer
69+
["permalink", "title", "body", "footer"].each { |template_var|
70+
template.gsub!("\{% #{template_var} %\}", eval(template_var))
71+
}
72+
File.open(target, mode="w") { |targetio|
73+
nbytes = targetio.write(template)
74+
puts "[GEN] #{target} (#{nbytes} bytes out)"
75+
}
76+
}
77+
end
78+
79+
main

clayovend.rb

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
imap = Net::IMAP.new('mail.example.com')
2+
imap.authenticate('LOGIN', 'joe_user', 'joes_password')
3+
imap.examine('INBOX')
4+
imap.search(["RECENT"]).each do |message_id|
5+
envelope = imap.fetch(message_id, "ENVELOPE")[0].attr["ENVELOPE"]
6+
puts "#{envelope.from[0].name}: \t#{envelope.subject}"
7+
end

imap-settings.template

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
username: publish@artagnon.com
2+
password:
3+
server: imap.gmail.com
4+
port: 993

0 commit comments

Comments
 (0)