solutus 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/solutus.rb +169 -92
- data/resources/404.html +27 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4aeee0bf89def35ee1d8f9ef1679c8922068575c9804df2be0a2bc9a077f4aec
|
4
|
+
data.tar.gz: f0a0ea1447c199be711a07834bfee3ddd02cb0bbaad75f627527648dc92c3948
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd52de693cd3915faf620286dbdaeabfafa5dc47a7fb82cfac1cb72ecc0b48ccdc100d70712a0150217803b3392a1de8520a27df1399d434fa509e63fd396a00
|
7
|
+
data.tar.gz: 180770a7761f4368ec9c842aec46ee6b29ba28020995af4633ee39c3b8a198524878a433cbdab0de8f3f22380ba3ad5878934675627e2a8abffe14de0a6acdc5
|
data/lib/solutus.rb
CHANGED
@@ -7,22 +7,27 @@ require 'json'
|
|
7
7
|
require 'nokogiri'
|
8
8
|
|
9
9
|
class Solutus
|
10
|
+
ARCHIVE = "archive"
|
10
11
|
DEFAULT_TEMPLATE = "default"
|
11
12
|
BLOG_TEMPLATE = "post"
|
12
13
|
BUILD_PATH = "deploy"
|
13
14
|
SITE_PATH = File.join(BUILD_PATH, "site")
|
14
|
-
BLOG_BUILD_PATH = File.join(SITE_PATH,
|
15
|
+
BLOG_BUILD_PATH = File.join(SITE_PATH, ARCHIVE)
|
15
16
|
STATIC_PATH = "static"
|
16
17
|
TEMPLATES_PATH = "templates"
|
17
18
|
SITE_PAGES_PATH = File.join("pages", "site-pages")
|
18
19
|
POSTS_PATH = File.join("pages", "posts")
|
19
20
|
BLOG_DATE_FORMAT = "%b %e, %Y"
|
20
21
|
SETTINGS_FILE = "settings.yml"
|
22
|
+
CACHE = ".solutus-cache"
|
21
23
|
DAY_ENDINGS = ["th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th", "th", "st"]
|
22
24
|
|
23
25
|
@@blog_urls = Hash.new
|
24
26
|
@@page_urls = Array.new
|
25
27
|
|
28
|
+
class SolutusStache < Mustache
|
29
|
+
end
|
30
|
+
|
26
31
|
def self.load_settings
|
27
32
|
begin
|
28
33
|
yml_text = ""
|
@@ -33,7 +38,7 @@ class Solutus
|
|
33
38
|
f.close
|
34
39
|
YAML.load(yml_text)
|
35
40
|
rescue
|
36
|
-
puts "settings.yml not found"
|
41
|
+
puts "Not a Solutus Project (yet) --- settings.yml not found"
|
37
42
|
end
|
38
43
|
end
|
39
44
|
|
@@ -114,11 +119,35 @@ class Solutus
|
|
114
119
|
"saved post @ #{path}"
|
115
120
|
end
|
116
121
|
|
122
|
+
get "/:page" do
|
123
|
+
path = File.join(settings.public_folder, params['page'], 'index.html')
|
124
|
+
if File.file?(path)
|
125
|
+
send_file path
|
126
|
+
else
|
127
|
+
send_404
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
get "/archive/:year/:month/:day/:title" do
|
132
|
+
path = File.join(settings.public_folder, ARCHIVE,
|
133
|
+
params['year'], params["month"], params["day"], params["title"],
|
134
|
+
'index.html')
|
135
|
+
if File.file?(path)
|
136
|
+
send_file path
|
137
|
+
else
|
138
|
+
send_404
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def send_404
|
143
|
+
send_file File.join(path_to_resources, "404.html")
|
144
|
+
end
|
145
|
+
|
117
146
|
def path_to_resources
|
118
147
|
File.join(File.dirname(File.expand_path(__FILE__)), '../resources')
|
119
148
|
end
|
120
149
|
|
121
|
-
class ServerStache < Mustache
|
150
|
+
class ServerStache < Mustache
|
122
151
|
end
|
123
152
|
|
124
153
|
def render_edit_page(path)
|
@@ -147,6 +176,7 @@ class Solutus
|
|
147
176
|
page_html = Solutus.render_page(Solutus.templates, settings.global_settings, data)
|
148
177
|
parser = Nokogiri::HTML(page_html)
|
149
178
|
parser.at_css("#solutus-content")['contenteditable'] = true
|
179
|
+
parser.at_css("#solutus-content")['style'] = "border: 1px black dashed"
|
150
180
|
result[:everything] = parser.at_css("#solutus-everything")
|
151
181
|
result.render
|
152
182
|
end
|
@@ -159,8 +189,8 @@ class Solutus
|
|
159
189
|
end
|
160
190
|
f.close
|
161
191
|
|
162
|
-
|
163
|
-
result =
|
192
|
+
SolutusStache.template = template
|
193
|
+
result = SolutusStache.new
|
164
194
|
|
165
195
|
f = File.open(path, "r")
|
166
196
|
file_contents = ""
|
@@ -184,8 +214,8 @@ class Solutus
|
|
184
214
|
template += line
|
185
215
|
end
|
186
216
|
f.close
|
187
|
-
|
188
|
-
result =
|
217
|
+
SolutusStache.template = template
|
218
|
+
result = SolutusStache.new
|
189
219
|
settings.global_settings.each do |key, val|
|
190
220
|
result[key.to_sym] = val
|
191
221
|
end
|
@@ -239,15 +269,18 @@ class Solutus
|
|
239
269
|
if args.length >= 1
|
240
270
|
if args[0] == "deploy"
|
241
271
|
deploy
|
242
|
-
elsif args[0] == "
|
272
|
+
elsif args[0] == "build"
|
243
273
|
build
|
274
|
+
elsif args[0] == "serve"
|
275
|
+
build #right now, the server won't werve unless its built.
|
276
|
+
#consider serializing data in cache to save time.
|
277
|
+
#TODO: Stress test the build for speed.
|
244
278
|
serve
|
245
279
|
return
|
246
|
-
elsif args[0] == "
|
280
|
+
elsif args[0] == "start"
|
281
|
+
build
|
247
282
|
serve
|
248
283
|
return
|
249
|
-
elsif args[0] == "build"
|
250
|
-
build
|
251
284
|
elsif args[0] == "publish"
|
252
285
|
build
|
253
286
|
deploy
|
@@ -270,7 +303,7 @@ class Solutus
|
|
270
303
|
end
|
271
304
|
end
|
272
305
|
else
|
273
|
-
puts "Unknown command"
|
306
|
+
puts "Unknown command."
|
274
307
|
return
|
275
308
|
end
|
276
309
|
end
|
@@ -278,20 +311,22 @@ class Solutus
|
|
278
311
|
|
279
312
|
end_time = Time.now
|
280
313
|
diff = end_time - start_time
|
281
|
-
puts "
|
314
|
+
puts "Completed in #{diff} seconds."
|
282
315
|
end
|
283
316
|
|
284
317
|
def self.deploy
|
318
|
+
puts "Solutus is deploying"
|
285
319
|
system load_settings["deploy-command"]
|
286
320
|
end
|
287
321
|
|
288
322
|
def self.serve
|
289
|
-
|
290
|
-
puts "http://localhost:4567/
|
323
|
+
puts "Solutus is serving"
|
324
|
+
puts "View at http://localhost:4567/"
|
291
325
|
Solutus_Server.run!
|
292
326
|
end
|
293
327
|
|
294
328
|
def self.build
|
329
|
+
puts "Solutus is building the static site"
|
295
330
|
settings_data = load_settings
|
296
331
|
|
297
332
|
if File.directory?(BUILD_PATH)
|
@@ -316,30 +351,7 @@ class Solutus
|
|
316
351
|
end
|
317
352
|
end
|
318
353
|
|
319
|
-
|
320
|
-
Dir.entries(SITE_PAGES_PATH).each do |entry|
|
321
|
-
next if entry == "." || entry == ".."
|
322
|
-
puts "Rendering page #{entry}"
|
323
|
-
path = File.join(SITE_PAGES_PATH, entry)
|
324
|
-
if File.file?(path)
|
325
|
-
yml_text = ""
|
326
|
-
f = File.open(path, "r")
|
327
|
-
f.each_line do |line|
|
328
|
-
yml_text += line
|
329
|
-
end
|
330
|
-
data = YAML.load(yml_text)
|
331
|
-
html = render_page(@@templates, settings_data, data, false)
|
332
|
-
new_path = File.join(SITE_PATH, entry.split(".")[0] + ".html")
|
333
|
-
f = File.new(new_path, "w")
|
334
|
-
puts "Created #{new_path}"
|
335
|
-
f.write(html)
|
336
|
-
f.close
|
337
|
-
@@page_urls.push({
|
338
|
-
"title" => data["title"],
|
339
|
-
"file_path" => path
|
340
|
-
})
|
341
|
-
end
|
342
|
-
end
|
354
|
+
yaml_data = Hash.new
|
343
355
|
|
344
356
|
@@blog_urls = Hash.new
|
345
357
|
Dir.entries(POSTS_PATH).each do |entry|
|
@@ -351,27 +363,46 @@ class Solutus
|
|
351
363
|
contents += line
|
352
364
|
end
|
353
365
|
f.close
|
366
|
+
|
367
|
+
yaml_data[entry] = contents
|
354
368
|
data = YAML.load(contents)
|
355
|
-
markdown_parsed = render_markdown(contents.split("---")[-1])
|
356
|
-
data["content"] = markdown_parsed
|
357
369
|
date = data["date"]
|
358
|
-
|
359
|
-
puts "Rendering blog post #{entry}"
|
360
|
-
html = render_page(@@templates, settings_data, data, true)
|
361
|
-
|
362
|
-
relative_dir = File.join(date.year.to_s, date.month.to_s, date.day.to_s)
|
363
|
-
root_url = File.join("archive", relative_dir, entry.split(".")[0] + ".html")
|
364
|
-
|
370
|
+
relative_dir = File.join(date.year.to_s, date.month.to_s, date.day.to_s, entry.split(".")[0])
|
365
371
|
year = date.year.to_s
|
366
372
|
if !@@blog_urls.key?(year)
|
367
373
|
@@blog_urls[year] = Array.new
|
368
374
|
end
|
369
375
|
@@blog_urls[year].push({
|
370
376
|
"title" => data["title"],
|
371
|
-
"url" =>
|
377
|
+
"url" => File.join(ARCHIVE, relative_dir),
|
372
378
|
"file_path" => path,
|
373
379
|
"date" => date
|
374
380
|
})
|
381
|
+
end
|
382
|
+
|
383
|
+
recents_count = 3
|
384
|
+
recents = ""
|
385
|
+
get_recents(recents_count).reverse.each do |post|
|
386
|
+
url = post["url"]
|
387
|
+
title = post["title"]
|
388
|
+
recents += "<div class=\"solutus-recent-posts\"><a href=\"#{url}\">#{title}</a></div>"
|
389
|
+
end
|
390
|
+
|
391
|
+
yaml_data.each do |entry, contents|
|
392
|
+
path = File.join(POSTS_PATH, entry)
|
393
|
+
data = YAML.load(contents)
|
394
|
+
markdown_parsed = render_markdown(contents.split("---")[-1])
|
395
|
+
data["content"] = markdown_parsed
|
396
|
+
data["recents"] = recents
|
397
|
+
date = data["date"]
|
398
|
+
|
399
|
+
puts "Rendering blog post #{entry}"
|
400
|
+
html = render_page(@@templates, settings_data, data, true)
|
401
|
+
|
402
|
+
relative_dir = File.join(date.year.to_s, date.month.to_s, date.day.to_s, entry.split(".")[0])
|
403
|
+
root_url = File.join(ARCHIVE, relative_dir, "index.html")
|
404
|
+
|
405
|
+
year = date.year.to_s
|
375
406
|
|
376
407
|
dir_path = File.join(BLOG_BUILD_PATH, relative_dir)
|
377
408
|
if !File.directory?(dir_path)
|
@@ -382,9 +413,43 @@ class Solutus
|
|
382
413
|
f = File.new(file_path, "w")
|
383
414
|
f.write(html)
|
384
415
|
f.close()
|
385
|
-
end
|
416
|
+
end
|
386
417
|
|
387
|
-
|
418
|
+
@@page_urls = Array.new
|
419
|
+
Dir.entries(SITE_PAGES_PATH).each do |entry|
|
420
|
+
next if entry == "." || entry == ".."
|
421
|
+
puts "Rendering page #{entry}"
|
422
|
+
path = File.join(SITE_PAGES_PATH, entry)
|
423
|
+
if File.file?(path)
|
424
|
+
yml_text = ""
|
425
|
+
f = File.open(path, "r")
|
426
|
+
f.each_line do |line|
|
427
|
+
yml_text += line
|
428
|
+
end
|
429
|
+
data = YAML.load(yml_text)
|
430
|
+
data["recents"] = recents
|
431
|
+
html = render_page(@@templates, settings_data, data, false)
|
432
|
+
new_dir = File.join(SITE_PATH, entry.split(".")[0])
|
433
|
+
if ["error", "index"].include? entry.split(".")[0]
|
434
|
+
new_path = File.join(SITE_PATH, entry.split(".")[0] + ".html")
|
435
|
+
else
|
436
|
+
if !File.directory?(new_dir)
|
437
|
+
FileUtils.mkdir_p(new_dir)
|
438
|
+
end
|
439
|
+
new_path = File.join(new_dir, "index.html")
|
440
|
+
end
|
441
|
+
f = File.new(new_path, "w")
|
442
|
+
puts "Created #{new_path}"
|
443
|
+
f.write(html)
|
444
|
+
f.close
|
445
|
+
@@page_urls.push({
|
446
|
+
"title" => data["title"],
|
447
|
+
"file_path" => path
|
448
|
+
})
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
# Create blog archive page
|
388
453
|
content = ""
|
389
454
|
@@blog_urls.each do |yr, arr|
|
390
455
|
sorted = arr.sort_by {|k| k["date"]} .reverse
|
@@ -400,16 +465,18 @@ class Solutus
|
|
400
465
|
content += "</div>"
|
401
466
|
end
|
402
467
|
end
|
403
|
-
path = File.join(SITE_PATH, "
|
468
|
+
path = File.join(SITE_PATH, ARCHIVE, "index.html")
|
404
469
|
data = Hash.new
|
405
470
|
data["title"] = "Archive"
|
406
471
|
data["content"] = content
|
472
|
+
data["recents"] = recents
|
407
473
|
html = render_page(@@templates, settings_data, data, false)
|
408
474
|
f = File.new(path, "w")
|
409
475
|
f.write(html)
|
410
476
|
f.close
|
411
477
|
puts "Created blog archive @ #{path}"
|
412
478
|
|
479
|
+
# Mirror build
|
413
480
|
if settings_data["mirror"]
|
414
481
|
dir_path = settings_data["mirror"]
|
415
482
|
FileUtils.rm_rf("#{dir_path}/.", secure: true)
|
@@ -417,6 +484,28 @@ class Solutus
|
|
417
484
|
end
|
418
485
|
end
|
419
486
|
|
487
|
+
def self.render_page(templates, default_data, data, blog=false)
|
488
|
+
if data.key?("template")
|
489
|
+
SolutusStache.template = templates[data["template"]]
|
490
|
+
else
|
491
|
+
SolutusStache.template = templates[DEFAULT_TEMPLATE]
|
492
|
+
end
|
493
|
+
result = SolutusStache.new
|
494
|
+
default_data.each do |key, val|
|
495
|
+
result[key.to_sym] = val
|
496
|
+
end
|
497
|
+
data.each do |key, val|
|
498
|
+
next if key == "template"
|
499
|
+
if key != "title"
|
500
|
+
val = wrap_element(key, val)
|
501
|
+
end
|
502
|
+
result[key.to_sym] = val
|
503
|
+
end
|
504
|
+
result[:blog] = blog
|
505
|
+
result[:year] = Time.now.year
|
506
|
+
result.render
|
507
|
+
end
|
508
|
+
|
420
509
|
def self.new_page(title)
|
421
510
|
file_title = title.gsub(/\s+/, "")
|
422
511
|
path = File.join(SITE_PAGES_PATH, file_title + ".yml")
|
@@ -440,10 +529,6 @@ HERE
|
|
440
529
|
puts "Created new site page #{title} at #{path}"
|
441
530
|
end
|
442
531
|
|
443
|
-
def self.correct_time(time)
|
444
|
-
time.utc.localtime("+05:30")
|
445
|
-
end
|
446
|
-
|
447
532
|
def self.new_post(title)
|
448
533
|
i = 1
|
449
534
|
new_title = title.gsub(/\s+/, "")
|
@@ -475,38 +560,6 @@ HERE
|
|
475
560
|
path
|
476
561
|
end
|
477
562
|
|
478
|
-
def self.render_page(templates, default_data, data, blog=false)
|
479
|
-
if data.key?("template")
|
480
|
-
Mustache.template = templates[data["template"]]
|
481
|
-
else
|
482
|
-
Mustache.template = templates[DEFAULT_TEMPLATE]
|
483
|
-
end
|
484
|
-
result = Mustache.new
|
485
|
-
default_data.each do |key, val|
|
486
|
-
result[key.to_sym] = val
|
487
|
-
end
|
488
|
-
data.each do |key, val|
|
489
|
-
next if key == "template"
|
490
|
-
if key != "title"
|
491
|
-
val = wrap_element(key, val)
|
492
|
-
end
|
493
|
-
result[key.to_sym] = val
|
494
|
-
end
|
495
|
-
result[:blog] = blog
|
496
|
-
result.render
|
497
|
-
end
|
498
|
-
|
499
|
-
def self.wrap_element(key, content)
|
500
|
-
if content.is_a?(Time)
|
501
|
-
content = correct_time(content).strftime(BLOG_DATE_FORMAT)
|
502
|
-
end
|
503
|
-
result = ""
|
504
|
-
result += "<div id=\"solutus-#{key}\">\n"
|
505
|
-
result += content
|
506
|
-
result += "</div>"
|
507
|
-
result
|
508
|
-
end
|
509
|
-
|
510
563
|
def self.copy_static
|
511
564
|
Dir.entries(STATIC_PATH).each do |entry|
|
512
565
|
next if entry == "." || entry == ".."
|
@@ -521,10 +574,33 @@ HERE
|
|
521
574
|
end
|
522
575
|
end
|
523
576
|
|
577
|
+
def self.get_recents(count)
|
578
|
+
res = Array.new
|
579
|
+
@@blog_urls.each do |yr, arr|
|
580
|
+
res = res + arr.sort_by {|k| k["date"]}
|
581
|
+
end
|
582
|
+
res.last(count)
|
583
|
+
end
|
584
|
+
|
585
|
+
def self.correct_time(time)
|
586
|
+
time.utc.localtime("+05:30")
|
587
|
+
end
|
588
|
+
|
524
589
|
def self.render_markdown(markdown)
|
525
590
|
Redcarpet::Markdown.new(Redcarpet::Render::HTML.new).render(markdown)
|
526
591
|
end
|
527
592
|
|
593
|
+
def self.wrap_element(key, content)
|
594
|
+
if content.is_a?(Time)
|
595
|
+
content = correct_time(content).strftime(BLOG_DATE_FORMAT)
|
596
|
+
end
|
597
|
+
result = ""
|
598
|
+
result += "<div id=\"solutus-#{key}\">\n"
|
599
|
+
result += content
|
600
|
+
result += "</div>"
|
601
|
+
result
|
602
|
+
end
|
603
|
+
|
528
604
|
def self.new_project(name)
|
529
605
|
if File.directory?(name)
|
530
606
|
puts "Invalid name, already a folder with that name"
|
@@ -539,7 +615,7 @@ HERE
|
|
539
615
|
Dir.mkdir(name)
|
540
616
|
|
541
617
|
paths = Array.new
|
542
|
-
["deploy", "static", "templates", "pages"].each do |dir|
|
618
|
+
["deploy", "static", "templates", "pages", CACHE].each do |dir|
|
543
619
|
paths.push(File.join(name, dir))
|
544
620
|
end
|
545
621
|
["css", "js", "imgs"].each do |dir|
|
@@ -560,12 +636,13 @@ domain: www.yoursite.tld
|
|
560
636
|
deploy-command: aws s3 sync --acl public-read --sse --delete deploy/site/ s3://www.yoursite.tld
|
561
637
|
watermark: |
|
562
638
|
<p style="text-align: center;">
|
563
|
-
<small>Powered by <a href="https://
|
639
|
+
<small>Powered by <a href="https://github.com/jeromew21/solutus">Solutus</a></small>
|
564
640
|
</p>
|
565
641
|
stylesheets: |
|
566
642
|
<link rel="stylesheet" type="text/css" href="/css/styles.css" />
|
567
643
|
scripts: |
|
568
|
-
<script></script>
|
644
|
+
<script></script>
|
645
|
+
recents-count: 3
|
569
646
|
HERE
|
570
647
|
|
571
648
|
styles_file = <<HERE
|
@@ -587,7 +664,7 @@ HERE
|
|
587
664
|
{{{date}}}
|
588
665
|
{{/blog}}
|
589
666
|
{{{content}}}
|
590
|
-
<small style="display: block; text-align: center;">© {{author}}</small>
|
667
|
+
<small style="display: block; text-align: center;">© {{year}} {{author}}</small>
|
591
668
|
{{{watermark}}}
|
592
669
|
</div>
|
593
670
|
{{{scripts}}}
|
data/resources/404.html
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<head>
|
3
|
+
<title>Error 404</title>
|
4
|
+
<style type="text/css">
|
5
|
+
body {
|
6
|
+
margin:40px auto;
|
7
|
+
background-color: #eeeeee;
|
8
|
+
max-width:650px;
|
9
|
+
line-height:1.6;
|
10
|
+
font-size:18px;
|
11
|
+
color:#444;
|
12
|
+
padding:0 10px;
|
13
|
+
font-family: "Segoe UI", sans-serif;
|
14
|
+
}
|
15
|
+
|
16
|
+
h1, h2, h3 {
|
17
|
+
line-height:1.2
|
18
|
+
}
|
19
|
+
</style>
|
20
|
+
</head>
|
21
|
+
|
22
|
+
<body>
|
23
|
+
<h1>Error 404: Page Not Found</h1>
|
24
|
+
<p><a href="/">Back to site</a></p>
|
25
|
+
<p><a href="/edit">Back to edit</a></p>
|
26
|
+
</body>
|
27
|
+
</html>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solutus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jerome Wei
|
@@ -75,6 +75,7 @@ extra_rdoc_files: []
|
|
75
75
|
files:
|
76
76
|
- bin/solutus
|
77
77
|
- lib/solutus.rb
|
78
|
+
- resources/404.html
|
78
79
|
- resources/editBlog.html
|
79
80
|
- resources/editPage.html
|
80
81
|
- resources/index.html
|