flutterby 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/README.md +20 -0
- data/lib/flutterby.rb +1 -0
- data/lib/flutterby/entity.rb +8 -9
- data/lib/flutterby/file.rb +12 -43
- data/lib/flutterby/filters.rb +41 -0
- data/lib/flutterby/folder.rb +1 -1
- data/lib/flutterby/version.rb +1 -1
- metadata +4 -13
- data/in/_layout.erb +0 -19
- data/in/about.html.md +0 -3
- data/in/contact.html.erb +0 -3
- data/in/index.html.erb +0 -11
- data/in/posts/_layout.slim +0 -7
- data/in/posts/hello-world.html.md +0 -6
- data/in/posts/really-old-blog-post.html.md +0 -8
- data/in/slim-test.html.slim +0 -3
- data/in/styles.css.scss +0 -160
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6269342eafe0fdbe1eddad019ecd44ebd5aea360
|
4
|
+
data.tar.gz: 6e9c64dda3163516e527b48247546226e943be0f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d850ecf93387945baf0e1d7fdb8cf7368cd474c8c24f2d536a9a7ae6d53b0fa2b6c363a078a3ab561af88c333f66af7feb306a6a297ca337af53d3e44917e05e
|
7
|
+
data.tar.gz: 46c17e31c18fbd87c86e5795f15fdd35b3edcccf365d84305e5e828e5228b21022a2a7b4faa55961059bdad3ecf521dd52ee10956aa9d90a3e6b5eb3d9065797
|
data/README.md
CHANGED
@@ -19,6 +19,26 @@ the _experimental_ bit, though. Use with care, if at all!)
|
|
19
19
|
- Produce a fun screencast to explain what the heck is going on here!
|
20
20
|
- More tests, of course!
|
21
21
|
|
22
|
+
## How does Flutterby work?
|
23
|
+
|
24
|
+
A loose collection of notes on how Flutterby actually generates your site -- mostly intended as rubberducking with myself.
|
25
|
+
|
26
|
+
- Flutterby reads a _source directory_ and writes a static website into a _target directory_. (It can also serve a live version of your site.)
|
27
|
+
- Before it writes (or serves) anything, it reads the entire contents from the source directory into a graph of plain old Ruby objects. Each of these objects represents a file (or folder) from your site.
|
28
|
+
- Flutterby then walks this tree to write the resulting static site, optionally _applying filters_ first. For example, `index.html.md` will be exported as `index.html` after applying a Markdown filter.
|
29
|
+
- These filters can be anything that modifies the Ruby object. Some examples:
|
30
|
+
- Rendering Markdown to HTML
|
31
|
+
- Parsing and executing ERB, Slim, HAML and other templating engines
|
32
|
+
- Processing Sass, CoffeeScript and the likes
|
33
|
+
- Leaving the current body intact, but modifying file attributes like the generated file's extension
|
34
|
+
- Filters can be chained at any length you require.
|
35
|
+
- Ruby code embedded in ERB, Slim etc. templates can interact with this object graph to do funky stuff like:
|
36
|
+
- including the rendered contents of another object (ie. partials)
|
37
|
+
- query the graph for certain objects (eg. "all objects in `/posts` that have `published_at` set")
|
38
|
+
- and much more, I guess!
|
39
|
+
- When a `_layout` object is available in the same folder as the rendered object, it will be used to wrap the object's rendered output. These layout files stack, so you can have a `/posts/_layout.erb` with the layout for a single post, and a `/_layout.erb` with the layout of your site.
|
40
|
+
- When a `_view.rb` object is available in the same folder as the rendered object, it will be evaluated against the current view, allowing you to define your own view helpers. Like layouts, these will stack.
|
41
|
+
- Files and folders starting with underscores (eg. `_header.html`) will never be exported.
|
22
42
|
|
23
43
|
## License
|
24
44
|
|
data/lib/flutterby.rb
CHANGED
data/lib/flutterby/entity.rb
CHANGED
@@ -1,19 +1,18 @@
|
|
1
1
|
module Flutterby
|
2
2
|
class Entity
|
3
|
-
attr_accessor :parent
|
4
|
-
attr_reader :name, :
|
3
|
+
attr_accessor :parent, :ext
|
4
|
+
attr_reader :name, :filters, :fs_path, :data, :children
|
5
5
|
|
6
6
|
def initialize(name, parent: nil, fs_path: nil)
|
7
|
+
@parent = parent
|
7
8
|
@data = {}
|
8
9
|
reset_children!
|
9
10
|
|
10
11
|
# Extract name, extension, and filters from given name
|
11
|
-
parts
|
12
|
-
@name
|
13
|
-
@ext = parts.shift
|
12
|
+
parts = name.split(".")
|
13
|
+
@name = parts.shift
|
14
14
|
@filters = parts.reverse
|
15
|
-
|
16
|
-
self.parent = parent
|
15
|
+
@ext = @filters.last || "html"
|
17
16
|
|
18
17
|
# If a filesystem path was given, read the entity from disk
|
19
18
|
if fs_path
|
@@ -61,7 +60,7 @@ module Flutterby
|
|
61
60
|
end
|
62
61
|
|
63
62
|
def url
|
64
|
-
|
63
|
+
::File.join(parent ? parent.url : "/", full_name)
|
65
64
|
end
|
66
65
|
|
67
66
|
def full_fs_path(base:)
|
@@ -144,7 +143,7 @@ module Flutterby
|
|
144
143
|
end
|
145
144
|
|
146
145
|
def full_name
|
147
|
-
|
146
|
+
[name, ext].compact.join(".")
|
148
147
|
end
|
149
148
|
|
150
149
|
def page?
|
data/lib/flutterby/file.rb
CHANGED
@@ -8,15 +8,15 @@ require 'json'
|
|
8
8
|
|
9
9
|
module Flutterby
|
10
10
|
class File < Entity
|
11
|
-
|
11
|
+
attr_accessor :source, :body
|
12
12
|
|
13
13
|
def reload!
|
14
|
-
@
|
14
|
+
@body = nil
|
15
15
|
super
|
16
16
|
end
|
17
17
|
|
18
18
|
def read
|
19
|
-
@
|
19
|
+
@source = ::File.read(fs_path)
|
20
20
|
|
21
21
|
# Extract date from name
|
22
22
|
if name =~ %r{^(\d\d\d\d\-\d\d?\-\d\d?)\-}
|
@@ -36,32 +36,21 @@ module Flutterby
|
|
36
36
|
data = {}
|
37
37
|
|
38
38
|
# YAML Front Matter
|
39
|
-
if @
|
39
|
+
if @source.sub!(/\A\-\-\-\n(.+)\n\-\-\-\n/m, "")
|
40
40
|
data.merge! YAML.load($1)
|
41
41
|
end
|
42
42
|
|
43
43
|
# TOML Front Matter
|
44
|
-
if @
|
44
|
+
if @source.sub!(/\A\+\+\+\n(.+)\n\+\+\+\n/m, "")
|
45
45
|
data.merge! TOML.parse($1)
|
46
46
|
end
|
47
47
|
|
48
48
|
data
|
49
49
|
end
|
50
50
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
# Apply all filters
|
56
|
-
filters.each do |filter|
|
57
|
-
meth = "process_#{filter}"
|
58
|
-
if respond_to?(meth)
|
59
|
-
result = send(meth, result)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
result
|
64
|
-
end
|
51
|
+
def body
|
52
|
+
Filters.apply!(self) if @body.nil?
|
53
|
+
@body
|
65
54
|
end
|
66
55
|
|
67
56
|
def page?
|
@@ -76,31 +65,12 @@ module Flutterby
|
|
76
65
|
end
|
77
66
|
end
|
78
67
|
|
79
|
-
def process_erb(input)
|
80
|
-
tilt = Tilt["erb"].new { input }
|
81
|
-
tilt.render(view)
|
82
|
-
end
|
83
|
-
|
84
|
-
def process_slim(input)
|
85
|
-
tilt = Tilt["slim"].new { input }
|
86
|
-
tilt.render(view)
|
87
|
-
end
|
88
|
-
|
89
|
-
def process_md(input)
|
90
|
-
Slodown::Formatter.new(input).complete.to_s
|
91
|
-
end
|
92
|
-
|
93
|
-
def process_scss(input)
|
94
|
-
engine = Sass::Engine.new(input, syntax: :scss)
|
95
|
-
engine.render
|
96
|
-
end
|
97
|
-
|
98
68
|
def read_json
|
99
|
-
data.merge!(JSON.parse(
|
69
|
+
data.merge!(JSON.parse(@source))
|
100
70
|
end
|
101
71
|
|
102
72
|
def read_yaml
|
103
|
-
data.merge!(YAML.load(
|
73
|
+
data.merge!(YAML.load(@source))
|
104
74
|
end
|
105
75
|
|
106
76
|
def apply_layout(input)
|
@@ -117,7 +87,7 @@ module Flutterby
|
|
117
87
|
|
118
88
|
# Apply all layouts in order
|
119
89
|
layouts.each do |layout|
|
120
|
-
tilt = Tilt[layout.ext].new { layout.
|
90
|
+
tilt = Tilt[layout.ext].new { layout.source }
|
121
91
|
output = tilt.render(view) { output }
|
122
92
|
end
|
123
93
|
|
@@ -129,8 +99,7 @@ module Flutterby
|
|
129
99
|
end
|
130
100
|
|
131
101
|
def render(layout: true)
|
132
|
-
|
133
|
-
(layout && apply_layout?) ? apply_layout(rendered) : rendered
|
102
|
+
(layout && apply_layout?) ? apply_layout(body) : body
|
134
103
|
end
|
135
104
|
|
136
105
|
def write_static(path)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Flutterby
|
2
|
+
module Filters
|
3
|
+
def apply!(file)
|
4
|
+
body = file.source
|
5
|
+
|
6
|
+
# Apply all filters
|
7
|
+
file.filters.each do |filter|
|
8
|
+
meth = "process_#{filter}"
|
9
|
+
|
10
|
+
if Filters.respond_to?(meth)
|
11
|
+
body = Filters.send(meth, body, file)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
file.body = body
|
16
|
+
end
|
17
|
+
|
18
|
+
def process_erb(input, file)
|
19
|
+
tilt("erb", input).render(file.view)
|
20
|
+
end
|
21
|
+
|
22
|
+
def process_slim(input, file)
|
23
|
+
tilt("slim", input).render(file.view)
|
24
|
+
end
|
25
|
+
|
26
|
+
def process_md(input, file)
|
27
|
+
file.ext = "html"
|
28
|
+
Slodown::Formatter.new(input).complete.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
def process_scss(input, file)
|
32
|
+
Sass::Engine.new(input, syntax: :scss).render
|
33
|
+
end
|
34
|
+
|
35
|
+
def tilt(format, body)
|
36
|
+
Tilt[format].new { body }
|
37
|
+
end
|
38
|
+
|
39
|
+
extend self
|
40
|
+
end
|
41
|
+
end
|
data/lib/flutterby/folder.rb
CHANGED
data/lib/flutterby/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flutterby
|
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
|
- Hendrik Mans
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -241,24 +241,15 @@ files:
|
|
241
241
|
- bin/setup
|
242
242
|
- exe/flutterby
|
243
243
|
- flutterby.gemspec
|
244
|
-
- in/_layout.erb
|
245
|
-
- in/about.html.md
|
246
|
-
- in/contact.html.erb
|
247
|
-
- in/index.html.erb
|
248
|
-
- in/posts/_layout.slim
|
249
|
-
- in/posts/hello-world.html.md
|
250
|
-
- in/posts/really-old-blog-post.html.md
|
251
|
-
- in/slim-test.html.slim
|
252
|
-
- in/styles.css.scss
|
253
244
|
- lib/flutterby.rb
|
254
245
|
- lib/flutterby/cli.rb
|
255
246
|
- lib/flutterby/entity.rb
|
256
247
|
- lib/flutterby/file.rb
|
248
|
+
- lib/flutterby/filters.rb
|
257
249
|
- lib/flutterby/folder.rb
|
258
250
|
- lib/flutterby/server.rb
|
259
251
|
- lib/flutterby/version.rb
|
260
252
|
- lib/flutterby/view.rb
|
261
|
-
- out/.gitkeep
|
262
253
|
homepage: https://github.com/hmans/flutterby
|
263
254
|
licenses:
|
264
255
|
- MIT
|
@@ -279,7 +270,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
279
270
|
version: '0'
|
280
271
|
requirements: []
|
281
272
|
rubyforge_project:
|
282
|
-
rubygems_version: 2.
|
273
|
+
rubygems_version: 2.6.8
|
283
274
|
signing_key:
|
284
275
|
specification_version: 4
|
285
276
|
summary: There are many static site generators. This is mine.
|
data/in/_layout.erb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<meta charset="utf-8">
|
5
|
-
<title>The Blawg of Hendrik Mans</title>
|
6
|
-
<link rel="stylesheet" href="/styles.css">
|
7
|
-
</head>
|
8
|
-
<body>
|
9
|
-
<div class="container">
|
10
|
-
<nav role="main">
|
11
|
-
<a href="/">hmans is blogging, yo</a>
|
12
|
-
</nav>
|
13
|
-
|
14
|
-
<main role="main">
|
15
|
-
<%= yield %>
|
16
|
-
</main>
|
17
|
-
</div>
|
18
|
-
</body>
|
19
|
-
</html>
|
data/in/about.html.md
DELETED
data/in/contact.html.erb
DELETED
data/in/index.html.erb
DELETED
data/in/posts/_layout.slim
DELETED
data/in/slim-test.html.slim
DELETED
data/in/styles.css.scss
DELETED
@@ -1,160 +0,0 @@
|
|
1
|
-
@import 'https://fonts.googleapis.com/css?family=Noto+Sans:400,700,900|EB+Garamond';
|
2
|
-
|
3
|
-
$col1: steelblue;
|
4
|
-
$col2: peru;
|
5
|
-
$col3: rgb(138, 138, 138);
|
6
|
-
$col-link: #666;
|
7
|
-
|
8
|
-
$font: 16px/1.5 "Noto Sans","Helvetica Neue",Arial,sans-serif;
|
9
|
-
|
10
|
-
* { box-sizing: inherit; }
|
11
|
-
html, body { box-sizing: border-box; }
|
12
|
-
|
13
|
-
body {
|
14
|
-
font: $font;
|
15
|
-
background-color: white;
|
16
|
-
color: #333;
|
17
|
-
}
|
18
|
-
|
19
|
-
.container {
|
20
|
-
margin-left: auto;
|
21
|
-
margin-right: auto;
|
22
|
-
max-width: 800px;
|
23
|
-
padding: 50px;
|
24
|
-
}
|
25
|
-
|
26
|
-
nav[role="main"] {
|
27
|
-
color: grey;
|
28
|
-
font-size: 0.825em;
|
29
|
-
|
30
|
-
a { color: inherit; }
|
31
|
-
}
|
32
|
-
|
33
|
-
main {
|
34
|
-
margin-top: 2em;
|
35
|
-
}
|
36
|
-
|
37
|
-
h1, h2, h3, h4, h5, h6 {
|
38
|
-
font-size: inherit;
|
39
|
-
}
|
40
|
-
|
41
|
-
a {
|
42
|
-
color: $col1;
|
43
|
-
}
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
/* action lists */
|
48
|
-
ul.actions {
|
49
|
-
list-style: none;
|
50
|
-
padding-left: 0;
|
51
|
-
li {
|
52
|
-
display: inline-block;
|
53
|
-
margin-right: 0.5em;
|
54
|
-
}
|
55
|
-
}
|
56
|
-
|
57
|
-
|
58
|
-
/* buttons */
|
59
|
-
button, a.button {
|
60
|
-
display: inline-block;
|
61
|
-
line-height: 2em;
|
62
|
-
padding: 0 1em;
|
63
|
-
border-radius: 2px;
|
64
|
-
background-color: $col1;
|
65
|
-
color: white;
|
66
|
-
text-decoration: none;
|
67
|
-
font-size: 0.825em;
|
68
|
-
border: none;
|
69
|
-
cursor: pointer;
|
70
|
-
|
71
|
-
&.button-grey {
|
72
|
-
background-color: lightgrey;
|
73
|
-
color: dimgrey;
|
74
|
-
}
|
75
|
-
|
76
|
-
&.button-red {
|
77
|
-
background-color: tomato;
|
78
|
-
}
|
79
|
-
}
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
/* forms */
|
86
|
-
label {
|
87
|
-
display: block;
|
88
|
-
font-weight: bold;
|
89
|
-
abbr { color: grey; text-decoration: none !important }
|
90
|
-
}
|
91
|
-
|
92
|
-
input, textarea, select {
|
93
|
-
font: inherit;
|
94
|
-
}
|
95
|
-
|
96
|
-
input.string, input.password, input.email, textarea {
|
97
|
-
width: 100%;
|
98
|
-
padding: 5px;
|
99
|
-
border: 1px solid lightgrey;
|
100
|
-
}
|
101
|
-
|
102
|
-
input[type="submit"] {
|
103
|
-
@extend button;
|
104
|
-
}
|
105
|
-
|
106
|
-
.input.field_with_errors {
|
107
|
-
input, textarea { border-color: crimson }
|
108
|
-
}
|
109
|
-
|
110
|
-
textarea {
|
111
|
-
height: 7em;
|
112
|
-
}
|
113
|
-
|
114
|
-
textarea#post_body {
|
115
|
-
height: 18em;
|
116
|
-
}
|
117
|
-
|
118
|
-
.input {
|
119
|
-
margin: 1em 0;
|
120
|
-
}
|
121
|
-
|
122
|
-
.error, .help-block {
|
123
|
-
color: crimson;
|
124
|
-
font-size: 0.825em;
|
125
|
-
}
|
126
|
-
|
127
|
-
|
128
|
-
/* stupid non-UJS link forms */
|
129
|
-
|
130
|
-
form.link {
|
131
|
-
display: inline;
|
132
|
-
}
|
133
|
-
|
134
|
-
/* post specific */
|
135
|
-
|
136
|
-
article.post {
|
137
|
-
margin: 4em 0;
|
138
|
-
|
139
|
-
.meta {
|
140
|
-
color: lightgrey;
|
141
|
-
font-size: 0.825em;
|
142
|
-
|
143
|
-
a {
|
144
|
-
color: inherit;
|
145
|
-
text-decoration: none;
|
146
|
-
&:hover {
|
147
|
-
text-decoration: underline;
|
148
|
-
}
|
149
|
-
}
|
150
|
-
}
|
151
|
-
|
152
|
-
h1 {
|
153
|
-
font: 44px "EB Garamond", serif;
|
154
|
-
color: #555;
|
155
|
-
}
|
156
|
-
|
157
|
-
h2 {
|
158
|
-
color: $col2;
|
159
|
-
}
|
160
|
-
}
|