OK, so lets put this together. We'll have all of our files in input/
and it will spit everything out into output/
. If we find a file
called input/_layout.html
we will use that as our layout, otherwise
we'll hardcode something in the script that will use watercss. We
will add access to the site
so we can loop over pages.
simple_gen.rb
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
| #!/usr/bin/env ruby
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'front_matter_parser', "1.0.1"
gem 'tilt'
gem 'kramdown'
end
require 'tilt/erb'
require 'tilt/kramdown'
DEFAULT_LAYOUT = <<-HTML
<html>
<head>
<title><%= title %></title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.css"></link>
</head>
<body>
<nav>
<ul>
<% site.pages.each do |page| %>
<li><a href="<%= page.link %>"><%= page.title %></a></li>
<% end %>
</ul>
</nav>
<%= yield %>
</body>
</html>
HTML
class InputFile
attr_accessor :file, :parsed, :front_matter, :content
def initialize( file, prefix )
@file = file[prefix.length+1..]
@parsed = FrontMatterParser::Parser.parse_file(file)
@front_matter = @parsed.front_matter
@content = @parsed.content
end
def title
return @file if front_matter.nil?
front_matter["title"] ||= "Title"
end
def link
if File.extname(file) == ".md"
"/" + file.gsub( /.md/, ".html" )
else
"/" + file
end
end
end
class Site
attr_accessor :dir
def initialize( dir = 'input' )
@dir = dir
@files = {}
Dir.glob( "#{dir}/**/*" ).each do |file|
add_file file
end
end
def add_file file
if File.file? file
f = InputFile.new( file, @dir )
printf "%-15s %s\n", f.file, f.title
if f.file == "_layout.html"
@layout = f
else
@files[f.file] = f
end
else
puts "Skipping #{file}"
end
end
def layout
Tilt::ERBTemplate.new do
@layout.nil? ? DEFAULT_LAYOUT : @layout.content
end
end
def pages
@files.values
end
def generate
FileUtils.mkdir_p "output"
outer = layout
@files.each do |key,file|
res = outer.render( binding, title: file.title, site: self ) do
results = ERB.new( file.content ).result_with_hash( page: file, title: file.title, site: self )
if key =~ /.md$/
Kramdown::Document.new(results).to_html
else
results
end
end
output_file = "output#{file.link}"
FileUtils.mkdir_p File.dirname( output_file )
puts "Writing #{output_file}"
File.open( output_file, "w" ) { |out| out << res }
end
end
end
s = Site.new
s.generate
|
Here's some sample output:
1
2
3
4
5
6
7
8
| _layout.html Title
index.md Title
Skipping input/sub
sub/1.md First
sub/2.md Second
Writing output/index.html
Writing output/sub/1.html
Writing output/sub/2.html
|
And we could add a custom layout:
input/_layout.html
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| <!doctype html>
<html>
<head>
<title><%= title || "Title" %></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio,line-clamp"></script>
</head>
<body>
<nav>
<ul class="flex justify-between">
<% site.pages.each do |page| %>
<li class="inline-block mx-2"><a href="<%= page.link %>"><%= page.title %></a></li>
<% end %>
</ul>
</nav>
<div class="prose">
<%= yield %>
</div>
</body>
</html>
|