Browse Source

First pass at generating HTML

master
Exa Stencil 5 months ago
parent
commit
d79253ff0d
3 changed files with 164 additions and 13 deletions
  1. +2
    -0
      README.gmi
  2. +6
    -4
      example/atom.xml.erb
  3. +156
    -9
      huge.rb

+ 2
- 0
README.gmi View File

@ -31,6 +31,8 @@ example
├── footer.gmi.erb
├── header.gmi.erb
└── hello-world.gmi
1 directory, 5 files
```
## Plans


+ 6
- 4
example/atom.xml.erb View File

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<id>gemini://example.com/</id>
<id>https://example.com/</id>
<title>Example Site</title>
<updated><%= Time.now %></updated>
<link href="gemini://example.com/atom.xml" rel="self" />
<link href="<%= scheme %>://example.com/atom.xml" rel="self" />
<link href="https://example.com/" type="text/html" />
<link href="gemini://example.com/" rel="alternate" type="text/gemini" />
<author>
<name>Your Name</name>
@ -13,8 +14,9 @@
<% posts.each do |post| %>
<entry>
<title><%= post['title'] %></title>
<link href="gemini://example.com/<%= post['url'] %>" rel="alternate" type="text/gemini" />
<id>gemini://example.com/<%= post['url'] %></id>
<id>https://example.com/<%= post['url'] %></id>
<link href="https://example.com/<%= post['url'] %>" type="text/html" />
<link href="gemini://example.com/<%= post['gemini_url'] %>" rel="alternate" type="text/gemini" />
<published><%= post['published'] %></published>
<updated><%= post['updated'] %></updated>
</entry>


+ 156
- 9
huge.rb View File

@ -28,13 +28,14 @@ class Time
end
end
def generate_gemini(path, posts = [])
# Gemtext generation
def generate_gemini(path, posts)
target_path = "../public_gemini/#{path}"
target_folder = target_path.split('/')[0...-1].join('/')
target = ""
# Parse the file for metadata and content
metadata = nil
parsed_metadata = nil
content = ""
File.open path do |file|
text = file.read
@ -46,11 +47,10 @@ def generate_gemini(path, posts = [])
content = text
end
end
if metadata
metadata['updated'] = File.mtime path
metadata['url'] = path.gsub '.erb', ''
posts << metadata
end
# Gemini runs last so find metadata instead of setting it
metadata = posts.select { |p| p['url'].start_with? path.gsub('.erb', '').gsub('.gmi', '') }.first
metadata ||= parsed_metadata
metadata['gemini_url'] = path.gsub '.erb', '' if metadata
# Optional header
folder = path.split('/')[0...-1]
@ -72,7 +72,7 @@ def generate_gemini(path, posts = [])
target_path.gsub! '.erb', ''
renderer = ERB.new content, nil, '<>'
metadata ||= {}
metadata['posts'] = posts
metadata['posts'] = posts.map { |p| p['url'] = p['gemini_url']; p }
target << renderer.result_with_hash(metadata)
else
target << content
@ -100,6 +100,149 @@ def generate_gemini(path, posts = [])
end
end
def gemini_to_html(gemtext)
in_pre = false
in_list = false
in_quote = false
unlist = ->(line) {
if in_list && !line.start_with?('* ')
in_list = false
"</ul>\n"
else
""
end
}
unquote = ->(line) {
if in_quote && !line.start_with?('>')
in_quote = false
"</blockquote>\n"
else
""
end
}
gemtext.split("\n").map do |line|
if in_pre
if line.strip == '```'
in_pre = false
"</pre>"
else
line
end
else
case line
when /^# (.*)/
"#{unquote.call line}#{unlist.call line}<h1>#{$1}</h1>"
when /^## (.*)/
"#{unquote.call line}#{unlist.call line}<h2>#{$1}</h2>"
when /^## (.*)/
"#{unquote.call line}#{unlist.call line}<h3>#{$1}</h3>"
when /^```/
in_pre = true
"#{unquote.call line}#{unlist.call line}<pre>"
when /^\* (.*)/
if !in_list
in_list = true
"#{unquote.call line}<ul>\n<li>#{$1}</li>"
else
"<li>#{$1}</li>"
end
when /^>\s?(.*)/
if !in_quote
in_quote = true
"#{unlist.call line}<blockquote>\n#{$1}"
else
$1
end
when /^=>\s*([^\s]+)\s?(.*)/
"#{unquote.call line}#{unlist.call line}<p><a href='#{$1}'>#{$2 || $1}</a></p>"
else
if line.strip == ''
"#{unquote.call line}#{unlist.call line}"
else
"#{unquote.call line}#{unlist.call line}<p>#{line}</p>"
end
end
end
end.join "\n"
end
# HTML Generation
def generate_html(path, posts)
target_path = "../public_html/#{path}".gsub '.gmi', '.html'
target_folder = target_path.split('/')[0...-1].join('/')
target = ""
# Parse the file for metadata and content
metadata = nil
content = ""
File.open path do |file|
text = file.read
pieces = text.split("---\n")
if pieces.size >= 3
metadata = YAML.load(pieces[1])
content = pieces.drop(2).join("---\n")
else
content = text
end
end
if metadata
metadata['updated'] = File.mtime path
metadata['url'] = path.gsub('.erb', '').gsub '.gmi', '.html'
posts << metadata
end
# Optional header
folder = path.split('/')[0...-1]
header = (folder + %w[header.html]).join '/'
if File.exists? header
File.open header do |file|
target << file.read
end
end
header = (folder + %w[header.html.erb]).join '/'
if File.exists? header
template = File.read header
renderer = ERB.new template, nil, '<>'
target << renderer.result_with_hash(metadata)
end
# Place the content in the post
if path.end_with? '.erb'
target_path.gsub! '.erb', ''
renderer = ERB.new content, nil, '<>'
metadata ||= {}
metadata['posts'] = posts
gemini = renderer.result_with_hash(metadata)
target << gemini_to_html(gemini)
else
target << gemini_to_html(content)
end
# Optional footer
footer = (folder + %w[footer.html]).join '/'
if File.exists? footer
File.open footer do |file|
target << file.read
end
end
footer = (folder + %w[footer.html.erb]).join '/'
if File.exists? footer
template = File.read footer
renderer = ERB.new template, nil, '<>'
target << renderer.result_with_hash(metadata)
end
# Ensure the folder exists
FileUtils.mkdir_p target_folder
# Write the file
File.open target_path, 'w' do |file|
file.write target
end
end
# Store all posts for the feeds
posts = []
# Find all Gemini content
@ -110,6 +253,7 @@ Dir['**/*.gmi.erb', '**/*.gmi', 'index.gmi.erb'].each do |path|
next if File.basename(path) == 'footer.gmi.erb'
puts "Processing #{path}..."
generate_html path, posts
generate_gemini path, posts
end
@ -118,6 +262,9 @@ if File.exists? 'atom.xml.erb'
template = File.read 'atom.xml.erb'
renderer = ERB.new template, nil, '<>'
File.open '../public_gemini/atom.xml', 'w' do |file|
file.write renderer.result_with_hash(posts: posts)
file.write renderer.result_with_hash(posts: posts, scheme: 'gemini')
end
File.open '../public_html/atom.xml', 'w' do |file|
file.write renderer.result_with_hash(posts: posts, scheme: 'https')
end
end

Loading…
Cancel
Save