flutterby 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +8 -0
- data/README.md +14 -72
- data/lib/flutterby/cli.rb +1 -0
- data/lib/flutterby/filters.rb +9 -7
- data/lib/flutterby/layout.rb +13 -23
- data/lib/flutterby/node.rb +54 -3
- data/lib/flutterby/version.rb +1 -1
- data/lib/flutterby/view.rb +12 -34
- data/lib/templates/new_project/Gemfile.tt +1 -0
- data/lib/templates/new_project/Rakefile +14 -0
- data/lib/templates/new_project/bin/rake +17 -0
- data/lib/templates/new_project/site/{_layout.slim → _layout.html.slim} +0 -0
- data/lib/templates/new_project/site/about.html.md +1 -1
- data/lib/templates/new_project/site/blog/{_layout.slim → _layout.html.slim} +0 -0
- data/lib/templates/new_project/site/blog/hello-world.html.md.tt +2 -2
- data/lib/templates/new_project/site/index.html.slim +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aaa79d7d4b6d42abb898e01b65d8628910b116c0
|
4
|
+
data.tar.gz: 28642fba892e47a24b141d9aaeb8d0e4851947ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6cb96a3e41dd21a7a0903ba6bd3b3d5f47ab30d2d6aff21d57385dc2dfe9e8b1d408e3d2f35b08d3d55ff389a71b5d5924ae29ae94d778ffa8a8f5e20fc4570
|
7
|
+
data.tar.gz: e65316a8cee9c3c93244491c801c5582f1be68ca7df225e976d3ac5855616d7d854c603b969ebd6bc4b4eba520626e96d4a998d06b00118abd3b8609397580c5
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Version History
|
2
2
|
|
3
|
+
### 0.6.0 (2017-01-26)
|
4
|
+
|
5
|
+
- **NEW:** Within a view context, you can now invoke `render(node, as: "foo")`, and it will use a `_foo` partial in the same folder as `node`, passing `node` as a `foo` local. This allows you to easily apply decorator partials to nodes.
|
6
|
+
- **NEW:** When invoking `Node#render`, you now have additional control over the layout behavior through the `layout` argument. Like before, when `true`, the default page layouts will be applied; when `false`, no layout will be applied whatsoever; but now you can also pass one or more nodes (or node selectors) that will be applied as layouts.
|
7
|
+
- **BREAKING:** If you want to pass locals to `render`, you now need to use the `locals:` key. Example: `node.render(locals: { foo: "bar" })`
|
8
|
+
- **IMPROVED:** The new project template has received some minor improvements, including a `Rakefile` containing an example `deploy` task.
|
9
|
+
|
10
|
+
|
3
11
|
### 0.5.2 (2017-01-25)
|
4
12
|
|
5
13
|
- **NEW:** Just like `find`, there is now also a `find!` that will raise an exception when the specified node could not be found.
|
data/README.md
CHANGED
@@ -5,93 +5,35 @@
|
|
5
5
|
[![Gem Version](https://badge.fury.io/rb/flutterby.svg)](https://badge.fury.io/rb/flutterby) [![Build Status](https://travis-ci.org/hmans/flutterby.svg?branch=master)](https://travis-ci.org/hmans/flutterby) [![license](https://img.shields.io/github/license/hmans/flutterby.svg)](https://github.com/hmans/flutterby/blob/master/LICENSE.txt) ![Status](https://img.shields.io/badge/status-active-brightgreen.svg)
|
6
6
|
|
7
7
|
|
8
|
-
####
|
8
|
+
#### Links:
|
9
9
|
|
10
|
-
-
|
11
|
-
-
|
12
|
-
- Built-in support for Markdown, Sass, Erb, Slim and more!
|
13
|
-
- Extremely easy to extend with new transformation filters!
|
14
|
-
- Sprinkle your site with Ruby code that can interact with your site's pages and data!
|
15
|
-
|
16
|
-
#### Recommended Reading:
|
17
|
-
|
18
|
-
- [Blog post introducing Flutterby](http://hmans.io/posts/2017/01/11/flutterby.html)
|
19
|
-
- [New project template](https://github.com/hmans/flutterby/tree/master/lib/templates/new_project) (example code)
|
20
|
-
- [Code Reference Documentation](http://www.rubydoc.info/github/hmans/flutterby)
|
10
|
+
- [Official Flutterby Website](http://www.flutterby.run/)
|
11
|
+
- [Flutterby Documentation](http://www.flutterby.run/docs/) and [Reference](http://www.rubydoc.info/github/hmans/flutterby)
|
21
12
|
- [Version History](https://github.com/hmans/flutterby/blob/master/CHANGES.md)
|
22
13
|
- [Issues/Roadmap](https://github.com/hmans/flutterby/issues)
|
23
|
-
- [Sites built with Flutterby](https://github.com/hmans/flutterby/wiki/Sites-built-with-Flutterby) (add yours!)
|
24
|
-
|
25
|
-
|
26
|
-
## Installation & Basic Usage
|
27
|
-
|
28
|
-
Flutterby is distributed as a RubyGem, so let's install it first:
|
29
|
-
|
30
|
-
gem install flutterby
|
31
|
-
|
32
|
-
This will install a `flutterby` executable on your system. Let's use it to create a new project:
|
33
|
-
|
34
|
-
flutterby new mysite
|
35
|
-
cd mysite
|
36
|
-
|
37
|
-
The new project template serves as a simple starting point for new projects. Let's compile it into a static site:
|
38
|
-
|
39
|
-
flutterby build
|
40
|
-
|
41
|
-
Flutterby comes with a local development server that will automatically pick up changes you make to your files:
|
42
|
-
|
43
|
-
flutterby serve
|
44
14
|
|
45
|
-
|
15
|
+
#### Examples:
|
46
16
|
|
17
|
+
- [Sites built with Flutterby](https://github.com/hmans/flutterby/wiki/Sites-built-with-Flutterby) (add yours!)
|
18
|
+
- [New project template](https://github.com/hmans/flutterby/tree/master/lib/templates/new_project/site) (used with `flutterby new`)
|
19
|
+
- [Source of hmans.io](https://github.com/hmans/hmans_me/tree/master/site), the Flutterby main author's blog
|
47
20
|
|
21
|
+
#### Blog Posts:
|
48
22
|
|
49
|
-
|
50
|
-
|
51
|
-
### How does Flutterby work?
|
52
|
-
|
53
|
-
#### The Basics:
|
54
|
-
|
55
|
-
Flutterby reads a _source directory_ and writes a static website into a _target directory_. (It can also serve a live version of your site.)
|
56
|
-
|
57
|
-
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.
|
58
|
-
|
59
|
-
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.
|
60
|
-
|
61
|
-
These filters can be anything that modifies the Ruby object. Some examples:
|
62
|
-
|
63
|
-
- Rendering Markdown to HTML
|
64
|
-
- Parsing and executing ERB, Slim, HAML and other templating engines
|
65
|
-
- Processing Sass, CoffeeScript and the likes
|
66
|
-
- Leaving the current body intact, but modifying file attributes like the generated file's extension
|
67
|
-
|
68
|
-
Filters can be chained at any length you require.
|
69
|
-
|
70
|
-
Files and folders starting with underscores (eg. `_secret.html`) will never be exported. There's a number of special files that start with this underscore -- more on that later.
|
71
|
-
|
72
|
-
#### Using Ruby in templates:
|
73
|
-
|
74
|
-
Ruby code embedded in ERB, Slim etc. templates can interact with this object graph to do funky stuff like:
|
75
|
-
|
76
|
-
- including the rendered contents of another object (ie. partials)
|
77
|
-
- query the graph for certain objects (eg. "all objects in `/posts` that have `published_at` set")
|
78
|
-
- and much more, I guess!
|
23
|
+
- [Blog post introducing Flutterby](http://hmans.io/posts/2017/01/11/flutterby.html)
|
79
24
|
|
80
|
-
#### Layout files:
|
81
25
|
|
82
|
-
|
26
|
+
#### Installation & Basic Usage:
|
83
27
|
|
84
|
-
|
28
|
+
Please refer to the [Flutterby Documentation](http://www.flutterby.run/docs/).
|
85
29
|
|
86
|
-
When a `_view.rb` file is available in the same folder as the rendered page, it will be evaluated against the current view object, allowing you to define your own view helpers. Like layouts, these will stack.
|
87
30
|
|
88
|
-
####
|
31
|
+
#### Contributing to Flutterby's Development:
|
89
32
|
|
90
|
-
|
33
|
+
Please refer to [Contributing to Flutterby](http://www.flutterby.run/docs/flutterby-development/contributing-to-flutterby.html) for details.
|
91
34
|
|
92
|
-
When a file named `_node.rb` is present, the contained code will be evaluated against _all_ nodes in the same directory. This allows you to easily extend multiple nodes with functionality. [I'm using this in the template project](https://github.com/hmans/flutterby/tree/master/lib/templates/new_project/site/blog) to add `#title` and `#date` methods to blog posts.
|
93
35
|
|
94
36
|
|
95
|
-
|
37
|
+
#### License:
|
96
38
|
|
97
39
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/flutterby/cli.rb
CHANGED
data/lib/flutterby/filters.rb
CHANGED
@@ -8,29 +8,31 @@ require 'flutterby/markdown_formatter'
|
|
8
8
|
|
9
9
|
module Flutterby
|
10
10
|
module Filters
|
11
|
-
|
11
|
+
extend self
|
12
|
+
|
13
|
+
def apply!(input, filters, view:, &blk)
|
12
14
|
# Apply all filters
|
13
|
-
|
15
|
+
filters.inject(input) do |body, filter|
|
14
16
|
meth = "process_#{filter}!"
|
15
17
|
|
16
18
|
if Filters.respond_to?(meth)
|
17
|
-
Filters.send(meth, body, view: view)
|
19
|
+
Filters.send(meth, body, view: view, &blk)
|
18
20
|
elsif template = tilt(filter, body)
|
19
|
-
template.render(view).html_safe
|
21
|
+
template.render(view, view.locals, &blk).html_safe
|
20
22
|
else
|
21
|
-
Flutterby.logger.warn "Unsupported filter '#{filter}'
|
23
|
+
Flutterby.logger.warn "Unsupported filter '#{filter}'"
|
22
24
|
body
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
27
|
-
def
|
29
|
+
def add(fmts, &blk)
|
28
30
|
Array(fmts).each do |fmt|
|
29
31
|
define_singleton_method("process_#{fmt}!", &blk)
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
33
|
-
def
|
35
|
+
def tilt(format, body, options = {})
|
34
36
|
default_options = {
|
35
37
|
"erb" => { engine_class: Erubis::Auto::EscapedEruby }
|
36
38
|
}
|
data/lib/flutterby/layout.rb
CHANGED
@@ -2,30 +2,18 @@ module Flutterby
|
|
2
2
|
module Layout
|
3
3
|
extend self
|
4
4
|
|
5
|
-
|
6
|
-
# the node it is rendering), and then applies each of these layouts in order,
|
7
|
-
# modifying the view in place.
|
8
|
-
#
|
9
|
-
def apply!(body, view:)
|
10
|
-
collect_layouts(view).inject(body) do |acc, layout|
|
11
|
-
tilt = Flutterby::Filters.tilt(layout.ext, layout.source)
|
12
|
-
tilt.render(view) { acc }.html_safe
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def collect_layouts(view)
|
5
|
+
def collect_layouts(node, list: nil, include_tree: true)
|
19
6
|
layouts = []
|
7
|
+
list ||= node.layout
|
20
8
|
|
21
9
|
# Collect layouts explicitly configured for node
|
22
|
-
if defined?
|
23
|
-
Array(
|
10
|
+
if defined? list
|
11
|
+
Array(list).each do |sel|
|
24
12
|
# If a false is explicity specified, that's all the layouts
|
25
13
|
# we're expected to render
|
26
14
|
return layouts if sel == false
|
27
15
|
|
28
|
-
if layout =
|
16
|
+
if layout = node.find(sel)
|
29
17
|
layouts << layout
|
30
18
|
else
|
31
19
|
raise "No layout found for path expression '#{sel}'"
|
@@ -33,13 +21,15 @@ module Flutterby
|
|
33
21
|
end
|
34
22
|
end
|
35
23
|
|
36
|
-
|
37
|
-
|
24
|
+
if include_tree
|
25
|
+
# Decide on a starting node for walking the tree upwards
|
26
|
+
start = layouts.any? ? layouts.last.parent : node
|
38
27
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
28
|
+
# Walk the tree up, collecting any layout files found on our way
|
29
|
+
TreeWalker.walk_up(start) do |n|
|
30
|
+
if layout = n.sibling("_layout")
|
31
|
+
layouts << layout
|
32
|
+
end
|
43
33
|
end
|
44
34
|
end
|
45
35
|
|
data/lib/flutterby/node.rb
CHANGED
@@ -330,12 +330,63 @@ module Flutterby
|
|
330
330
|
|
331
331
|
|
332
332
|
module Rendering
|
333
|
+
# Renders the node. One of the most important methods in Flutterby, which
|
334
|
+
# explains why it's wholly undocumented. Apologies, I'm working on it!
|
335
|
+
#
|
336
|
+
def render(layout: false, view: nil, extra_filters: [], locals: {}, &blk)
|
337
|
+
# If no view was specified, create a new one for this node.
|
338
|
+
view ||= View.for(self, locals: locals)
|
339
|
+
layouts = []
|
340
|
+
|
341
|
+
if layout == true
|
342
|
+
# build standard list of layouts for rendering the full page
|
343
|
+
layouts = Layout.collect_layouts(self, include_tree: page?)
|
344
|
+
elsif layout
|
345
|
+
# build list of nodes based on specified layouts
|
346
|
+
layouts = Layout.collect_layouts(self, list: layout, include_tree: false)
|
347
|
+
end
|
348
|
+
|
349
|
+
# Start rendering
|
350
|
+
output = ""
|
351
|
+
time = Benchmark.realtime do
|
352
|
+
# Apply filters
|
353
|
+
output = Filters.apply! @source.html_safe,
|
354
|
+
filters + extra_filters,
|
355
|
+
view: view, &blk
|
356
|
+
|
357
|
+
# Apply layouts
|
358
|
+
output = layouts.inject(output) do |acc, layout_node|
|
359
|
+
layout_node.render(layout: false,
|
360
|
+
view: view, extra_filters: [layout_node.ext]) { acc }
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
# Log rendering times using different colors based on duration
|
365
|
+
color = if time > 1
|
366
|
+
:red
|
367
|
+
elsif time > 0.25
|
368
|
+
:yellow
|
369
|
+
else
|
370
|
+
:green
|
371
|
+
end
|
372
|
+
|
373
|
+
logger.debug "Rendered #{url.colorize(:blue)} in #{sprintf("%.1fms", time * 1000).colorize(color)}"
|
374
|
+
|
375
|
+
output
|
376
|
+
end
|
377
|
+
|
378
|
+
|
379
|
+
|
333
380
|
# Creates a new {View} instance and uses it to
|
334
381
|
# render this node. Returns the rendered page as a string.
|
335
382
|
#
|
336
|
-
def render(opts = {})
|
337
|
-
|
338
|
-
end
|
383
|
+
# def render(opts = {}, &blk)
|
384
|
+
# render_with_view(View.for(self, opts), &blk)
|
385
|
+
# end
|
386
|
+
#
|
387
|
+
# def render_with_view(view, *args, &blk)
|
388
|
+
# NodeRenderer.render(self, view, *args, &blk)
|
389
|
+
# end
|
339
390
|
end
|
340
391
|
|
341
392
|
include Rendering
|
data/lib/flutterby/version.rb
CHANGED
data/lib/flutterby/view.rb
CHANGED
@@ -3,7 +3,7 @@ require 'flutterby/layout'
|
|
3
3
|
|
4
4
|
module Flutterby
|
5
5
|
class View
|
6
|
-
attr_reader :node, :
|
6
|
+
attr_reader :node, :locals
|
7
7
|
alias_method :page, :node
|
8
8
|
|
9
9
|
# Include ERB::Util from ActiveSupport. This will provide
|
@@ -13,35 +13,9 @@ module Flutterby
|
|
13
13
|
#
|
14
14
|
include ERB::Util
|
15
15
|
|
16
|
-
def initialize(node,
|
16
|
+
def initialize(node, locals: {})
|
17
17
|
@node = node
|
18
|
-
@
|
19
|
-
end
|
20
|
-
|
21
|
-
def render!
|
22
|
-
output = node.source.try(:html_safe)
|
23
|
-
|
24
|
-
time = Benchmark.realtime do
|
25
|
-
output = Filters.apply!(output, view: self)
|
26
|
-
|
27
|
-
# Apply layouts
|
28
|
-
if opts[:layout] && node.page?
|
29
|
-
output = Layout.apply!(output, view: self)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# Log rendering times using different colors based on duration
|
34
|
-
color = if time > 1
|
35
|
-
:red
|
36
|
-
elsif time > 0.25
|
37
|
-
:yellow
|
38
|
-
else
|
39
|
-
:green
|
40
|
-
end
|
41
|
-
|
42
|
-
logger.debug "Rendered #{node.url.colorize(:blue)} in #{sprintf("%.1fms", time * 1000).colorize(color)}"
|
43
|
-
|
44
|
-
output
|
18
|
+
@locals = locals
|
45
19
|
end
|
46
20
|
|
47
21
|
def date_format(date, fmt)
|
@@ -52,12 +26,16 @@ module Flutterby
|
|
52
26
|
str.html_safe
|
53
27
|
end
|
54
28
|
|
55
|
-
def render(expr,
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
29
|
+
def render(expr, as: nil, locals: {}, **args)
|
30
|
+
node = expr.is_a?(Node) ? expr : find(expr)
|
31
|
+
|
32
|
+
# Resolve rendering "as" specific things
|
33
|
+
if as
|
34
|
+
locals[as] = node
|
35
|
+
node = node.find!("./_#{as}.#{self.node.ext}")
|
60
36
|
end
|
37
|
+
|
38
|
+
node.render(**args, locals: locals.with_indifferent_access, **args)
|
61
39
|
end
|
62
40
|
|
63
41
|
def find(*args)
|
@@ -0,0 +1,14 @@
|
|
1
|
+
task default: [:build]
|
2
|
+
|
3
|
+
desc "Build the website"
|
4
|
+
task :build do
|
5
|
+
system "rm -rf _build/* && bin/flutterby build"
|
6
|
+
end
|
7
|
+
|
8
|
+
# This is a sample "deploy" task that will upload your
|
9
|
+
# statically generated website to your server via rsync.
|
10
|
+
#
|
11
|
+
# desc "Deploy the website"
|
12
|
+
# task deploy: [:build] do
|
13
|
+
# system "rsync -vr --del _build/* server:/path/to/website/"
|
14
|
+
# end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
#
|
4
|
+
# This file was generated by Bundler.
|
5
|
+
#
|
6
|
+
# The application 'rake' is installed as part of a gem, and
|
7
|
+
# this file is here to facilitate running it.
|
8
|
+
#
|
9
|
+
|
10
|
+
require "pathname"
|
11
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
12
|
+
Pathname.new(__FILE__).realpath)
|
13
|
+
|
14
|
+
require "rubygems"
|
15
|
+
require "bundler/setup"
|
16
|
+
|
17
|
+
load Gem.bin_path("rake", "rake")
|
File without changes
|
@@ -1,5 +1,5 @@
|
|
1
1
|
## About this site
|
2
2
|
|
3
|
-
This is a small template site [Flutterby] generated for you. You can keep using it, modify it as you wish, or get rid of everything and start from scratch. It's up to you!
|
3
|
+
This is a small template site [Flutterby] generated for you. You can keep using it, modify it as you wish, or get rid of everything within the `site/` directory and start from scratch. It's up to you!
|
4
4
|
|
5
5
|
[Flutterby]: http://www.flutterby.run
|
File without changes
|
@@ -10,8 +10,8 @@ This sample project is set up as a simple blog, but of course you can do so much
|
|
10
10
|
|
11
11
|
| `/_config.yaml` | Your site configuration. |
|
12
12
|
| `/css/styles.css.scss` | Your stylesheet. [Sass]-powered, of course! |
|
13
|
-
| `/_layout.slim` | Your global site layout. |
|
14
|
-
| `/posts/_layout.slim` | Your post-specific layout. |
|
13
|
+
| `/_layout.html.slim` | Your global site layout. |
|
14
|
+
| `/posts/_layout.html.slim` | Your post-specific layout. |
|
15
15
|
|
16
16
|
#### Recommended Reading
|
17
17
|
|
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.
|
4
|
+
version: 0.6.0
|
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-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -402,13 +402,15 @@ files:
|
|
402
402
|
- lib/templates/new_project/.gitignore
|
403
403
|
- lib/templates/new_project/Gemfile.tt
|
404
404
|
- lib/templates/new_project/README.md
|
405
|
+
- lib/templates/new_project/Rakefile
|
405
406
|
- lib/templates/new_project/bin/flutterby
|
407
|
+
- lib/templates/new_project/bin/rake
|
406
408
|
- lib/templates/new_project/site/_config.yaml
|
407
|
-
- lib/templates/new_project/site/_layout.slim
|
409
|
+
- lib/templates/new_project/site/_layout.html.slim
|
408
410
|
- lib/templates/new_project/site/_view.rb
|
409
411
|
- lib/templates/new_project/site/about.html.md
|
410
412
|
- lib/templates/new_project/site/blog/_init.rb
|
411
|
-
- lib/templates/new_project/site/blog/_layout.slim
|
413
|
+
- lib/templates/new_project/site/blog/_layout.html.slim
|
412
414
|
- lib/templates/new_project/site/blog/_list.html.slim
|
413
415
|
- lib/templates/new_project/site/blog/_view.rb
|
414
416
|
- lib/templates/new_project/site/blog/hello-world.html.md.tt
|