lei 0.2.0

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.
@@ -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)