lei 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f87a0bde671b78a0057e812d57d56f072716df67242f9224c02c9787726c9aa2
4
+ data.tar.gz: dea85cb6c79dff5a7f188dfd376df76839ed02043833f4426f2271cb42225bf4
5
+ SHA512:
6
+ metadata.gz: ed07ec2339b7ca5dd0ff4c501604ea26d78469943f3ece112bb1a73e5716a876b61e7efe797a5232c99268cbf54fea06883da7480fd6b249f5d81a1a2ecee187
7
+ data.tar.gz: b3e6184e0e83b634b7ad11582dba6aea8a425dd73b00c366b91c01cbafc966d7d9272a1a7580764b85526fcf3d90f832332001abe1349406f7a06ac63fd3de7e
@@ -0,0 +1,116 @@
1
+ require_relative "../functions"
2
+
3
+ content = <<~CONTENT
4
+ puts "\\tController: Content"
5
+
6
+ class ContentController < Sinatra::Base
7
+
8
+ set :content_dir, "\#{$root}/content"
9
+ set :stylesheet, "content"
10
+ set :public_folder, $assets_root
11
+ set :views, $views
12
+
13
+ get "/" do
14
+ content = ContentHelpers.get_content(settings.content_dir)
15
+ redirect 404 if content.length == 0
16
+
17
+ url = request.url
18
+
19
+ ContentHelpers.time_sort(content)
20
+ contentParts = ContentHelpers.paginate(content, params, url)
21
+
22
+ slim :content, locals: {
23
+ **contentParts,
24
+ style: ContentHelpers.load_css(settings.stylesheet),
25
+ title: "Posts",
26
+ url: url
27
+ }
28
+ end
29
+
30
+ get "/post/:title" do
31
+ title = params["title"]
32
+ redirect 404 if title.nil? || title.length == 0
33
+
34
+ content = ContentHelpers.get_post(settings.content_dir, title)
35
+ redirect 404 if content.length != 1
36
+
37
+ parsed_title = title.split("-").join(" ")
38
+
39
+ slim :post, locals: {
40
+ content: ContentHelpers.parse_md(content)[0],
41
+ style: ContentHelpers.load_css(settings.stylesheet),
42
+ title: parsed_title,
43
+ url: request.url
44
+ }
45
+ end
46
+
47
+ get "/filter" do
48
+ content = ContentHelpers.get_content(settings.content_dir)
49
+
50
+ ContentHelpers.filter_content(content, params)
51
+ redirect 404 if content.length == 0
52
+
53
+ url = request.url
54
+
55
+ ContentHelpers.time_sort(content)
56
+ contentParts = ContentHelpers.paginate(content, params, url)
57
+
58
+ slim :search_results, locals: {
59
+ **contentParts,
60
+ style: ContentHelpers.load_css(settings.stylesheet),
61
+ title: "Filtered Results",
62
+ url: url
63
+ }
64
+ end
65
+
66
+ not_found do
67
+ slim :notfound, locals: { **ContentHelpers.nf_404, url: request.url }
68
+ end
69
+
70
+ end
71
+ CONTENT
72
+
73
+ custom = <<~CUSTOM
74
+ puts "\\tController: Custom"
75
+
76
+ class CustomController < Sinatra::Base
77
+
78
+ set :public_folder, $assets_root
79
+ set :views, $views
80
+
81
+ routes = YAML.load_file("\#{$root}/customlist.yml")
82
+
83
+ routes.each do |route|
84
+ name = route["name"]
85
+ path = route["path"]
86
+ puts "\\t\\t\#{path}: \#{name}"
87
+
88
+ get path do
89
+ folder = "\#{$root}/\#{name}"
90
+
91
+ content = route["content"].map { |section| "\#{folder}/\#{section}" }
92
+
93
+ slim name.to_sym, locals: {
94
+ content: ContentHelpers.parse_md(content),
95
+ style: ContentHelpers.load_css(name),
96
+ title: route["title"],
97
+ url: request.url
98
+ }
99
+ end
100
+ end
101
+
102
+ not_found do
103
+ slim :notfound, locals: { **ContentHelpers.nf_404, url: request.url }
104
+ end
105
+
106
+ end
107
+ CUSTOM
108
+
109
+ files = {
110
+ "content.rb": content,
111
+ "custom.rb": custom
112
+ }
113
+
114
+ loc = "$(pwd)/controllers"
115
+
116
+ makeFiles(files, loc)
@@ -0,0 +1,191 @@
1
+ require_relative "../functions"
2
+
3
+ content = <<~CONTENT
4
+ puts "\\tHelper: Content ---"
5
+
6
+ require "redcarpet"
7
+
8
+ module ContentHelpers
9
+
10
+ CARPET = Redcarpet::Markdown.new(
11
+ Redcarpet::Render::HTML.new({
12
+ hard_wrap: true,
13
+ highlight: true
14
+ })
15
+ )
16
+
17
+ def self.filter_content(content, params)
18
+ term = params["term"]
19
+ if !term.nil? && term.length > 2
20
+ content.reject! do |c|
21
+ post = `cat \#{c}`
22
+ !post.match?(Regexp.new(term, true))
23
+ end
24
+ end
25
+
26
+ yyyy = params["year"]
27
+ if !yyyy.nil? && yyyy.length == 4
28
+ content.reject! { |c| File::Stat.new(c).mtime.year != yyyy.to_i }
29
+ end
30
+
31
+ mm = params["month"]
32
+ if !mm.nil? && mm.length == 2
33
+ content.reject! { |c| File::Stat.new(c).mtime.month != mm.to_i }
34
+ end
35
+
36
+ dd = params["day"]
37
+ if !dd.nil? && dd.length == 2
38
+ content.reject! { |c| File::Stat.new(c).mtime.day != dd.to_i }
39
+ end
40
+ end
41
+
42
+ def self.get_content(contentDir)
43
+ all = Dir.glob("\#{contentDir}/*.md")
44
+ classified = YAML.load_file($banlist)
45
+
46
+ all - classified
47
+ end
48
+
49
+ def self.get_post(contentDir, title)
50
+ content = self.get_content(contentDir)
51
+
52
+ post = "\#{contentDir}/\#{title}.md"
53
+
54
+ content.include?(post) ? [ post ] : []
55
+ end
56
+
57
+ <<~load_css
58
+ This function reads and returns the contents of a CSS file as a string.
59
+ Its return value gets stored in a variable for ease of interpolation in
60
+ templates.
61
+ load_css
62
+
63
+ def self.load_css(filename)
64
+ `cat \#{$style_root}/\#{filename}.css`
65
+ end
66
+
67
+ def self.mp_eu(path, params, replacement)
68
+ newParams = {}
69
+ params.each { |k, v| newParams[k] = v }
70
+ replacement.each { |i, j| newParams[i] = j }
71
+ encoded = URI.encode_www_form(newParams)
72
+
73
+ "\#{path}?\#{encoded}"
74
+ end
75
+
76
+ def self.nf_404
77
+ {
78
+ title: "404: Not Found",
79
+ style: self.load_css("notfound")
80
+ }
81
+ end
82
+
83
+ def self.paginate(content, params, url)
84
+ pageParam = params["page"].to_i
85
+
86
+ page = pageParam != 0 ? pageParam : 1
87
+ pages = (content.length / 5.0).ceil
88
+
89
+ firstIndex = (page - 1) * 5
90
+ lastIndex = page * 5 - 1
91
+
92
+ path = URI(url).path
93
+ pageUrls = [ nil, nil, nil, nil ]
94
+
95
+ if page > 1
96
+ pageUrls[0] = self.mp_eu(path, params, { "page" => "1" })
97
+
98
+ prev = (page - 1).to_s
99
+ pageUrls[1] = self.mp_eu(path, params, { "page" => prev })
100
+ end
101
+
102
+ if page < pages
103
+ foll = (page + 1).to_s
104
+ pageUrls[2] = self.mp_eu(path, params, { "page" => foll })
105
+
106
+ pageUrls[3] = self.mp_eu(path, params, { "page" => pages.to_s })
107
+ end
108
+
109
+ {
110
+ content: self.parse_md(content[firstIndex..lastIndex]),
111
+ page: page,
112
+ pages: pages,
113
+ pageUrls: pageUrls
114
+ }
115
+ end
116
+
117
+ <<~parse_md
118
+ This function takes a list of filenames, reads their contents, and
119
+ utilizes the Redcarpet gem to parse them into HTML.
120
+ parse_md
121
+
122
+ def self.parse_md(filenames)
123
+ filenames.map do |filename|
124
+ content = `cat \#{filename}`
125
+ CARPET.render(content)
126
+ end
127
+ end
128
+
129
+ def self.time_sort(content)
130
+ content.sort_by! { |c| File::Stat.new(c).mtime }
131
+ content.reverse!
132
+ end
133
+
134
+ end
135
+ CONTENT
136
+
137
+ global = <<~GLOBAL
138
+ puts "\\tHelper: Global Utilities ---"
139
+
140
+ require "dotenv"
141
+
142
+ module GlobalUtils
143
+
144
+ def self.declare_globals
145
+ puts "\\t\\t--- Loading Environment Variables ---"
146
+
147
+ Dotenv.load
148
+
149
+ puts "\\t\\t--- Declaring Globals ---"
150
+
151
+ $assets_root = "\#{$root}/static"
152
+ $style_root = "\#{$assets_root}/styles"
153
+ $views = "\#{$root}/views"
154
+
155
+ $banlist = "\#{$root}/banlist.yml"
156
+
157
+ <<~AMP
158
+ AMP Static Header Parts, as of 15 APR 2018:
159
+ https://www.ampproject.org/docs/fundamentals/spec
160
+
161
+ AMP Boilerplate, as of 15 APR 2018:
162
+ https://www.ampproject.org/docs/fundamentals/spec/amp-boilerplate
163
+
164
+ amp-bind, as of 15 APR 2018:
165
+ https://www.ampproject.org/docs/reference/components/amp-bind
166
+ AMP
167
+
168
+ $amp_static_header = <<~HEADER
169
+ <meta charset="utf-8">
170
+ <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
171
+ <script async src="https://cdn.ampproject.org/v0.js"></script>
172
+ HEADER
173
+
174
+ $amp_boiler = <<~BOILER
175
+ <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
176
+ BOILER
177
+
178
+ $amp_bind = "<script async custom-element=\\"amp-bind\\" src=\\"https://cdn.ampproject.org/v0/amp-bind-0.1.js\\"></script>"
179
+ end
180
+
181
+ end
182
+ GLOBAL
183
+
184
+ files = {
185
+ "content_helpers.rb": content,
186
+ "global_utils.rb": global
187
+ }
188
+
189
+ loc = "$(pwd)/helpers"
190
+
191
+ makeFiles(files, loc)
@@ -0,0 +1,199 @@
1
+ require_relative "../functions"
2
+
3
+ banlist = <<~BANLIST
4
+ ---
5
+ # Paths of content from `$root`.
6
+
7
+ - ./banned-content.md
8
+ ...
9
+ BANLIST
10
+
11
+ config = <<~CONFIG
12
+ require "rack/deflater"
13
+ require "rack/protection"
14
+ require "sinatra"
15
+ require "slim"
16
+ require "yaml"
17
+
18
+ # Project Root
19
+
20
+ $root = File.dirname(__FILE__)
21
+
22
+ # Global Settings and Utilities
23
+
24
+ puts "--- Loading Helpers ---"
25
+
26
+ utils_root = "\#{$root}/helpers"
27
+
28
+ require "\#{utils_root}/global_utils"
29
+ GlobalUtils.declare_globals
30
+
31
+ require "\#{utils_root}/content_helpers"
32
+
33
+ # Sinatra Configuration
34
+
35
+ configure do
36
+ use Rack::Deflater
37
+ use Rack::Protection, except: [ :remote_token, :session_hijacking ]
38
+
39
+ set :server, :puma
40
+ set :bind, "0.0.0.0"
41
+ end
42
+
43
+ puts "--- Loading Controllers ---"
44
+
45
+ controllers = YAML.load_file("\#{$root}/controllerlist.yml")
46
+
47
+ controllers.each do |controller|
48
+ require "\#{$root}/controllers/\#{controller["file"]}"
49
+
50
+ map(controller["path"]) { run eval(controller["name"]) }
51
+ end
52
+ CONFIG
53
+
54
+ controllerlist = <<~CONTROLLERLIST
55
+ ---
56
+ -
57
+ file: custom
58
+ name: CustomController
59
+ path: /
60
+ -
61
+ file: content
62
+ name: ContentController
63
+ path: /content
64
+ ...
65
+ CONTROLLERLIST
66
+
67
+ customlist = <<~CUSTOMLIST
68
+ ---
69
+ -
70
+ name: welcome
71
+ path: /
72
+ title: Welcome
73
+ content:
74
+ - welcome.md
75
+ ...
76
+ CUSTOMLIST
77
+
78
+ gems = <<~GEMS
79
+ source "https://rubygems.org"
80
+
81
+ gem "dotenv", "~>2.2.1"
82
+ gem "puma", "~>3.11.3"
83
+ gem "rack", "~>2.0.4"
84
+ gem "rake", "~>12.3.1"
85
+ gem "redcarpet", "~>3.4.0"
86
+ gem "rspec", "~>3.7.0"
87
+ gem "sinatra", "~>2.0.3"
88
+ gem "slim", "~>3.0.9"
89
+ GEMS
90
+
91
+ gulp = <<~GULP
92
+ const exec = require("child_process").exec;
93
+ const gulp = require("gulp");
94
+ const pump = require("pump");
95
+
96
+ const cleanCSS = require("gulp-clean-css");
97
+ const less = require("gulp-less");
98
+
99
+ const lessFiles = `${__dirname}/src/styles/*.less`;
100
+ const excludedLess = `!${__dirname}/src/styles/_*.less`;
101
+ const cssDest = `${__dirname}/static/styles`;
102
+
103
+ async function shrink() {
104
+ console.log("** Compiling and minifying .less **");
105
+
106
+ await pump(
107
+ [
108
+ gulp.src([ lessFiles, excludedLess ]),
109
+ less(),
110
+ cleanCSS(),
111
+ gulp.dest(cssDest)
112
+ ],
113
+ function(err) {
114
+ console.log("--- err:", err);
115
+ }
116
+ );
117
+ }
118
+
119
+ gulp.task("shrink", shrink);
120
+
121
+ gulp.task("default", gulp.series("shrink", function() {
122
+ console.log("--- Starting .less watcher ---");
123
+
124
+ gulp.watch(lessFiles).on("change", shrink);
125
+ }));
126
+ GULP
127
+
128
+ ignore = <<~IGNORE
129
+ # Environment Variables
130
+ .env
131
+ nohup.out
132
+
133
+ # Certificates
134
+ *.pem
135
+ *.cert
136
+
137
+ # Mac File System Artifacts
138
+ .DS_Store
139
+
140
+ # Node.js Dependencies
141
+ node_modules
142
+
143
+ # ** Content **
144
+ # *.md
145
+ IGNORE
146
+
147
+ launch = <<~LAUNCH
148
+ #!/bin/bash
149
+
150
+ # Provide port number as argument.
151
+ puma -b tcp://0.0.0.0:$1
152
+ LAUNCH
153
+
154
+ package = <<~PACKAGE
155
+ {
156
+ "name": "project-name",
157
+ "version": "1.0.0",
158
+ "repository": "repository-url",
159
+ "author": "your-name",
160
+ "license": "MIT",
161
+ "dependencies": {
162
+ "gulp": "^4.0.0",
163
+ "gulp-clean-css": "3.10.0",
164
+ "gulp-less": "^4.0.0",
165
+ "gulp-uglify": "^3.0.0",
166
+ "pump": "3.0.0"
167
+ }
168
+ }
169
+ PACKAGE
170
+
171
+ loc = "$(pwd)"
172
+
173
+ dirs = [
174
+ "content",
175
+ "controllers",
176
+ "helpers",
177
+ "index",
178
+ "spec",
179
+ "src",
180
+ "static",
181
+ "views",
182
+ "welcome"
183
+ ]
184
+
185
+ makeDirs(dirs, loc)
186
+
187
+ files = {
188
+ ".gitignore": ignore,
189
+ "banlist.yml": banlist,
190
+ "config.ru": config,
191
+ "controllerlist.yml": controllerlist,
192
+ "customlist.yml": customlist,
193
+ "Gemfile": gems,
194
+ "gulpfile.js": gulp,
195
+ "launch.sh": launch,
196
+ "package.json": package
197
+ }
198
+
199
+ makeFiles(files, loc)