etblog 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f8f54c99f9525eaf6bc88d00b08e8fa36c3c0a41d1b7f1792ecb0e4cbd26cddb
4
+ data.tar.gz: 9e4f74ba1b718cbeb1f443cc7c6a41eb7e207bcb81d08db20417a5cd5b5996d1
5
+ SHA512:
6
+ metadata.gz: 1ea5499df4b76e876bc98093d0f4093b68a881b7a26165586e35eee543a3b57229614fa6228efca44afab0d8bd01ce164f8ab2c9cfa3f5a857fe4b24f2c6c72c
7
+ data.tar.gz: 3324141ce656a3885dc98ae533fbb6ff4710d5dc7da7f39b0324427979955f01881f11334ba58f9d236496ea12be9aac107c738025a99acd83f7c2e271d9e92f
data/bin/etblog ADDED
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+ require 'etblog'
3
+ require 'fileutils'
4
+ require 'socket'
5
+ require 'uri'
6
+
7
+ action = ARGV[0] || 'help'
8
+ if ['-help', '--help', '-h', '-?', 'help'].include? action then
9
+ puts "Usage: #{$0} init # creates a new blog in PWD"
10
+ puts " #{$0} build # compiles the blog into HTML files"
11
+ puts " #{$0} serve # starts a web server with the blog"
12
+ puts " #{$0} help # shows this help message"
13
+ exit 1
14
+ end
15
+
16
+ if action == 'init' then
17
+ ETBlogCore.new(Dir.pwd)
18
+ puts "Created a new ETBlog blog in #{Dir.pwd}."
19
+ puts ""
20
+ puts "What to do next?"
21
+ puts " - Add some blog posts. It's simple. Just create a Markdown file with the prefix \"post-\" prepended before the actual filename, open it in your favorite editor and start editing. No need to specify the date or front matters."
22
+ puts " Example for macOS and Linux users:"
23
+ puts " touch post-hello.md"
24
+ puts " echo \"# Hello world\" > post-hello.md"
25
+ puts " echo \"Look how cool my new blog is\" >> post-hello.md"
26
+ puts " #{$0} build"
27
+ puts ""
28
+ puts " - Add a new theme. By default, the theme that comes with ETBlog looks really old-fashioned. Try adapting an existing Bootstrap or UIKit theme. Notice that a theme cannot contain any internal JavaScript or CSS dependencies - it can only use extenal libraries and JS, such as Bootstrap from CDNJS. After you are finished with the theme, save it to \"index.html\". And yes, you should definetly check out this guide on creating themes: http://timkoi.gitlab.io/etblog/newtheme"
29
+ puts " - Build your blog. The resulting blog files with be placed into \"static\". Copy over that folder onto GitLab Pages or your web server and enjoy your new blog!"
30
+ puts ""
31
+ puts "Have a great time using ETBlog!"
32
+ elsif action == 'build' || action == 'make' then
33
+ ETBlogCore.new(Dir.pwd).build
34
+ puts "Done!"
35
+ elsif action == 'serve' || action == 'server' || action == 'demo' then
36
+ if not File.exists? Dir.pwd + '/blog.plist' then
37
+ raise "There is no blog in #{Dir.pwd} - blog.plist does not exist. Try running \"#{$0} init\" first?"
38
+ end
39
+ temp_dir = "/tmp/etblogdemo#{rand(9999)}"
40
+ if ENV['OS'] == 'Windows_NT' then
41
+ temp_dir = Dir.pwd + '/' + File.dirname(test_dir)
42
+ end
43
+ if File.directory? temp_dir then
44
+ FileUtils.rm_rf(temp_dir)
45
+ end
46
+ port = ARGV[1] || 8080
47
+ if String === port then
48
+ port = port.to_i
49
+ end
50
+ puts "Running on port #{port}..."
51
+ server = TCPServer.new('0.0.0.0', port)
52
+ loop do
53
+ socket = server.accept
54
+ ETBlogCore.new(Dir.pwd, temp_dir).build
55
+ path = temp_dir + '/' + socket.gets.split(' ')[1]
56
+ if File.directory? path then
57
+ path += '/index.html'
58
+ end
59
+ if not File.exists? path then
60
+ socket.print "HTTP/1.1 404 Not Found\r\n"
61
+ socket.print "Content-Type: text/plain\r\n"
62
+ socket.print "Connection: close\r\n\r\n"
63
+ socket.print "NOT FOUND"
64
+ else
65
+ socket.print "HTTP/1.1 200 OK\r\n"
66
+ socket.print "Content-Type: text/html\r\n"
67
+ socket.print "Connection: close\r\n\r\n"
68
+ socket.print File.read(path)
69
+ end
70
+ socket.close
71
+ FileUtils.rm_rf(temp_dir)
72
+ end
73
+ else
74
+ raise "Unknown action - \"#{action}\"."
75
+ end
76
+
77
+ exit 0
data/lib/etblog.rb ADDED
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env ruby
2
+ # etblog.rb - Extremely Tiny Blog
3
+ require 'plist'
4
+ require 'kramdown'
5
+ require 'fileutils'
6
+
7
+ def maplists(list1, list2)
8
+ hash = {}
9
+ index2 = -1
10
+ list1.each do |item|
11
+ index2 += 1
12
+ hash[item] = list2[index2]
13
+ end
14
+ return hash
15
+ end
16
+
17
+ class String
18
+ def unxml
19
+ inside_tag = false
20
+ out = ''
21
+ self.split('').each do |item|
22
+ if item == '<' then
23
+ inside_tag = true
24
+ elsif item == '>' then
25
+ inside_tag = false
26
+ elsif inside_tag == false then
27
+ out += item
28
+ end
29
+ end
30
+ return out
31
+ end
32
+ end
33
+
34
+ class ETBlogCore
35
+ def initialize(folder, static_custom=nil)
36
+ if not File.directory? folder then
37
+ raise 'No such directory - ' + folder
38
+ end
39
+ @base = folder.clone
40
+ @output = @base + '/htdocs'
41
+ @conf = @base + '/blog.plist'
42
+ if not File.exists? @conf then
43
+ File.write(@conf, { 'Title' => 'Blog',
44
+ 'Author' => ENV['USER'] || 'You',
45
+ 'Static' => 'static',
46
+ 'Description' => 'Your new ETBlog blog.'}.to_plist )
47
+ end
48
+ plist_parsed = Plist.parse_xml(@conf)
49
+ @title = plist_parsed['Title']
50
+ @author = plist_parsed['Author']
51
+ @static = @base + '/' + plist_parsed['Static'].to_s
52
+ if static_custom != nil then
53
+ @static = static_custom.clone
54
+ end
55
+ @description = plist_parsed['Description'] || 'Your new ETBlog blog.'
56
+ @description += '<br><p>Powered by <a href="http://timkoi.gitlab.io/etblog">ETBlog</a>.</p>'
57
+ if not File.directory? @static then
58
+ FileUtils.mkdir_p(@static)
59
+ end
60
+ @links = []
61
+ plist_parsed.keys.each do |key|
62
+ if not ['Title', 'Author', 'Static', 'Description'].include? key then
63
+ @links.push("<li><a href=\"#{plist_parsed[key]}\">#{key}</a></li>")
64
+ end
65
+ end
66
+ if @links.length < 1 then
67
+ @links.push("<li><a href=\"http://timkoi.gitlab.io/etblog\">ETBlog homepage</a></li>")
68
+ @links.push("<li><a href=\"http://github.com/timkoi\">@timkoi on GitHub</a></li>")
69
+ end
70
+ end
71
+
72
+ def findimages(string)
73
+ possible_image = false
74
+ inside_image_tag = false
75
+ img = ''
76
+ out = []
77
+ string.split('').each do |item|
78
+ if item == '!' then
79
+ possible_image = true
80
+ elsif item == '(' && possible_image then
81
+ possible_image = false
82
+ inside_image_tag = true
83
+ elsif item == ')' && inside_image_tag then
84
+ inside_image_tag = false
85
+ out.push(img.clone)
86
+ img = ''
87
+ elsif inside_image_tag then
88
+ img += item
89
+ end
90
+ end
91
+ return out
92
+ end
93
+
94
+ def conv(string, put_ctnt)
95
+ return string.to_s.gsub('@{post}', put_ctnt).gsub('@{title}', @title).gsub('@{description}', @description).gsub('@{links}', '<ul>' + @links.join("") + '</ul>').gsub('@{author}', @author).gsub("@{year}", Time.now.year.to_s)
96
+ end
97
+
98
+ def build
99
+ if not File.exists? @base + '/index.html' then
100
+ FileUtils.cp(File.absolute_path(File.dirname(__FILE__)) + '/index-default-etblog.html', @base + '/index.html')
101
+ end
102
+ newest_post = ''
103
+ all_posts = Dir.glob(@base + '/post-*.md').sort_by{ |f| File.mtime(f) }.reverse
104
+ all_posts_headings = []
105
+ all_posts_outputs = []
106
+ ctnt_homepage = ''
107
+ file_first = true
108
+ all_posts.each do |item|
109
+ output = '/posts/' + File.basename(item) + '/index.html'
110
+ all_posts_outputs.push(output.clone)
111
+ output = @static + output
112
+ if not File.directory? File.dirname(output) then
113
+ FileUtils.mkdir_p(File.dirname(output))
114
+ end
115
+ FileUtils.cp(@base + '/index.html', output)
116
+ ctnt = File.read(output)
117
+ put_ctnt = File.read(item)
118
+ all_images = self.findimages(put_ctnt)
119
+ all_images.each do |item|
120
+ if File.exists? @base + '/' + item then
121
+ FileUtils.cp(@base + '/' + item, File.dirname(output) + '/' + item)
122
+ end
123
+ end
124
+ heading = Kramdown::Document.new(put_ctnt.gsub("\r\n", "\n").split("\n")[0]).to_html.unxml
125
+ all_posts_headings.push(heading)
126
+ put_ctnt = "<p><a href=\"../../index.html\">< Back to the homepage</a></p><br>" + Kramdown::Document.new(put_ctnt).to_html
127
+ ctnt = self.conv(ctnt, put_ctnt)
128
+ File.write(output, ctnt)
129
+ puts "#{item} => #{output}"
130
+ if newest_post == '' || File.mtime(newest_post) < File.mtime(item) then
131
+ newest_post = item
132
+ end
133
+ end
134
+ ctnt_for_main = ''
135
+ maplists(all_posts_headings, all_posts).each do |key, value|
136
+ ctnt_for_main += "<h2><a href=\"posts/#{File.basename(value)}/index.html\">#{key}</a></h2>"
137
+ ctnt_for_main += "<p><i style=\"color: darkgrey;\">Posted on #{File.mtime(value).to_s} by #{@author}</i></p>"
138
+ ctnt_for_main += "<hr>"
139
+ end
140
+ if ctnt_for_main == '' then
141
+ ctnt_for_main = 'Nothing was posted on this blog yet. Stay tuned!'
142
+ end
143
+ File.write(@static + '/index.html', self.conv(File.read(@base + '/index.html'), ctnt_for_main))
144
+ end
145
+ end
146
+
@@ -0,0 +1,29 @@
1
+ <html>
2
+ <head>
3
+ <title>@{title}</title>
4
+ </head>
5
+ <body style="font-family: Helvetica;">
6
+ <div style="background-color: slateblue; color: white; border: 2px solid slateblue;">
7
+ <h1> @{title}</title>
8
+ </div>
9
+ <table style="width: 100%">
10
+ <tr>
11
+ <td style="width: 80%" valign="top">
12
+ @{post}
13
+ </td>
14
+ <td valign="top">
15
+ <h4>Links</h4>
16
+ @{links}
17
+ </h4>
18
+ <h4>About this blog</h4>
19
+ @{description}
20
+ </h4>
21
+ <h4>About this theme</h4>
22
+ This is a demo theme that is used as a placeholder. Please customize it because, as you know, it is lightweight, but it is also ugly.
23
+ </td>
24
+ </tr>
25
+ </table>
26
+ <hr>
27
+ <p><i style="color: darkgrey;">Copyright (C) @{author} @{year}.</i></p>
28
+ </body>
29
+ </html>
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: etblog
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Tim K
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-08-22 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A really tiny static blog generator written in Ruby.
14
+ email: timprogrammer@rambler.ru
15
+ executables:
16
+ - etblog
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/etblog
21
+ - lib/etblog.rb
22
+ - lib/index-default-etblog.html
23
+ homepage: http://timkoi.gitlab.io/etblog
24
+ licenses:
25
+ - MIT
26
+ metadata: {}
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubygems_version: 3.0.4
43
+ signing_key:
44
+ specification_version: 4
45
+ summary: A really tiny static blog generator written in Ruby.
46
+ test_files: []