solutus 0.0.1
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.
- checksums.yaml +7 -0
- data/bin/solutus +4 -0
- data/lib/solutus.rb +342 -0
- metadata +46 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 726e73c608c5ee52e178eb44a2b8c49b4c045c91691931a060fdea8c4d5eb4b0
|
4
|
+
data.tar.gz: e596ad97cc3e985b693d0836f80a10cd48545457e0aacb668b97599b4ac96d44
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 740a22d2d1054ff79d0a5458ceeea692e752b49cb7f20ec228592842acb2901464c09ef88e66b34ceecd1d479063be53b3006c7c19af40062900df450acd2de7
|
7
|
+
data.tar.gz: 5c6844b88e67dec102939d105f369bd65420e096e5af6d543480f594a18b504bc298cc6041f697d26a49c574f281de63b9ae9250fa7e54b3f5da7365d54d8297
|
data/bin/solutus
ADDED
data/lib/solutus.rb
ADDED
@@ -0,0 +1,342 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'yaml'
|
3
|
+
require 'sinatra/base'
|
4
|
+
require 'mustache'
|
5
|
+
require 'redcarpet'
|
6
|
+
|
7
|
+
class Solutus
|
8
|
+
DEFAULT_TEMPLATE = "default"
|
9
|
+
BLOG_TEMPLATE = "post"
|
10
|
+
BUILD_PATH = "deploy"
|
11
|
+
SITE_PATH = File.join(BUILD_PATH, "site")
|
12
|
+
STATIC_PATH = "static"
|
13
|
+
TEMPLATES_PATH = "templates"
|
14
|
+
SITE_PAGES_PATH = File.join("pages", "site-pages")
|
15
|
+
POSTS_PATH = File.join("pages", "posts")
|
16
|
+
BLOG_DATE_FORMAT = "%b %-d, %Y"
|
17
|
+
|
18
|
+
class Solutus_Server < Sinatra::Base
|
19
|
+
set :public_folder, SITE_PATH
|
20
|
+
|
21
|
+
get "/" do
|
22
|
+
send_file File.join(settings.public_folder, 'index.html')
|
23
|
+
end
|
24
|
+
|
25
|
+
get "/edit" do
|
26
|
+
redirect '/edit/'
|
27
|
+
end
|
28
|
+
|
29
|
+
get "/edit/?" do
|
30
|
+
"Edit your site!"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.command(*args)
|
35
|
+
start_time = Time.now
|
36
|
+
|
37
|
+
if args.length >= 1
|
38
|
+
if args[0] == "start"
|
39
|
+
build
|
40
|
+
serve
|
41
|
+
return
|
42
|
+
elsif args[0] == "serve"
|
43
|
+
serve
|
44
|
+
return
|
45
|
+
elsif args[0] == "build"
|
46
|
+
build
|
47
|
+
else
|
48
|
+
if args.length >= 2
|
49
|
+
if args[0] == "create"
|
50
|
+
new_project(args[1])
|
51
|
+
else
|
52
|
+
if args.length >= 3
|
53
|
+
if args[0] == "new"
|
54
|
+
if args[1] == "page"
|
55
|
+
new_page(args[2])
|
56
|
+
elsif args[1] == "post"
|
57
|
+
new_post(args[2])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
else
|
61
|
+
puts "Unknown command"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
else
|
65
|
+
puts "Not enough arguments"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end_time = Time.now
|
71
|
+
diff = end_time - start_time
|
72
|
+
puts "Finished in #{diff} seconds."
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.serve
|
76
|
+
#TODO: RESTART THE SERVER WHEN LOCAL CHANGES ARE MADE! REBUILD ERRYTHANG
|
77
|
+
puts "http://localhost:4567/site/"
|
78
|
+
Solutus_Server.run!
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.build
|
82
|
+
if File.directory?(BUILD_PATH)
|
83
|
+
FileUtils.remove_dir(BUILD_PATH)
|
84
|
+
end
|
85
|
+
Dir.mkdir(BUILD_PATH)
|
86
|
+
Dir.mkdir(SITE_PATH)
|
87
|
+
copy_static
|
88
|
+
|
89
|
+
templates = Hash.new
|
90
|
+
Dir.entries(TEMPLATES_PATH).each do |entry|
|
91
|
+
next if entry == "." || entry == ".."
|
92
|
+
puts "Loading template #{entry}"
|
93
|
+
path = File.join(TEMPLATES_PATH, entry)
|
94
|
+
if File.file?(path)
|
95
|
+
contents = ""
|
96
|
+
f = File.open(path, "r")
|
97
|
+
f.each_line do |line|
|
98
|
+
contents += line
|
99
|
+
end
|
100
|
+
templates[entry.split(".")[0]] = contents
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
Dir.entries(SITE_PAGES_PATH).each do |entry|
|
105
|
+
next if entry == "." || entry == ".."
|
106
|
+
puts "Rendering page #{entry}"
|
107
|
+
path = File.join(SITE_PAGES_PATH, entry)
|
108
|
+
if File.file?(path)
|
109
|
+
yml_text = ""
|
110
|
+
f = File.open(path, "r")
|
111
|
+
f.each_line do |line|
|
112
|
+
yml_text += line
|
113
|
+
end
|
114
|
+
data = YAML.load(yml_text)
|
115
|
+
html = render_page(templates, data, false)
|
116
|
+
new_path = File.join(SITE_PATH, entry.split(".")[0] + ".html")
|
117
|
+
f = File.new(new_path, "w")
|
118
|
+
puts "Created #{new_path}"
|
119
|
+
f.write(html)
|
120
|
+
f.close
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
Dir.entries(POSTS_PATH).each do |entry|
|
125
|
+
next if entry == "." || entry == ".."
|
126
|
+
path = File.join(POSTS_PATH, entry)
|
127
|
+
f = File.open(path, "r")
|
128
|
+
contents = ""
|
129
|
+
f.each_line do |line|
|
130
|
+
contents += line
|
131
|
+
end
|
132
|
+
f.close
|
133
|
+
data = YAML.load(contents)
|
134
|
+
markdown_parsed = render_markdown(contents.split("---")[-1])
|
135
|
+
data["content"] = markdown_parsed
|
136
|
+
date = data["date"]
|
137
|
+
|
138
|
+
puts "Rendering blog post #{entry}"
|
139
|
+
html = render_page(templates, data, true)
|
140
|
+
|
141
|
+
dir_path = File.join(SITE_PATH, date.year.to_s, date.month.to_s, date.day.to_s)
|
142
|
+
if !File.directory?(dir_path)
|
143
|
+
FileUtils.mkdir_p(dir_path)
|
144
|
+
end
|
145
|
+
file_path = File.join(dir_path, entry.split(".")[0] + ".html")
|
146
|
+
puts "Created #{file_path}"
|
147
|
+
f = File.new(file_path, "w")
|
148
|
+
f.write(html)
|
149
|
+
f.close()
|
150
|
+
end
|
151
|
+
#TODO: CREATE SOME FCUKIN BLOG NAVIGATION HTML PAGES
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
def self.new_page(title)
|
156
|
+
file_title = title.gsub(/\s+/, "")
|
157
|
+
path = File.join(SITE_PAGES_PATH, file_title + ".yml")
|
158
|
+
if File.file?(path)
|
159
|
+
puts "Page with that name already exists."
|
160
|
+
return
|
161
|
+
end
|
162
|
+
|
163
|
+
text = <<HERE
|
164
|
+
template: default
|
165
|
+
title: #{title}
|
166
|
+
content: |
|
167
|
+
<h1>#{title}</h1>
|
168
|
+
<p>
|
169
|
+
Some Content
|
170
|
+
</p>
|
171
|
+
HERE
|
172
|
+
f = File.new(path, "w")
|
173
|
+
f.write(text)
|
174
|
+
f.close
|
175
|
+
puts "Created new site page #{title} at #{path}"
|
176
|
+
end
|
177
|
+
|
178
|
+
def self.new_post(title)
|
179
|
+
i = 1
|
180
|
+
new_title = title.gsub(/\s+/, "")
|
181
|
+
while true
|
182
|
+
path = File.join(POSTS_PATH, new_title + ".md")
|
183
|
+
if File.file?(path)
|
184
|
+
new_title = title + "#{i}"
|
185
|
+
i += 1
|
186
|
+
else
|
187
|
+
break
|
188
|
+
end
|
189
|
+
end
|
190
|
+
date = Time.now.strftime("%Y-%m-%e %I:%M:%S")
|
191
|
+
text = <<HERE
|
192
|
+
---
|
193
|
+
title: #{title}
|
194
|
+
date: #{date}
|
195
|
+
---
|
196
|
+
*This is a test blog post page!*
|
197
|
+
HERE
|
198
|
+
f = File.new(path, "w")
|
199
|
+
f.write(text)
|
200
|
+
f.close
|
201
|
+
puts "Created new blog post #{title} at #{path}"
|
202
|
+
end
|
203
|
+
|
204
|
+
def self.render_page(templates, data, blog)
|
205
|
+
if data.key?("template")
|
206
|
+
Mustache.template = templates[data["template"]]
|
207
|
+
else
|
208
|
+
Mustache.template = templates[DEFAULT_TEMPLATE]
|
209
|
+
end
|
210
|
+
result = Mustache.new
|
211
|
+
data.each do |key, val|
|
212
|
+
next if key == "template"
|
213
|
+
if key != "title"
|
214
|
+
val = wrap_element(key, val)
|
215
|
+
end
|
216
|
+
result[key.to_sym] = val
|
217
|
+
end
|
218
|
+
result[:blog] = blog
|
219
|
+
result.render
|
220
|
+
end
|
221
|
+
|
222
|
+
def self.wrap_element(key, content)
|
223
|
+
if content.is_a?(Time)
|
224
|
+
content = content.strftime(BLOG_DATE_FORMAT)
|
225
|
+
end
|
226
|
+
result = ""
|
227
|
+
result += "<div id=\"solutus-#{key}\">\n"
|
228
|
+
result += content
|
229
|
+
result += "</div>"
|
230
|
+
result
|
231
|
+
end
|
232
|
+
|
233
|
+
def self.copy_static
|
234
|
+
Dir.entries(STATIC_PATH).each do |entry|
|
235
|
+
next if entry == "." || entry == ".."
|
236
|
+
path = File.join(STATIC_PATH, entry)
|
237
|
+
if File.file?(path)
|
238
|
+
puts "Copying static file #{path}"
|
239
|
+
FileUtils.copy(path, File.join(SITE_PATH, entry))
|
240
|
+
elsif File.directory?(path)
|
241
|
+
puts "Recursively copying static dir #{path}"
|
242
|
+
FileUtils.copy_entry(path, File.join(SITE_PATH, entry))
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def self.render_markdown(markdown)
|
248
|
+
Redcarpet::Markdown.new(Redcarpet::Render::HTML.new).render(markdown)
|
249
|
+
end
|
250
|
+
|
251
|
+
def self.new_project(name)
|
252
|
+
if File.directory?(name)
|
253
|
+
puts "Invalid name, already a folder with that name"
|
254
|
+
print "Overwrite? [Y/n]"
|
255
|
+
if STDIN.gets.chomp == "Y"
|
256
|
+
FileUtils.remove_dir(name)
|
257
|
+
else
|
258
|
+
return
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
Dir.mkdir(name)
|
263
|
+
|
264
|
+
paths = Array.new
|
265
|
+
["deploy", "static", "server", "templates", "pages"].each do |dir|
|
266
|
+
paths.push(File.join(name, dir))
|
267
|
+
end
|
268
|
+
["css", "js", "imgs"].each do |dir|
|
269
|
+
paths.push(File.join(name, "static", dir))
|
270
|
+
end
|
271
|
+
["posts", "site-pages"].each do |dir|
|
272
|
+
paths.push(File.join(name, "pages", dir))
|
273
|
+
end
|
274
|
+
|
275
|
+
paths.each do |path|
|
276
|
+
Dir.mkdir(path)
|
277
|
+
end
|
278
|
+
|
279
|
+
settings_file = <<HERE
|
280
|
+
name: #{name}
|
281
|
+
author: Your Name
|
282
|
+
HERE
|
283
|
+
|
284
|
+
styles_file = <<HERE
|
285
|
+
body {
|
286
|
+
background-color: grey;
|
287
|
+
}
|
288
|
+
HERE
|
289
|
+
|
290
|
+
default_file = <<HERE
|
291
|
+
<!DOCTYPE html>
|
292
|
+
<head>
|
293
|
+
<title>{{title}}</title>
|
294
|
+
<link rel="stylesheet" type="text/css" href="/css/styles.css" />
|
295
|
+
</head>
|
296
|
+
<body>
|
297
|
+
<div id="solutus-everything">
|
298
|
+
{{#blog}}
|
299
|
+
<h1>{{title}}</h1>
|
300
|
+
{{date}}
|
301
|
+
{{/blog}}
|
302
|
+
{{{content}}}
|
303
|
+
</div>
|
304
|
+
</body>
|
305
|
+
</html>
|
306
|
+
HERE
|
307
|
+
|
308
|
+
test_file = <<HERE
|
309
|
+
title: Example Blog Post
|
310
|
+
date: 2018-05-10 03:43:20
|
311
|
+
---
|
312
|
+
*This is an example blog post page!*
|
313
|
+
HERE
|
314
|
+
|
315
|
+
index_file = <<HERE
|
316
|
+
template: default
|
317
|
+
title: Home page
|
318
|
+
content: |
|
319
|
+
<h1>Hello World!</h1>
|
320
|
+
<p>
|
321
|
+
this is a test
|
322
|
+
</p>
|
323
|
+
HERE
|
324
|
+
|
325
|
+
files = {
|
326
|
+
File.join(name, "settings.yml") => settings_file,
|
327
|
+
File.join(name, "static", "css", "styles.css") => styles_file,
|
328
|
+
File.join(name, "templates", "default.html") => default_file,
|
329
|
+
File.join(name, "pages", "posts", "test.md") => test_file,
|
330
|
+
File.join(name, "pages", "site-pages", "index.yml") => index_file,
|
331
|
+
}
|
332
|
+
|
333
|
+
files.each do |filename, contents|
|
334
|
+
puts "Created #{filename}"
|
335
|
+
f = File.new(filename, "w")
|
336
|
+
f.write(contents)
|
337
|
+
f.close
|
338
|
+
end
|
339
|
+
|
340
|
+
puts "Created new project #{name}"
|
341
|
+
end
|
342
|
+
end
|
metadata
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: solutus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jerome Wei
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-05-15 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A miminal static site generator
|
14
|
+
email: jeromew@berkeley.edu
|
15
|
+
executables:
|
16
|
+
- solutus
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- bin/solutus
|
21
|
+
- lib/solutus.rb
|
22
|
+
homepage: https://github.com/jeromew21/solutus
|
23
|
+
licenses:
|
24
|
+
- MIT
|
25
|
+
metadata: {}
|
26
|
+
post_install_message:
|
27
|
+
rdoc_options: []
|
28
|
+
require_paths:
|
29
|
+
- lib
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubyforge_project:
|
42
|
+
rubygems_version: 2.7.6
|
43
|
+
signing_key:
|
44
|
+
specification_version: 4
|
45
|
+
summary: A miminal static site generator
|
46
|
+
test_files: []
|