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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 912db5fb0467b2ea17535d27a16f7d5cae9c4844
4
- data.tar.gz: bc120fb8c0db94fe25f9894183c2ac784c8c7723
3
+ metadata.gz: aaa79d7d4b6d42abb898e01b65d8628910b116c0
4
+ data.tar.gz: 28642fba892e47a24b141d9aaeb8d0e4851947ad
5
5
  SHA512:
6
- metadata.gz: 2f00d281c3fc731e97877ee6c091d38a5589ed3ff6bcddc0301f6b5b4a78a1b6357585af2facbbe314c2134233e2e349108d789e34c75e11f502e9617d5a58f2
7
- data.tar.gz: 2c054331bd42b2c1fc898694ec1b9446d8fa04d8e53f728feaff8ba13885c27e6ac0d22e738f9191998e47619c46309e8820deccf53c40b2e08c9d4ae80f4d9d
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
- #### Key Features:
8
+ #### Links:
9
9
 
10
- - Generate a static website from a source directory!
11
- - Apply any number of transformations on files!
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
- **Note**: by default, both the `build` and `serve` commands assume `./site/` to be the source directory and `./_build/` to be the export directory. Please refer to `flutterby help` to see how you can override these.
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
- ## Notes
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
- When a `_layout` file is available in the same folder as the rendered page, 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.
26
+ #### Installation & Basic Usage:
83
27
 
84
- #### Extending views:
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
- #### Writing Ruby nodes:
31
+ #### Contributing to Flutterby's Development:
89
32
 
90
- When a file has a `.rb` filter extension, the contained Ruby code will be evaluated against the Node instance. This allows you to build Ruby-based nodes. These nodes can do some powerful things, like creating other "virtual" nodes on the fly. I'm using this technique for the [archives on my blog](https://github.com/hmans/hmans_me/tree/master/site/archive).
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
- ## License
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
@@ -82,6 +82,7 @@ module Flutterby
82
82
  say color("🏗 Creating a new Flutterby project in #{path}...", :bold)
83
83
  directory("new_project", path)
84
84
  chmod("bin/flutterby", 0755)
85
+ chmod("bin/rake", 0755)
85
86
  in_root { bundle_install }
86
87
  end
87
88
 
@@ -8,29 +8,31 @@ require 'flutterby/markdown_formatter'
8
8
 
9
9
  module Flutterby
10
10
  module Filters
11
- def self.apply!(input, view:)
11
+ extend self
12
+
13
+ def apply!(input, filters, view:, &blk)
12
14
  # Apply all filters
13
- view.node.filters.inject(input) do |body, filter|
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}' for #{view.node.url}"
23
+ Flutterby.logger.warn "Unsupported filter '#{filter}'"
22
24
  body
23
25
  end
24
26
  end
25
27
  end
26
28
 
27
- def self.add(fmts, &blk)
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 self.tilt(format, body, options = {})
35
+ def tilt(format, body, options = {})
34
36
  default_options = {
35
37
  "erb" => { engine_class: Erubis::Auto::EscapedEruby }
36
38
  }
@@ -2,30 +2,18 @@ module Flutterby
2
2
  module Layout
3
3
  extend self
4
4
 
5
- # Determines which layouts should be applied to the view object (based on
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? view.node.layout
23
- Array(view.node.layout).each do |sel|
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 = view.node.find(sel)
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
- # Decide on a starting node for walking the tree upwards
37
- start = layouts.any? ? layouts.last.parent : view.node
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
- # Walk the tree up, collecting any layout files found on our way
40
- TreeWalker.walk_up(start) do |node|
41
- if layout = node.sibling("_layout")
42
- layouts << layout
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
 
@@ -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
- View.for(self, opts).render!
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
@@ -1,3 +1,3 @@
1
1
  module Flutterby
2
- VERSION = "0.5.2"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -3,7 +3,7 @@ require 'flutterby/layout'
3
3
 
4
4
  module Flutterby
5
5
  class View
6
- attr_reader :node, :opts
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, opts = {})
16
+ def initialize(node, locals: {})
17
17
  @node = node
18
- @opts = opts
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, *args)
56
- if expr.is_a?(Node)
57
- expr.render(*args)
58
- else
59
- find(expr).render(*args)
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)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  source "https://rubygems.org"
3
3
 
4
+ gem "rake"
4
5
  gem "flutterby", "~> <%= Flutterby::VERSION %>"
@@ -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")
@@ -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
@@ -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
 
@@ -1,6 +1,6 @@
1
1
  h1 = config.site.title
2
2
 
3
- p This is my new website! #{link_to "Find out more", "/about.html"}.
3
+ p Hooray, you now have a Flutterby-powered website! #{link_to "Find out more", "/about.html"}.
4
4
 
5
5
  h3 Latest Posts:
6
6
  == render("/blog/_list")
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.5.2
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-25 00:00:00.000000000 Z
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